📜 ⬆️ ⬇️

Effective Django. Part 2


Continuing to translate articles on Django from effectivedjango.com . I stumbled upon this site while studying this framework. The information posted on this resource seemed useful to me, but since I did not find a translation into Russian anywhere, I decided to do this good deed myself. This cycle of articles, I think, will be useful for web developers who are only taking the first steps in learning Django.



Table of contents


Chapter 3. Writing a presentation ⇧


3.1. Basics of ideas


Django views get an HTTP request and return an HTTP response to the user:

Any Python object called can be a representation. The only strict and necessary requirement is that the Python object being called must accept the request object as the first argument (usually this parameter is called “ request ). This means that the minimum representation will be very simple:

 from django.http import HttpResponse def hello_world(request): return HttpResponse("Hello, World") 

Of course, like most other frameworks, Django allows you to pass arguments to a view via a URL. We will talk about this when we build our application.

3.2. General views and class views



Django 1.3 introduces class views that we will focus on in this chapter. Class views, or CBVs, can eliminate a lot of template code from your views, especially from views for editing something where you want to take different actions for GET and POST requests. Representations classes will give you the opportunity to assemble the functionality in parts. The disadvantage is that all this power entails some additional complication.
')

3.3. Representation Classes (CBV)


The minimal representation, implemented as CBV, is derived from the View doc class and implements the supported HTTP methods. Below is a very small representation of “Hello, World” written by us earlier, but executed as a class-representation:

 from django.http import HttpResponse from django.views.generic import View class MyView(View): def get(self, request, *args, **kwargs): return HttpResponse("Hello, World") 

In class view, HTTP method names are mapped to class methods. In our case, we defined a handler for a GET request using the get class method. In the same way as when implemented by a function, this method takes the request object as the first parameter and returns an HTTP response.

Note: Valid Signatures
You may notice several additional arguments in the function signature compared to the representation we wrote earlier, in particular *args and **kwargs . CBVs were first created to make Django’s “generic” representations more flexible. The implication was that they would be used in a variety of different contexts, with potentially different arguments extracted from the URL. Being engaged in the last year of writing class representations, I continue to write them using valid signatures, and each time this turns out to be useful in unexpected situations.

3.4. Display a list of contacts


We will start with a view that displays a list of contacts from the database.

The basic implementation of the view is very short. We can write it all in just a few lines. To do this, in the views.py file of our contacts application, type the following code:

 from django.views.generic import ListView from contacts.models import Contact class ListContactView(ListView): model = Contact 

The ListView doc class, from which we inherited the view, is itself composed of several impurities that implement some behavior. This gives us great power with a small amount of code. In our case, we specified a model ( model = Contact ), which will force this view to list all contacts of the Contact model from our database.

3.5. Define URLs


The URL configuration (URLconf) tells Django how to find your Python code at the request address. Django looks for a URL configuration that is defined in the urlpatterns variable of the urlpatterns file.

Let's add to the addressbook/urls.py URL template for our view that displays a list of contacts:

 from django.conf.urls import patterns, include, url import contacts.views urlpatterns = patterns('', url(r'^$', contacts.views.ListContactView.as_view(), name='contacts-list',), ) 


While the urlpatterns variable must be defined, Django also allows you to define several other values ​​( variables ) for exceptions. These values ​​include handler403 , handler404 , and handler500 , which tell Django which view to use in case of an HTTP error. For more information, see the Django URL configuration documentation .

Note: Error importing URL configuration
Django loads the URL configuration very early during startup and tries to import modules found inside. If at least one of the import operations fails, the error message may be a little confusing. If your project has stopped working due to an import error, try importing the URL configuration in an interactive shell. This allows, in most cases, to determine where the problem occurred.

3.6. Creating a Template


Now, by defining the URL for our contact list view, we can try it. Django includes a server suitable for development purposes, which you can use to test your project:

 (venv:tutorial)$ python ./manage.py runserver 0.0.0.0:8080 Validating models... 0 errors found November 04, 2014 - 15:25:05 Django version 1.6.7, using settings 'addressbook.settings' Starting development server at http://0.0.0.0:8080/ Quit the server with CONTROL-C. 

