Said the end, immediately began to write the advanced chapter.

This chapter will not add new functionality to the blog project, but it is just as important because we will learn about the high-powered class-based view.

What is a class view

All views written in the previous section are function-based, def; The class view is class-based, class.

Those of you with programming background know that classes are very important concepts in object-oriented technology. Classes with complex data and functions can easily pass their own features to another class through inheritance, thus realizing efficient reuse of code.

Class views have the following advantages over previous functional views:

  • The HTTP method (GET.POSTEtc.) related code can be passedmethodsRather thanConditional branchTo organize the
  • Object-oriented techniques such as mixins (multiple inheritance) can be used to decompose code into reusable components

What does it all mean? Feel it through an example.

The list of

Functions and classes

Suppose we have a list of blogs with both GET and POST methods, and the view function looks something like this:

views.py

def article_list_example(request):
    """ Processing GET requests """
    if request.method == 'GET':
        articles = ArticlePost.objects.all()
        context = {'articles': articles}
        return render(request, 'article/list.html', context)
Copy the code

In the class view, it looks like this:

views.py

from django.views import View

class ArticleListView(View):
    """ Processing GET requests """
    def get(self, request):
        articles = ArticlePost.objects.all()
        context = {'articles': articles}
        return render(request, 'article/list.html', context)
Copy the code

Essentially, class-based views allow you to use different class instance methods (def get() above) to respond to different HTTP request methods without using conditional branching code. The advantage of this approach is that different HTTP requests are separated into separate functions, making logic clearer and easier to reuse.

Note that because Django’s URL parser wants to send requests to functions rather than classes, the class view has an as_view() method that returns a function to be called when a request matches a URL with an association pattern.

That is, the view function’s URL was originally written as:

urls.py

...
urlpatterns = [
    path('... ', views.article_list_example, name='... '),]Copy the code

The url of the class view should be rewritten as:

urls.py

...
urlpatterns = [
    path('... ', views.ArticleListView.as_view(), name='... '),]Copy the code

General view

Features like lists are common in Web development, where developers write almost the same list logic over and over again. Django’s generic view was developed to alleviate this pain. They abstract common patterns so you can quickly write common views without writing too much code.

So rewrite the list generic view as follows:

views.py

from django.views.generic import ListView

class ArticleListView(ListView):
    The name of the context
    context_object_name = 'articles'
    # query set
    queryset = ArticlePost.objects.all()
    # template location
    template_name = 'article/list.html'
Copy the code

The list inherits its parent class, ListView, and gets the methods that handle the list, so as you can see, we didn’t write any logic in our own class, just a few variables.

Dynamic filtering

Filtering specific content from a database is also a common requirement. How does the class view work?

You can think of, the above code to the queryset = ArticlePost. Objects. The filter ().

A better alternative is to override the get_queryset() method:

views.py

...

class ArticleListView(ListView):
    context_object_name = 'articles'
    template_name = 'article/list.html'

    def get_queryset(self):
        """ Query Set ""
        queryset = ArticlePost.objects.filter(title='Python')
        return queryset
Copy the code

In this example, only articles with the title “Python” are filtered out, which is overqualified; But you can write complex federated query logic in get_queryset() for personalized functionality.

Add context

When designing the blog list, we return the context to the template in addition to articles, as well as a lot of additional information, such as order and search; The same can be done in the class view by rewriting the get_context_data() method:

views.py

...

class ArticleListView(ListView):.def get_context_data(self, **kwargs):
        Get the original context
        context = super().get_context_data(**kwargs)
        # Add new context
        context['order'] = 'total_views'
        return context
Copy the code

In addition, there are other methods that can be overridden by ListView. For more information, see the official documentation here

With class

A Mixin is a class that has some functionality that is not usually used in isolation and provides inherited functionality from other classes. Well, it literally means “blend in.”

The get_context_data() method already exists in the previous list view. If you need to write a list of videos that function similarly, you can use mixins to avoid repetitive code:

views.py

...

class ContextMixin:
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['order'] = 'total_views'
        return context

class ArticleListView(ContextMixin, ListView):.class VideoListView(ContextMixin, ListView):.Copy the code

By mixing, both subclasses get the get_context_data() method.

Syntactically, mixin is implemented through multiple inheritance. The difference is that mixins are added to subclasses as features, not as superclasses.

In fact, Django comes with a number of generic Mixin classes that implement most of the common functions. See the official documentation here

Details page

Since lists have a common view, the detail page also has a corresponding DetailView.

Write a simple detail page using the class view:

views.py

from django.views.generic import DetailView

class ArticleDetailView(DetailView):
    queryset = ArticlePost.objects.all()
    context_object_name = 'article'
    template_name = 'article/detail.html'
Copy the code

Then configure the URL:

urls.py

...
urlpatterns = [
    # detail class view
    path('detail-view/<int:pk>/', views.ArticleDetailView.as_view(), name='... '),]Copy the code

Note that the argument passed here is not id but PK, which is required by the view (slug can also be passed). Pk is the primary key of the table, which is actually the ID by default.

That’s it!

You can also add any other functionality, such as counting page views:

views.py

...
class ArticleDetailView(DetailView):.def get_object(self):
        """
        获取需要展示的对象
        """
        Call the parent method first
        obj = super(ArticleDetailView, self).get_object()
        # Views +1
        obj.total_views += 1
        obj.save(update_fields=['total_views'])
        return obj
Copy the code

The get_object() method gets the object to display. The parent method is called to assign the object to the obj variable, and then the pageviews are counted, and finally the object is returned. It is equivalent to “plugging” one’s own logic into the original method.

For more details about DetailView, see here: official documentation

The editor

In addition to presenting information, generic views also contain classes for editing data, such as CreateView, UpdateView, and DeleteView.

If you want to create a new article, the view might look like this:

views.py

from django.views.generic.edit import CreateView

class ArticleCreateView(CreateView):
    model = ArticlePost
    
    fields = '__all__'
    Fill in only a few fields, such as:
    # fields = ['title', 'content']
    
    template_name = 'article/create_by_class_view.html'
Copy the code

Create create_by_class_view.html (you already know where the directory is) and say:

create_by_class_view.html

<form method="post">{% csrf_token %}
    {{ form.as_p }}
    <input type="submit" value="Save">
</form>
Copy the code

Finally add the URL:

urls.py

urlpatterns = [
    path('create-view/', views.ArticleCreateView.as_view(), name='... '),]Copy the code

While the look is rudimentary (that’s not the point), this view is now capable of creating new articles!

I’m not going to talk about UpdateView and DeleteView, but I’ll talk about it when we use it.

For those who want to know in advance, here is the official document

conclusion

Feel the power of code isolation and inheritance? No? Later chapters will use classes to write views, as you’ll see.

The class view is so rich that a single article can only scratch the surface. Readers are having trouble programming, and the official documentation is your best tutorial.

If you have the patience to read the official documentation of the class view from cover to cover, that’s best.


  • If you have any questions please leave a message on Doucet’s personal website and I will reply as soon as possible.
  • Or Email me a private message: [email protected]
  • Project code: Django_blog_tutorial

Please inform the author and indicate the source for reprinting.