Good day, dear readers! Not so long ago, I published the
first part of an article on this topic. I want to once again thank all users who expressed constructive criticism, thanks to which the examples in the article managed to lead to an almost perfect look. At the same time, I realized that this format of the presentation of the material is inefficient: we considered only a couple of methods implemented in Class Based View (hereinafter referred to as CBV). In the second part, I decided to rework the feed and then try to describe the maximum possible number of methods presented in the API. I will try, also, to cover those methods that were missed in the first part. I really hope for the constructive support of readers and I hope that in the future we will have a productive dialogue, as a result of which the article will become even more informative.
Part 1 ,
Part 2 ,
Part 3 ,
Part 4Quick links to find methods
dispatchget_context_dataget_template_namesget_context_object_namegetpostputdeleteheadoptionstracerender_to_responseget_queryset')
Quick links to find attributes
objecttemplate_nametemplate_name_suffixcontext_object_namehttp_method_namesquerysetmodelgeneral information
To begin with, we will decide what these CBVs are, whether they are needed and where they should be used. Probably it should be emphasized that the developers of Django do not provide us with much choice. Most likely already with version 1.4 (judging by the trunk) generic views will be declared as deprecated, and in one of the next versions they may refuse to use them at all. Therefore, I decided, as is often the case, not to postpone the study indefinitely, but to start working with CBV right now. Actually, in the absence of detailed information, this article will be written on personal observations.
So, CBV allows us to use the features of object-oriented programming when designing our mappings. Now we can implement base classes that carry certain functionality and use them as impurities (mixins) for our maps.
All mappings have an entry point, which can be considered a constructor as well.
dispatch . This method takes a request argument, which is an instance of the HttpRequest object, as the first argument. This is its main similarity with function based views. This method also accepts all variables passed to the mapping as named and unnamed positional arguments (* args / ** kwargs). Consider a couple of examples of working with this method.
The dispatch method is the best place to use decorators. To specify them, you must use the method_decorator decorator implemented in django. Suppose we need to provide access to a certain list of objects only for authorized users:
from django.contrib.auth.decorators import login_required from django.utils.decorators import method_decorator from django.views.generic import ListView class PostList(ListView): model = Post @method_decorator(login_required()) def dispatch(self, request, *args, **kwargs): return super(PostList, self).dispatch(request, *args, **kwargs)
Keep in mind that the dispatch method must return a link to the parent dispatcher to work correctly. Otherwise, the correct transfer of control will not occur.
Very often there is a need to transfer to our display an additional context. Suppose we have an article, the view of which we implement using the DetailView class. We also need to get a list of comments on this article. In my opinion the method
get_context_data
will be the best point to implement the required functionality.
from django.views.generic.detail import DetailView from models import Post, Comment class PostDetail(DetailView): model = Post def get_context_data(self, **kwargs): context = super(PostDetail, self).get_context_data(**kwargs) context['comments'] = Comment.objects.filter(post=self.object, is_delete=False).order_by('-created_at') return context
Looking ahead a bit, I’ll clarify that accessing the current object when implementing the DetailView can be done through the attribute
object .
If we want to find out (or set) a name for a template that will use our display, then we need to pay attention to the method
get_template_names . This method returns a list of template names that Django will try to use in the order they are specified. By default, the template specified in the attribute will have the highest priority.
template_name of our object. If this attribute is not specified, Django will try to use the "application_name / object_name_prefix" template. For example, for the content application and the post model, this path will look like "content / post_prefix.html". The prefix is set using the attribute
template_name_suffix , or use the default prefix for this type of display. For example, for ListView the prefix is named "_list", for DetailView "_detail". If we just want our display to use the template we want, we just need to specify it using the template_name attribute. Overriding the get_template_names method may be required if we need to build a template name according to our own rules.
It is often necessary to change the name of the variable under which our object (or list of objects) is available in the template. The method responsible for this functionality is named
get_context_object_name . This method takes an object (or a list of objects) as an argument. In the case of a single object, the variable name in the template by default will be the name of the object itself. In the case of a list of objects, this will be the name of the object with the suffix _list. For example, for the Post object and the variable names will be post and post_list for a single object and a list of objects, respectively. We can explicitly specify the name of a variable if we assign its value to an attribute.
context_object_name .
Imagine that we are faced with the task of implementing a RESTful application, CBV provides an exhaustive set of methods for their implementation. To implement the application through a certain method, we only need to override the method of the same name in our display. List of available methods:
get ,
post ,
put ,
delete ,
head ,
options ,
trace . Working with forms is simplified many times, because we can use the get method to display our form, and transfer its processing to the post method. Need to add any additional specific http method? No problem, just add the attribute.
http_method_names , which contains a list of names of the available methods, and then define the method of the same name in its display. All http methods must return an HttpResponse object. If we need to render our display template, then we can call the method in the above http methods for this
render_to_response . This method has not only the same name as its functional counterpart, but also similar functionality.
class PostDetail(DetailView): model = Post def get(self, request, **kwargs): return self.render_to_response(self.get_context_data(), **kwargs)
The method takes the required context as an argument.
Before you display information in the template, we need to get it. The method will help us in this.
get_queryset , whose task is to return a QuerySet object. By default, this method returns an attribute
queryset if it is defined, or a list of all objects of the model, which is specified in the attribute
model . We can override this method to suit our needs.
class PostList(ListView): model = Post def get_queryset(self): qs = Post.objects.filter(is_delete=False).order_by('-created_at') if not self.request.user.is_authenticated(): return qs.exclude(is_private=True) return qs
In this part, I have tried to cover, if possible, all the basic (available in all types of CBV) methods. If I missed something, please inform me and I will add the article. The following parts will include a description of the features of individual types of CBV. I will begin, perhaps, with the description of the ListView and DetailView methods. I would be very happy if my articles help people in finding information. Thank you for reading this article :)