Django博客开发教程:实现文章列表

文章列表的URL是:网站域名/list-分类ID.html,文章列表页面需要调用的地方相对首页就少了很多。我这边就不再像首页那样做详细解释了。

直接上视图函数代码:

blog/views.py

#文章列表
def list(request,lid):
    list = Article.objects.filter(category_id=lid)#获取通过URL传进来的lid,然后筛选出对应文章
    cname = Category.objects.get(id=lid)#获取当前文章的栏目名
    remen = Article.objects.filter(tui__id=2)[:6]#右侧的热门推荐
    allcategory = Category.objects.all()#导航所有分类
    tags = Tag.objects.all()#右侧所有文章标签
    return render(request, 'list.html', locals())

大家留意一下Article.objects.filter(category_id=lid),通过filter查询到的是多个文章对象,(request,lid)这里面的lid是通过url传过来的,表示分类的id,然后我们在视图函数里接收。category_id=lid表示筛选出文章里分类id与传过进来的id相等文章。id=lid则是在文章分类里筛选出id与lid相同的分类,然后在列表页里展现。

大家可能也留意到了,我们这个视图函数里和首页视图函数对比少了一个context = {...}而多了一个locals(),这个locals()代替了context,locals()的作用是返回一个包含当前作用域里面的所有变量和它们的值的字典。由于后面我们进行代码优化的时候用的着,所以先介绍给大家。

打开templates/list.html页面。你的位置,后面的代码修改为:

templates/list.html

您的位置: <a itemprop="breadcrumb" href="/">首页</a> » 
<span class="current">Python</span></div>
修改为: 
<a itemprop="breadcrumb" href="{% url 'index' %}">首页</a> » 
<span class="current">{{ cname }} </span></div>

分类:

templates/list.html

<h4 class="post-left-title">分类:Python</h4>
修改为:
<h4 class="post-left-title">分类:{{ cname}}</h4>

文章列表展示修改为:

templates/list.html

{% for list in list %}
    <div class="article-box clearfix excerpt-1">
        <div class="col-md-4">
            <div class="thumbnail">
                <a href="{% url 'index' %}show-{{ list.id }}.html" title="{{ list.title }}">
                    <img src="media/{{ list.img }}"
                         srcset="media/{{ list.img }}"
                         alt="{{ list.title }}" class="wp-post-image" width="240" height="160"/></a>
            </div>
        </div>
        <div class="col-md-8">
            <h2><a href="{% url 'index' %}show-{{ list.id }}.html" target="_blank"
                   title="{{ list.title }}">{{ list.title }}</a></h2>
            <p class="txtcont hidden-xs"><a href="{% url 'index' %}show-{{ list.id }}.html"
                                            target="_blank"
                                            title="{{ list.title }}">{{ list.excerpt }}</a></p>
            <div class="meta"><span class="label label-info"><a
                    href="{% url 'index' %}list-{{ list.category_id }}.html">{{ list.category.name }}</a></span>
                <time class="item"><i
                        class="fa fa-clock-o"></i>{{ list.created_time|date:"Y年m月d日" }}
                </time>
            </div>
        </div>
    </div>
{% endfor %}

最后是文章分页,如果文章数量太多,我们需要对查询出来的数据进行分页展示。Django自带一个强大的分页功能插件,我们使用的时候,先在视图函数里导入,然后再使用。

blog/views.py
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
#导入分页插件包
def list(request,lid):
    ...
    page = request.GET.get('page')#在URL中获取当前页面数
    paginator = Paginator(list, 5)#对查询到的数据对象list进行分页,设置超过5条数据就分页
    try:
        list = paginator.page(page)#获取当前页码的记录
    except PageNotAnInteger:
        list = paginator.page(1)#如果用户输入的页码不是整数时,显示第1页的内容
    except EmptyPage:
        list = paginator.page(paginator.num_pages)#如果用户输入的页数不在系统的页码列表中时,显示最后一页的内容
    return render(request, 'list.html', locals())

分页代码修改为:

templates/list.html

<div class="pagination">
    <ul>
        <li class="prev-page"></li>
        <li class="active"><span>1</span></li>
        <li><a href="?page=2">2</a></li>
        <li class="next-page"><a href="?page=2">下一页</a></li>
    </ul>
</div>

修改为:

<div class="pagination">
    <ul>
        {% if list.has_previous %}
        <li class="prev-page"><a href="?page={{ list.previous_page_number }}">上一页</a></li>
        {% else %}
         <li class="prev-page"></li>
        {% endif %}


            {% for num in list.paginator.page_range %}
                {% if num %}
                    {% ifequal num list.number %}
                        <li class="active"><span>{{ num }}</span></li>
                    {% else %}
                        <li><a href="?page={{ num }}">{{ num }}</a></li>
                    {% endifequal %}
                {% else %}
                    <li class="disabled"><span>...</span></li>
                {% endif %}
            {% endfor %}


            {% if list.has_next %}
                <li class="next-page"><a href="?page={{ list.next_page_number }}">下一页</a></li>
            {% else %}
                <li class="prev-page"></li>
            {% endif %}
    </ul>
</div>

这个分页代码就不做过多解释,大家有不明白的可以加我微信:VIPdjango进行咨询,也可以自行百度。

至此,列表页面实现完毕。

文章评论 5

  • 大师,我的列表页为啥一直出问题。从admin的管理页面添加了分类。页面访问时,一直报错: Not Found: / list-5.html [14/Mar/2020 22:45:02] "GET /%20list-5.html HTTP/1.1" 404 2966

    页面上去掉 %20访问正常。

  • 搞定了,这边写错了。

    {% for category in allcategory %} <li id="menu-item-117720" class="menu-item"> <a href="{% url 'index' %}list-{{ category.id }}.html">{{ category.name }}</a> </li>

  • 大佬,你这个有点问题吧,为什么我点击那个分类页面进去之后那个导航栏里从数据库中渲染出来的那几个分类就不见了,感觉是分类的详情页里没有继承到base页面里的数据库中的导航栏呀

  • 这里没有通过'context'的方式传递上下文了,在views中把allcategory参数名改为模板中用到的categories即可