Open-Source: Week 2
Hi and welcome everyone to another blog. This week I would like to discuss my experience of finding an open-source project, what things did I face, and how did I manage to find a project.
My experience so far
As you may know, finding an open-source project to work on is not a trivial task, it is necessary to dedicate enough time to go through the projects and identify whether you will be able to solve an issue, and how much time will it take you to solve that issue.
It is very important to learn to identify how much time will take you to solve different problems so in the future you can decide and negotiate how many days do you need to do something.
That’s one of the skills I have been practicing. In addition to that, I faced other problems, I felt that I wasted too much time trying to find the correct project. I would recommend you not to overthink what project you want to collaborate on, once you understand the project and the issue, go ahead and try to collaborate. If you wait too much time, someone else might comment before and you will end up having to search again for a project.
Another thing I recommend is to pay attention to your communication skills. Open-source is about collaboration, learn how to communicate so your collaborations will improve.
Communication includes how you request to work on an issue, how do you follow up the conversation with the admin of the project, how do you ask questions and how do you create your pull requests.
One last thing on this, all projects will require tests to prove that your changes are ok, learn how the project implements testing, and create the necessary tests for you.
I also share a list of good links and resources to find your first contribution:
The one that I liked the most:
Good-first-issue:
First-timers only:
- https://github.com/search?p=4&q=label%3Afirst-timers-only+is%3Aissue+is%3Aopen&type=Issues
- https://github.com/MunGell/awesome-for-beginners/blob/master/README.md#python
More:
Questions about Django Framework
I also worked on solving 2 questions about Django, due to the fact that I tried to make a contribution to the project. The contribution I worked on was about adding a repr() representation method to some classes in the Django project. I submit a pull request with the edited class and also with the test for that change.
So I made 2 changes: One for editing a file where I added the repr() method to a class and second I created a file for testing that change. The tests worked and everything was ok, except for the fact that they request to add the repr() method to some specific classes, not the one that I worked on, so they couldn’t accept my pull request.
This gave me a lesson, so in future contributions, I won't make this mistake again.
Question 1: How does a Django-admin command work?
What are Django-admin commands?
Django admin is the command-line tool that Django uses for administrative tasks. The possible commands that we can run are explained in this list. At the same time, commands have options that we can use to interact with them. A Django command and option would look like this:
$ django-admin <command> [options]
What is happening internally in Django to use these commands?
Django has a base command class from where all other commands derive. Therefore, all commands predefined in Django are subclasses that inherit the base command class along with its methods and attributes.
The normal flow inside the code works as follows:
- Django-admin or manage.py loads the command class and calls its run_from_argv() method.
- The run_from_argv() method calls create_parser() to get an ArgumentParser for the arguments, parses them, performs any environment changes requested by options like pythonpath, and then calls the execute() method, passing the parsed arguments.
- The execute() method attempts to carry out the command by calling the handle() method with the parsed arguments; any output produced by handle() will be printed to standard output and, if the command is intended to produce a block of SQL statements, will be wrapped in BEGIN and COMMIT.
- If handle() or execute() raised any exception (e.g. CommandError), run_from_argv() will instead print an error message to stderr. Thus, the handle() method is typically the starting point for subclasses; many built-in commands and command types either place all of their logic in handle(), or perform some additional parsing work in handle() and then delegate from it to more specialized methods as needed.
A command is normally run using:
python manage.py [my_command]
In every command, the method handle carries the necessary logic to make the command work. It is useful to know that following this structure you can create custom commands to automate tasks and help you in several things.
In case you would like to create a command the way of organizing your files is:
- Create a directory called management inside your app.
- Inside management, create a child directory called commands.
- Finally, create a python file with the name of your command.
Following that structure, it is possible to automate database maintenance, admin reporting, and periodic app-specific tasks.
Question 2: How do responses work in Django?
What are requests?
A Request is a request made by the client to the server. Any URL that gets searched is a request. Request objects also give information to the server through the forms we fill, and the images we upload to the server. When we upload this information, it is transferred as attributes of the Request object.
What are responses?
The Response objects usually contain HTML, CSS, JavaScript, images, video files, etc. There are other files as well, which can be served by the server as a response. Response objects also have various parts.
How does Django do this?
Django uses request and response objects to pass state through the system.
Django can be considered as an application on the server. Its main task is to process the request received by the server. Then it calls functions and provides a response.
- When the Django server starts, the first thing it loads after settings.py is middlewares.
- Once our request is processed by the middlewares it is passed to the URL Router. The URL router simply extracts the URL from the request and will try to match it to defined URLs.
- When we get a matching URL, the corresponding view function is called. The view function will get various attributes and other URL parameters. Also, the view function will be able to access files from the requests. These Requests are considered to be HttpRequest class objects.
- The requests module is a Python module that provides various methods for Request objects.
- The response is given in the form of HttpResponse. The response is not limited to that. The Response can be PDF, JSON, CSV. That is one of the features of Django. It provides built-in support to provide responses of various types.
- When the response is a render, it will look for the HTML. The HTML page to be the server is processed by Django Templating Engine. Once that completes, Django simply sends the files as any server would. That response will contain the HTML and other static files.
How does Django do this internally?
In contrast to HttpRequest objects, which are created automatically by Django, HttpResponse objects are your responsibility. Each view you write is responsible for instantiating, populating, and returning an HttpResponse.
Django includes a number of HttpResponse subclasses that handle different types of HTTP responses. Below I described the most important classes that I found in the code in django/http/response.py.
- The HttpResponse class inherits HttpResponseBase. HttpResponse allows you to create a response with a string as content.
>>> from django.http import HttpResponse
>>> response = HttpResponse("Here's the text of the Web page.")
>>> response = HttpResponse("Text only, please.", content_type="text/plain")
>>> response = HttpResponse(b'Bytestrings are also accepted.')
>>> response = HttpResponse(memoryview(b'Memoryview as well.'))
- Django uses different classes to create responses for different status codes such as 301, 302, 304, 400, 404, 403, 405, 410, and 500.
- If Django doesn’t provide a response class you need, it can be created with the help of http.HTTPStatus from python modules. An example from the documentation:
from http import HTTPStatus
from django.http import HttpResponseclass HttpResponseNoContent(HttpResponse):
status_code = HTTPStatus.NO_CONTENT
- The JsonResponse class inherits HttpResponse. This class consumes data to be serialized to JSON. A basic example from the documentation is:
from django.http import JsonResponse
>>> response = JsonResponse({'foo': 'bar'})
>>> response.content
b'{"foo": "bar"}'
- The StreamingHttpResponse class inherits HttpResponseBase. This class allows you to create a response with an iterator as content. From the documentation, we can understand that this class serves to stream a response from Django to the browser. You might want to do this if generating the response takes too long or uses too much memory. For instance, it’s useful for generating large CSV files.
- The FileResponse class inherits StreamingHttpResponse. This class serves to stream HTTP responses also but is optimized for binary files. An example from the documentation:
>>> from django.http import FileResponse
>>> response = FileResponse(open('myfile.png', 'rb'))
Thank you for reading my blog, see you soon!