9 个人站点页面的文章查询 & 个人站点页面的渲染布局 & 个人站点页面的跳转过滤功能 & 知识点补充

image

urls.py
from django.urls import re_path

urlpatterns = [
    ...
    # 个人站点url
    re_path('^(?P<username>\w+)/$', views.home_site),
    # 个人站点页面的跳转过滤功能
    re_path('^(?P<username>\w+)/(?P<condition>tag|category|archive)/(?P<param>.*)/$', views.home_site),
]
views.py
from django.shortcuts import render
from django.db.models import Count
from blog import models
...

def home_site(request, username, **kwargs):
    """个人站点视图函数"""
    user_obj = models.UserInfo.objects.filter(username=username).first()

    if not user_obj:  # 判断用户是否存在
        return render(request, "not_found.html")

    # 查询当前站点对象
    blog_obj = user_obj.blog

    # 当前用户或者当前站点对应所有的文章
    # 基于对象查询
    # article_list = user_obj.article_set.all()
    # 基于__查询
    article_list = models.Article.objects.filter(user=user_obj)

    if kwargs:  # 区分访问的是站点页面还是站点下的跳转页面
        condition = kwargs.get('condition')
        param = kwargs.get('param')
        if condition == "category":
            article_list = article_list.filter(category__title=param)
        elif condition == "tag":
            article_list = article_list.filter(tags__title=param)
        else:
            year, month = param.split('-')
            article_list = article_list.filter(create_time__year=year, create_time__month=month)

    # 查询当前站点的每一个分类名称以及对应的文章数
    cate_list = models.Category.objects.filter(blog=blog_obj).values("pk").annotate(c=Count("article__title")).values_list("title", "c")
    # print(cate_list)

    # 查询当前站点的每一个标签名称以及对应的文章数
    tag_list = models.Tag.objects.filter(blog=blog_obj).values("pk").annotate(c=Count("article")).values_list("title", "c")
    # print(tag_list)

    # 查询当前站点每一年月的名称以及对应的文章数
    # 方式1:
    date_list = models.Article.objects.filter(user=user_obj).extra(select={'y_m_date': 'date_format(create_time, "%%Y-%%m")'}).values("y_m_date").annotate(c=Count('nid')).values_list("y_m_date", "c")
    # print(date_list)  # <QuerySet [{'y_m_date': '2022-08', 'c': 2}]>
    # 方式2:
    # date_list = models.Article.objects.filter(user=user_obj).annotate(month=TruncMonth("create_time")).values("month").annotate(c=Count('nid')).values_list("month", "c")  # 年月分组
    # print(date_list)  # <QuerySet [(datetime.datetime(2022, 8, 1, 0, 0), 2)]>

    return render(request, "home_site.html", locals())
home_site.html
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="{% static 'blog/bootstrap/css/bootstrap.css' %}">
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        .header {
            width: 100%;
            height: 55px;
            background-color: #369;
        }

        .header .title {
            font-size: 18px;
            font-weight: 100;
            line-height: 60px;
            color: white;
            margin-left: 15px;
            margin-top: -10px;
        }

        .backend {
            float: right;
            color: white;
            text-decoration: none;
            font-size: 14px;
            margin-right: 10px;
            margin-top: 10px;
        }

        .pub_info {
            margin-top: 10px;
            color: darkgray;
        }

    </style>
</head>
<body>

<div class="header">
    <div class="content">
        <p class="title">
            <span>{{ blog_obj.title }}</span>
            <a href="" class="backend">管理</a>
        </p>
    </div>
</div>

