目录
3-3 配合inclusion_tag使用结构页(classify.html)
一、路由配置
from django.conf.urls import url from django.contrib import admin from bbs import views from django.views.static import serve from mybbs.settings import MEDIA_ROOT urlpatterns = [ url(r'^$', views.index), url(r'^admin/', admin.site.urls), url(r'^login/', views.login), # 用于login前端页面对于验证码的获取 url(r'^get_valid_code/', views.get_valid_code), url(r'^index/', views.index), url(r'^register/', views.register), url(r'^logout/', views.logout), url(r'^change_pwd/', views.change_pwd), url(r'^change_avatar/', views.change_avatar), url(r'^media/(?P<path>.*)', serve, {"document_root": MEDIA_ROOT}), # 三个过滤(分类,标签,归档) - 用于进入点击左边导航后的个人站点的文章显示 # 分组分出三个(用户名,category|tag|archive中的一个,可能是分类id,tag_id,时间) url(r'^(?P<username>[\w]+)/(?P<condition>category|tag|archive)/(?P<param>.*)', views.user_blog), # 个人主页的文章查看路由 url(r'^(?P<username>[\w]+)/article/(?P<id>\d+)', views.article_detail), # 上方未匹配到,接收参数匹配个人站点 有名分组 url(r'^(?P<username>[\w]+)$', views.user_blog), ]
二、视图函数
from django.shortcuts import render, HttpResponse, redirect from bbs import models from django.db.models import Count from django.db.models.functions import TruncMonth # -----------个人站点(分类文章显示)---------- def user_blog(request, username, *args, **kwargs): ''' 个人站点(参数需要与路由的有名分组进行对应) - 用于获取用户的所有文章及简单信息 - 可以通过左侧导航控制显示的文章数和文章信息 - 通过模板的导入和继承实现 - 左侧时间导航切割显示 - TruncMonth模块 :param request: :param username: :return: ''' user = models.UserInfo.objects.filter(username=username).first() if not user: return render(request, 'error.html') blog = user.blog # 获取当前blog站点对象。Category分类表下的article文章数 category_num = models.Category.objects.all().filter(blog=blog).annotate(coun=Count('article__title')).values_list( 'title', 'coun', 'pk') print(category_num) # <QuerySet [('编程基础', 2), ('计算机基础', 0)]> # 获取当前blog站点对象,Tag标签表下的article文章数 tag_num = models.Tag.objects.all().filter(blog=blog).annotate(coun=Count('article__title')).values_list('title', 'coun', 'pk') print(tag_num) # <QuerySet [("test's tag 1", 0), ("test's tag 2", 0)]> # 获取当前blog站点对象,按年月分类的文章数 - TruncMonth模块 y_m_num = models.Article.objects.all().filter(blog=blog).annotate(y_m=TruncMonth('create_time')).values( 'y_m').annotate(coun=Count('y_m')).values_list('y_m', 'coun').order_by('-y_m') print(y_m_num) # <QuerySet [(datetime.datetime(2018, 11, 1, 0, 0), 2)]> # 获取当前站点的所有文章对象 - 一对多反向查询,表名小写_set article_list = blog.article_set.all() # 获取从前端传来的关键词进行逻辑操作 condition = kwargs.get('condition') param = kwargs.get('param') if param: if 'tag' == condition: # 当点入标签内,查询文章对象符合标签主键为url传输id的对象 article_list = article_list.filter(tag__pk=param) elif 'category' == condition: # 当点入分类内,查询文章对象符合分类主键为url传输id的对象 article_list = article_list.filter(category__pk=param) elif 'archive' == condition: # 当点入随笔时间内,查询文章对象符合创建时间为url传输时间的对象 # url内传输数据2018-11 切分[2018,11] archive_list = param.split('-') # 过滤:发布年为2018年,月为11月的所有文章 article_list = article_list.filter(create_time__year=archive_list[0], create_time__month=archive_list[1]) return render(request, 'new_user_blog.html', locals())
三、前端设计
3-1 母版
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> {# blog对象的反向查询 表名小写#} <title>{{ blog.userinfo.username }}-的个人博客</title> <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css"> {# 使用当前用户的样式文件 #} <link rel="stylesheet" href="/static/css/{{ blog.theme }}"> <link rel="stylesheet" href="/static/css/default.css"> <script src="/static/jquery-3.3.1.js"></script> <style> * { margin: 0; padding: 0; } </style> </head> <body> <div class="head"> <h1>{{ blog.title }}</h1> </div> <div class="container-fluid"> <div class="row"> {# 侧栏导航 模板的导入#} <div class="col-md-3"> {# 也可以通过自定义过滤器进行互相传参操作#} {% load my_tag %} {% classify username %} {# 通过模板导入具有的局限性:每个视图函数内必须返回所需的参数才能构建一个网站#} {# {% include 'classify.html' %}#} </div> {# 中心内容 模板的继承#} <div class="col-md-9"> {% block content %} {% endblock %} </div> </div> </div> </div> </body> </html>
3-2 自定义过滤器(inclusion_tag)
from django.template import Library from django.db.models.functions import TruncMonth from bbs import models from django.db.models import Count register = Library() @register.inclusion_tag('classify.html') def classify(username): user = models.UserInfo.objects.filter(username=username).first() blog = user.blog category_num = models.Category.objects.all().filter(blog=blog).annotate(coun=Count('article__title')).values_list( 'title', 'coun', 'pk') tag_num = models.Tag.objects.all().filter(blog=blog).annotate(coun=Count('article__title')).values_list('title', 'coun', 'pk') y_m_num = models.Article.objects.all().filter(blog=blog).annotate(y_m=TruncMonth('create_time')).values( 'y_m').annotate( coun=Count('y_m')).values_list('y_m', 'coun') return {'category_num': category_num, 'tag_num': tag_num, 'y_m_num': y_m_num, 'username': username}
3-3 配合inclusion_tag使用结构页(classify.html)
<div> <div class="panel panel-primary"> <div class="panel-heading">我的标签</div> <div class="panel-body"> {% for foo in tag_num %} {# <p><a href="tag/{{ foo.2 }}">{{ foo.0 }}({{ foo.1 }})</a></p>#} <p><a href="/{{ username }}/tag/{{ foo.2 }}">{{ foo.0 }}({{ foo.1 }})</a></p> {% endfor %} </div> </div> <div class="panel panel-primary"> <div class="panel-heading">我的分类</div> <div class="panel-body"> {% for foo in category_num %} <p><a href="/{{ username }}/category/{{ foo.2 }}">{{ foo.0 }}({{ foo.1 }})</a></p> {% endfor %} </div> </div> <div class="panel panel-primary"> <div class="panel-heading">随笔档案</div> <div class="panel-body"> {% for foo in y_m_num %} {# 注意:a标签内链接对时间的修改,href内必须传输和后台的处理一一对应#} <p><a href="/{{ username }}/archive/{{ foo.0|date:"Y-m" }}">{{ foo.0|date:"Y年m月" }}({{ foo.1 }})</a></p> {% endfor %} </div> </div> </div>
3-4 继承子版(new_user_blog.html)
{% extends 'base.html' %} {% block content %} {#通过站点查询所有文章,反向查询,按表名小写_set.all#} {% for article in article_list %} {#lqz/article/1#} <h4><a href="/{{ username }}/article/{{ article.pk }}">{{ article.title }}</a></h4> <div> {{ article.desc }} </div> {# clearfix是bootstrap框架提供的清浮动方式 #} <div class="clearfix"> <div style="margin-top: 10px " class="article_bottom small pull-right"> <span>posted @ {{ article.create_time|date:'Y-m-d H:i:s' }}</span> {#反向查询,一对多,按表名小写_set#} {# <span class="glyphicon glyphicon-comment"><a href="">评论({{ article.commit_num }})</a></span>#} <span>{{ article.blog.userinfo.username }}</span> <span><i class="fa fa-comment" aria-hidden="true"><a href="">评论({{ article.commit_num }})</a></i></span> {# <span class="glyphicon glyphicon-comment"><a href="">评论({{ article.commit_num }})</a></span>#} <span class="glyphicon glyphicon-thumbs-up"><a href="">点赞({{ article.up_num }})</a></span> <span><a href="">编辑</a></span> </div> </div> <hr> {% endfor %} {% endblock %}