After the number of page views, the popularity of the article has an evaluation standard. With this comes the need to sort articles by page views, showing ** “most popular articles” **.

Now that you’re familiar with the MTV mode, you don’t need me to bog you down:

  • The Model of the article is already available, so there is no need to write the Model
  • Write a view functionarticle_list_by_views(), retrieve the article object sorted by browse
  • Pass the article object to the template and render it

It’s simple, but there’s a hidden problem: Most of the features of the top articles list are actually the same as the normal articles list before it, just in a different order.

What if one day you need to sort by article title? In case you need to sort by user ID, tag, favorite… Not only that, but even routing urls.py is bloated. The code becomes bloated and unmaintainable.

** Repetitive code is the root of all evil. ** So the challenge is not to create a new view/route, but to merge the sorting functionality into the existing view/route.

view

Rewrite article_list() based on the above requirements:

article/views.py

...
# Rewrite the list of articles
def article_list(request):
    Select * from GET request
    # return an array of objects in different sorts
    if request.GET.get('order') = ='total_views':
        article_list = ArticlePost.objects.all().order_by('-total_views')
        order = 'total_views'
    else:
        article_list = ArticlePost.objects.all()
        order = 'normal'

    paginator = Paginator(article_list, 3)
    page = request.GET.get('page')
    articles = paginator.get_page(page)
    
    # change this line
    context = { 'articles': articles, 'order': order }
    
    return render(request, 'article/list.html', context)
Copy the code

Key knowledge is as follows:

  • We used the GET request earlier to pass a single parameter. It can also pass multiple arguments, such as? a=1&b=2, used between parameters&separated
  • View based on the GET argumentorderTo determine how to sort the articles taken out
  • order_by()Method specifies how objects are sorted. In the modeltotal_viewsThis integer field, so ‘total_views’ is positive and’ -total_views’ is reverse
  • Why the new variableorderAlso passed to the template? Because articles need turning pages!orderGive the template an indication of how the next page should be sorted

This way, all the parameters needed for sorting can be retrieved from the query, without rewriting urls.py.

The template

Next modify the article list template by optimizing the entry and paging properly:

templates/article/list.html

...

<div class="container">
    <nav aria-label="breadcrumb">
        <ol class="breadcrumb">
            <li class="breadcrumb-item">
                <a href="{% url 'article:article_list' %}">The latest</a>
            </li>
            <li class="breadcrumb-item">
                <a href="{% url 'article:article_list' %}? order=total_views">The hottest</a>
            </li>
        </ol>
    </nav>
    
    <div class="row mt-2">
        {% for article in articles %}
        ...
        {% endfor %}
    </div>

<! -- Page navigation -->.<a href="? page=1&order={{ order }}" class="btn btn-success">&laquo; 1</a>.<a href="? page={{ articles.previous_page_number }}&order={{ order }}" 
   class="btn btn-secondary">.</a>. {% if articles.has_next %}<a href="? page={{ articles.next_page_number }}&order={{ order }}"
   class="btn btn-secondary">{{ articles.next_page_number }}</a>.<a href="? page={{ articles.paginator.num_pages }}&order={{ order }}"
   class="btn btn-success">{{ articles.paginator.num_pages }} &raquo;</a>.Copy the code
  • Added breadcrumb navigation styles in Bootstrapbreadcrumb
  • All paging links have been added in the page number navigationorderparameter

test

Start the server and click “hottest” :

Well done! Switch page numbers and notice how the address bar changes.

There’s just one minor glitch: when users click on the “hottest” button, it should preferably turn gray and be unclickable. The opportunity for refinement is left to the reader.

There is one small change in header. HTML: The “write article” entry has been moved to the user drop-down menu.

conclusion

This chapter has touched on an advanced programming domain threshold: code reuse. Combine code for similar functionality and make it easy to extend subsequent functionality. Just write a few elif statements in the view and you’re done.

In the future programming, readers should also try to optimize the code structure to achieve twice the result with half the effort.

At this point, the blog is small, but quite complete. Keep trying!

  • 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 indicate the source of reprint.