BBS个人站点

一、个人站点功能编写思路概览

  • 首先要开设路由紧接着要写视图函数在建页面
  • 其次考虑逻辑判断是该个人站点与否要返回两个页面
  • 再补充细节 模板的继承加分页器创建CSS个人样式

二、个人站点功能编写思路详细

1.开始个人站点路由

    path('<str:username>/', views.site_func),
    # 侧边栏筛选接口
    # path('<str:username>/category/<int:category_id>/', views.site_func),
    # path('<str:username>/tag/<int:tag_id>/', views.site_func),
    # path('<str:username>/archive/<str:yearAndmonth>/', views.site_func),
    # 上述三个路由可以合并成一个路由
    re_path('^(?P<username>\w+)/(?P<condition>category|tag|archive)/(?P<params>.*?)/', views.site_func),

侧边栏功能只需要开路由用个人站点视图函数即可

2.写视图函数

def site_func(request, username):
    site_obj = models.Site.objects.filter(site_name=username)
    if not site_obj:
        return render(request, 'errorPage.html')

3.如果没有此个人站点则展示404page

<!DOCTYPE html>
<html>
<head>
    <meta charset='utf-8'>
    <link rel="icon" href="//common.cnblogs.com/favicon.ico" type="image/x-icon" />
    <title>404 页面不存在 - BBS</title>
    <style type='text/css'>
        body {
            margin: 8% auto 0;
            max-width: 400px;
            min-height: 200px;
            padding: 10px;
            font-family: 'PingFang SC', 'Microsoft YaHei', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif;
            font-size: 14px;
            padding-right: 200px;
            position: relative;
        }
        p { color: #555;margin: 15px 0px; }
        img { border: 0px; }
        .d { color: #404040; }
        .robot img { max-width: 192px; }
        .robot { position: absolute; top: 0; right: 0; }
    </style>
</head>
<body>
    <p style="margin-left: 5px;"><a href="/home/"><img src="media/404logo.jpeg" style="height:45px" alt="cnblogs"></a></p>
    <div style="margin-top:20px">
        <p style=""><b style="">404.</b> 抱歉,您访问的资源不存在。</p>
        <p class="d">可能是网址有误,或者对应的内容被删除,或者处于私有状态。</p>
        <p style="color:#777;">代码改变世界,联系邮箱 contact@BBS.com</p>
    </div>
    <div class="robot"><a href="//www.cnblogs.com/cmt/articles/13940458.html"><img src="media/404-robot.png" alt="404 robot" /></a></div>
    <script async src="https://www.googletagmanager.com/gtag/js?id=G-4CQQXWHK3C"></script>
    <script>
      window.dataLayer = window.dataLayer || [];
      function gtag(){dataLayer.push(arguments);}
      gtag('js', new Date());

      gtag('config', 'G-4CQQXWHK3C');
    </script>
</body>
</html>

4.如果有这个个人站点就返回一个页面

    # 查询个人站点是否存在
    site_obj = models.Site.objects.filter(site_name=username).first()
	return render(request, 'sitePage.html', locals())

5.考虑到代码精简,可以用inclusion_tag

  • 首先在应用Aapp01下创建名字叫templatetags的目录()

  • 其次在此目录地下创建mytag.py文件

  • 在文件里面写如下代码

from django import template  # 固定代码
from app01 import models
from django.db.models import Count
from django.db.models.functions import TruncMonth


register = template.Library()  # 固定代码


@register.inclusion_tag('leftmenu.html',name='mymenu')
def index(username):
    site_obj = models.Site.objects.filter(site_name=username).first()
    # 查询个人站点下所有的分类名称以及每个分类下的文章数
    category_queryset = models.Category.objects.filter(site=site_obj).annotate(article_num=Count('article__pk')).values(
        'name', 'article_num', 'pk')
    # 查询个人站点下所有的标签名称以及每个标签下的文章数
    tag_queryset = models.Tag.objects.filter(site=site_obj).annotate(article_num=Count('article__pk')).values(
        'name', 'article_num', 'pk')
    # 年月分组并统计文章个数
    from django.db.models.functions import TruncMonth
    date_queryset = models.Article.objects.filter(site=site_obj).annotate(month=TruncMonth('create_time')).values(
        'month').annotate(
        article_num=Count('pk')).values('month', 'article_num')
    return locals()

6.创建leftmenu.html页面(局部页面)

<div class="panel panel-primary">
                  <div class="panel-heading">
                    <h3 class="panel-title">文章分类</h3>
                  </div>
                  <div class="panel-body">
                        {% for category_obj in category_queryset %}
                            <p><a href="/{{ site_obj.site_name }}/category/{{ category_obj.pk }}/">{{ category_obj.name }}({{ category_obj.article_num }})</a></p>
                        {% endfor %}
                  </div>
                </div>
<div class="panel panel-warning">
                  <div class="panel-heading">
                    <h3 class="panel-title">文章标签</h3>
                  </div>
                  <div class="panel-body">
                        {% for tag_obj in tag_queryset %}
                            <p><a href="/{{ site_obj.site_name }}/tag/{{ tag_obj.pk }}/">{{ tag_obj.name }}({{ tag_obj.article_num }})</a></p>
                        {% endfor %}
                  </div>
                </div>
<div class="panel panel-danger">
                  <div class="panel-heading">
                    <h3 class="panel-title">日期归档</h3>
                  </div>
                  <div class="panel-body">
                        {% for date_obj in date_queryset %}
                            <p><a href="/{{ site_obj.site_name }}/archive/{{ date_obj.month|date:'Y-m' }}/">{{ date_obj.month|date:'Y年m月' }}({{ date_obj.article_num }})</a></p>
                        {% endfor %}

                  </div>
                </div>

6.编写个人站点页面,跟首页类似 用模板的继承

{% extends 'homePage.html' %}


{% block css %}
    <link rel="stylesheet" href="media/css/{{ site_obj.site_theme }}/">
{% endblock %}

{% block title %}
    {{ site_obj.site_title }}
{% endblock %}


{% block content %}
        <div class="col-md-2">
            {% load mytag %}
            {% mymenu username %}
        </div>
        <div class="col-md-10">
            {% for article_obj in article_queryset %}
                <div class="media">
                         <h4 class="media-heading"><a href="/{{ article_obj.site.userinfo.username }}/article/{{ article_obj.pk }}/">{{ article_obj.title }}</a></h4>
                          <div class="media-left">
                            <a href="#">
                              <img class="media-object" src="/media/{{ article_obj.site.userinfo.avatar }}/" alt="..." width="80">
                            </a>
                          </div>
                          <div class="media-body" style="padding:10px">
                            {{ article_obj.desc }}
                          </div>
                            <br>
                            <div class="pull-right">
                                <span>posted&nbsp;&nbsp;@</span>
                                <span>{{ article_obj.create_time|date:'Y-m-d H:i:s' }}&nbsp;&nbsp;</span>
                                <span>{{ article_obj.site.userinfo.username }}&nbsp;&nbsp;</span>
                                <span class="glyphicon glyphicon-thumbs-up">{{ article_obj.up_num }}&nbsp;&nbsp;</span>
                                <span class="glyphicon glyphicon-thumbs-down">{{ article_obj.down_num }}&nbsp;&nbsp;</span>
                                <span class="glyphicon glyphicon-comment">{{ article_obj.comment_num }}&nbsp;&nbsp;</span>
                            </div>
                        </div>
                <hr>
            {% endfor %}
        </div>
{% endblock %}

7.编写完整的个人站点后端代码

def site_func(request, username, **kwargs):
    """
    :param kwargs: 接收多余的关键字参数 代码通过该参数是否有值从而得出是个人站点还是侧边栏筛选
    """
    # 查询个人站点是否存在
    site_obj = models.Site.objects.filter(site_name=username).first()
    if not site_obj:
        return render(request, 'errorPage.html')
    # 查询个人站点下所有的文章
    article_queryset = models.Article.objects.filter(site=site_obj)
    if kwargs:
        condition = kwargs.get('condition')
        params = kwargs.get('params')
        if condition == 'category':
            article_queryset = article_queryset.filter(category_id=params)
        elif condition == 'tag':
            article_queryset = article_queryset.filter(tags__pk=params)
        else:  # 年-月
            year, month = params.split('-')
            article_queryset = article_queryset.filter(create_time__year=year, create_time__month=month)
    '''如果文章较多也应该添加分页器'''

    return render(request, 'sitePage.html', locals())