Django - BBS - 项目学习 - 个人站点的实现

本文详细介绍如何使用Django框架构建个人博客系统,包括路由配置、视图函数设计、前端页面布局与继承,以及自定义过滤器的使用,旨在帮助读者理解Django的MVC模式并掌握实际应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一、路由配置

二、视图函数

三、前端设计

3-1 母版

3-2 自定义过滤器(inclusion_tag)

3-3 配合inclusion_tag使用结构页(classify.html)

3-4 继承子版(new_user_blog.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 %}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值