BBS个人站点
目录
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 @</span>
<span>{{ article_obj.create_time|date:'Y-m-d H:i:s' }} </span>
<span>{{ article_obj.site.userinfo.username }} </span>
<span class="glyphicon glyphicon-thumbs-up">{{ article_obj.up_num }} </span>
<span class="glyphicon glyphicon-thumbs-down">{{ article_obj.down_num }} </span>
<span class="glyphicon glyphicon-comment">{{ article_obj.comment_num }} </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())