<div class="container">
    <div class="row">
        <div class="col-md-3">
            <div class="panel panel-warning">
                <div class="panel-heading">我的标签</div>
                <div class="panel-body">
                    {% for tag in tag_list %}
                        <p><a href="/{{ username }}/tag/{{ tag.0 }}">{{ tag.0 }} ({{ tag.1 }})</a></p>
                    {% endfor %}
                </div>
            </div>
            <div class="panel panel-danger">
                <div class="panel-heading">随笔分类</div>
                <div class="panel-body">
                    {% for cate in cate_list %}
                        <p><a href="/{{ username }}/category/{{ cate.0 }}">{{ cate.0 }} ({{ cate.1 }})</a></p>
                    {% endfor %}

                </div>
            </div>
            <div class="panel panel-success">
                <div class="panel-heading">随笔归档</div>
                <div class="panel-body">
                    {% for date in  date_list%}
                        <p><a href="/{{ username }}/archive/{{ date.0 }}">{{ date.0 }} ({{ date.1 }})</a></p>
                    {% endfor %}
                    
                </div>
            </div>
        </div>
        <div class="col-md-9">
            <div class="article_list">
                {% for article in article_list %}
                    <div class="article-item clearfix">
                        <h5><a href="">{{ article.title }}</a></h5>
                        <div class="article-desc">
                            {{ article.desc }}
                        </div>
                        <div class="small pub_info pull-right">
                            <span>发布于&nbsp;&nbsp;{{ article.create_time|date:"Y-m-d H:i" }}</span> &nbsp;&nbsp;
                            <span><iclass="glyphicon glyphicon-comment"></i>&nbsp;评论({{ article.comment_count }})</span>
                            &nbsp;&nbsp;
                            <span><i class="glyphicon glyphicon-thumbs-up"></i>&nbsp;点赞({{ article.up_count }})</span>
                        </div>
                    </div>
                    <hr>
                {% endfor %}

            </div>
        </div>
    </div>
</div>


</body>
</html>

成品看图:

image


image


知识点补充:
image

如何只拿出,dt字段中的年月字段?
image


知识点补充:extra

有些时候复杂的sql语句,Django无法去对应。

extra(select=None, where=None, params=None, tables=None, order_by=None, select_params=None )

有些情况下,Dj ango的查询语法难以简单的表达复杂的WHERE子句,对于这种情况,Django 提供了extra() QuerySet修改机制,它能在QuerySet生成的SQL从句中注入新子句

extra可以指定一个或多个参数,例如select, where or tables.这些参数都不是必须的,但是你至少要使用一个!要注意这些额外的方式对不同的数据库引擎可能存在移植性问题。(因为你在显式的书写SQL语句)

参数之select
The select 参数可以让你在SELECT 从句中添加其他字段信息,它应该是一个字典, 存放着属性名到SQL 从句的映射。

queryResult models.Article.objects.extra(select={'is_ recent': "create_ time > '2017-09- -05'"})
结果集中每个Entry 对象都有一个额外的属性is_ recent, 它是一个布尔值, 表示Article对象的create_ time是否晚于2017-09-05

练习1:

ret = models.Article.objects.extra(select={'is_recent': 'create_time > "2020-09-05"'}).values("title", "is_recent")

# <QuerySet [{'is_recent': 1, 'title': 'nginx的使用方式哈哈哈哈'}, {'is_recent': 1, 'title': 'python-mysql哈哈哈哈哈'}]>

# SELECT (create_time > "2020-09-05") AS `is_recent`, `blog_article`.`nid`, `blog_article`.`title`, `blog_article`.`desc`, `blog_article`.`create_time`, `blog_article`.`content`, `blog_article`.`comment_count`, `blog_article`.`up_count`, `blog_article`.`down_count`, `blog_article`.`user_id`, `blog_article`.`category_id` FROM `blog_article`

练习2:

ret = models.Article.objects.extra(select={'y_m_d_date': 'date_format(create_time, "%%Y-%%m-%%d")'}).values("title", "y_m_d_date")

print(ret)
# <QuerySet [{'y_m_d_date': '2022-08-17', 'title': 'nginx的使用方式哈哈哈哈'}, {'y_m_d_date': '2022-08-17', 'title': 'python-mysql哈哈哈哈哈'}]>

select参数,相当于对每一条查询的数据插入一个字段,如y_m_d_date。在格式化时间格式的字段,生成新的字段如 y_m_d_date


Django提供了一种方式:日期归档查询方式
如果以后遇到,要用某年某月分组的话,那么可以使用Django提供的方式:

# from django.db.models.functions import TruncMonth, TruncDay, TruncHour
from django.db.models.functions import TruncMonth

models.Sales.objects\
    .annotate(month=TruncMonth('timestamp'))  # 截断日期到年月,在赋值给month。使用:Sales.month
    .values("month")  #  用截断出来的年月字段,来分组
    .annotate(c=Count('id'))  # 统计id的数量
    .values('month', 'c')  # 

实例:

ret = models.Article.objects.filter(user=user_obj).annotate(month=TruncMonth("create_time")).values("month").annotate(c=Count('nid')).values_list("month", "c")  # 年月分组
print(ret)  # <QuerySet [(datetime.datetime(2022, 8, 1, 0, 0), 2)]>
posted @ 2022-08-18 11:58  角角边  Views(31)  Comments(0)    收藏  举报