If you visit http: // localhost: 8080 / in your browser, you still get a TemplateDoesNotExists error
Translator's Note:
localhost if you start the browser from the same host where the server is running. If your server is running on another host (like mine) - instead of localhost specify the IP address of this host (in my case it is 192.168.1.51 ).


Most of the common Django views (here, the ListView we used) have a predefined template name that they expect to find. We can see in this error message that the view expected to find a template file named contact_list.html , which was derived from the model name. Let's create such a template.

By default, Django searches for templates in applications, as well as in the directories specified in settings.TEMPLATE_DIRS . General views expect patterns to be found in the application directory (in this case, in the contacts directory), and the file name will contain the model name (in this case, the expected file name: contact_list.html ). This comes in handy when you develop applications for reuse: the user of your application can create their own templates that will override the default templates and they will be stored in a directory directly associated with the application.

Translator's Note:
Django expects the template to be located at _/templates/_/_

For our purposes, however, we do not need an additional layer from directory structures, so we explicitly define the template using the template_name property of our class view. Let's add one line to views.py :

 from django.views.generic import ListView from contacts.models import Contact class ListContactView(ListView): model = Contact template_name = 'contact_list.html' 

Create the templates subdirectory in the contacts directory (this is the directory with the application), and in it create the contact_list.html template contact_list.html :

 <h1>Contacts</h1> <ul> {% for contact in object_list %} <li class="contact">{{ contact }}</li> {% endfor %} </ul> 

When you re-open (or refresh) the http: // localhost: 8080 / page in your browser, you will need to see at least one contact that we created earlier through an interactive shell.



3.7. Create contacts


Adding information to the database through an interactive shell takes too much time, so let's create a view to add new contacts.

As with the list of contacts, we use one of the common concepts of Django. In the views.py file we will add a few lines:

 from django.core.urlresolvers import reverse from django.views.generic import ListView from django.views.generic import CreateView from contacts.models import Contact class ListContactView(ListView): model = Contact template_name = 'contact_list.html' class CreateContactView(CreateView): model = Contact template_name = 'edit_contact.html' def get_success_url(self): return reverse('contacts-list') 

Translator's Note:
If you are using Django version> = 1.7, then you can add an additional field to the CreateContactView class:

  fields = ['first_name', 'last_name', 'email'] 

This is not necessary, but since Django 1.7, the disuse of this field in classes with automatic generation of forms has been declared obsolete (they will tell you about this when running the tests). If you do not specify it, then all fields will be used in the edit form, but from Django 1.8 version this behavior will be removed.

Most of the common submissions that work with forms have the concept of a “successful URL”: such a URL where the user is redirected after the form has been successfully processed. All submissions processing forms adhere to the practice of POST-redirect-GET to accept changes, so updating the final page does not resend the form. You can implement this concept as a class property, or override the get_success_url() method, as we did. In our case, we use the reverse function to calculate the URL of the contact list.

Note: Context variables in class views
The set of variables available in a template when it is displayed is called a context . Context is a combination of data from the view and information from the context processors .
When you use built-in generic views, it’s not at all obvious what variables are available in context. Over time, you will discover that their names (provided by common concepts into the context of the template) are fairly consistent — form , object and object_list are often used — although this will not help you at the beginning of the path. Fortunately, the documentation on this issue has become prettier since Django 1.5.
In class get_context_data() method is used to add information to the context. If you overload this method, you will need to enable **kwargs and call the superclass.

The template for adding a contact will be a bit more complicated than the template for the contact list, but not too much. Our contacts/templates/edit_contact.html will look something like this:

 <h1>Add Contact</h1> <form action="{% url "contacts-new" %}" method="POST"> {% csrf_token %} <ul> {{ form.as_ul }} </ul> <input id="save_contact" type="submit" value="Save" /> </form> <a href="{% url "contacts-list" %}">back to list</a> 

A few new pieces of note:

Source: https://habr.com/ru/post/242261/


All Articles