BBS项目分布搭建三(个人站点时间归档补充,实现侧边栏跳转、无线级分类、实现文章详情页展示功能)

BBS项目分布搭建三(个人站点时间归档补充,)

1. 个人站点时间归档

"""
settings.py设置最好更改以下:

    LANGUAGE_CODE = 'zh-hans'
    TIME_ZONE = 'Asia/Shanghai'

    USE_TZ = False  # 数据库时间
"""



# 在 blog.html文件中修改:
            <div class="panel panel-danger">
                <div class="panel-body">
                    时间归档
                </div>

                {% for date in date_list %}
                    <div class="panel-footer">
                        <a href="">{{ date.month|date:'Y-m' }}({{ date.c }})</a>
                    </div>
                {% endfor %}
            </div>
            
            
# 在views.py中修改个人站点功能:
# 7.个人站点页
def blog(request, username):
    '''
    验证站点是否存在
    :param request:
    :param username:
    :return:
    '''

    # 验证站点的存在性 404页面
    user_obj = models.UserInfo.objects.filter(username=username).first()
    if not user_obj:
        # 应该返回定制的404页面
        return render(request, '404.html')

    blog = user_obj.blog  # 个人站点
    # 查询当前站点的所有文章列表
    article_list = models.Article.objects.filter(blog=blog).all()

    '''查询当前站点下的所有标签'''
    # 第一步:
    tag_list = models.Tag.objects.filter(blog=blog).all()
    # print(tag_list)
    # 第二步:聚合查询每一个标签下的文章数量
    '''
        聚合查询使用关键字annotate
        分组查询使用关键字aggreate
    '''
    from django.db.models import Count

    # tag_list = models.Tag.objects.filter(blog=blog).annotate(count_num=Count('article__pk')).values_list('title', 'count_num')
    # tag_list = models.Tag.objects.filter(blog=blog).annotate(count_num=Count('article')).values_list('title', 'count_num')
    tag_list = models.Tag.objects.filter(blog=blog).annotate(count_num=Count('article')).values('title', 'count_num')
    # print(tag_list)

    '''查询当前站点下的所有分类'''
    category_list = models.Category.objects.filter(blog=blog).annotate(count_num=Count('article__pk')).values('title', 'count_num')
    # print(category_list)


    '''把当前站点下的文章按照年月分组,并且查询分组下的文章数量'''
    from django.db.models.functions import TruncMonth
    # 1. 查的是添加文章的时间:年月
    # 2. 查询分组之后的文章数量
    # 3. month =>  2021-06   => 虚拟字段

    date_list = models.Article.objects.filter(blog=blog).annotate(month=TruncMonth('create_time')).values('month').annotate(c=Count('id')).values('month', 'c')
    print(date_list)

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

image

image

2. 实现侧边栏筛选跳转功能

# 添加路由:
    # 侧边栏筛选功能
    # url(r'^(?P<username>\w+)/tag/(?P<param>\d+)', views.blog),  # 标签
    # url(r'^(?P<username>\w+)/category/(?P<param>\d+)', views.blog),  # 分类
    # url(r'^(?P<username>\w+)/archive/(?P<param>\w+)', views.blog),  # 分类
    # 以上三个地址可以合并为一个地址
    url(r'^(?P<username>\w+)/(?P<conditon>tag|category|archive)/(?P<param>.*)', views.blog),
    
    
    
    
# 修改个人站点功能:
 
# 7.个人站点页
def blog(request, username, **kwargs):
    print(123)
    '''
    验证站点是否存在
    :param request:
    :param username:
    :return:
    '''

    # 验证站点的存在性 404页面
    user_obj = models.UserInfo.objects.filter(username=username).first()
    if not user_obj:
        # 应该返回定制的404页面
        return render(request, '404.html')

    blog = user_obj.blog  # 个人站点
    # 查询当前站点的所有文章列表
    article_list = models.Article.objects.filter(blog=blog).all()

    # 侧边栏少选功能
    if kwargs:
        # print(kwargs) # {'conditon': 'tag', 'param': '2'}
        # print(kwargs) # {'conditon': 'category', 'param': '1'}
        # print(kwargs) # {'conditon': 'archive', 'param': '2022-03'}
        conditon = kwargs.get('conditon')
        param = kwargs.get('param')
        if conditon == 'tag':
            # 按照标签筛选
            article_list = article_list.filter(tags__pk=param)
        elif conditon == 'category':
            # 按照分类进行筛选
            article_list = article_list.filter(category__id=param)
        else:
            # 按照时间筛选
            # 2022-03
            year, month = param.split('-')  # [2022, 03]
            article_list = article_list.filter(create_time__year=year, create_time__month=month)

    '''查询当前站点下的所有标签'''
    # 第一步:
    tag_list = models.Tag.objects.filter(blog=blog).all()
    # print(tag_list)
    # 第二步:聚合查询每一个标签下的文章数量
    '''
        聚合查询使用关键字annotate
        分组查询使用关键字aggreate
    '''
    from django.db.models import Count

    # tag_list = models.Tag.objects.filter(blog=blog).annotate(count_num=Count('article__pk')).values_list('title', 'count_num')
    # tag_list = models.Tag.objects.filter(blog=blog).annotate(count_num=Count('article')).values_list('title', 'count_num')
    tag_list = models.Tag.objects.filter(blog=blog).annotate(count_num=Count('article')).values('title', 'count_num', 'pk')
    # print(tag_list)

    '''查询当前站点下的所有分类'''
    category_list = models.Category.objects.filter(blog=blog).annotate(count_num=Count('article__pk')).values('title', 'count_num', 'pk')
    # print(category_list)


    '''把当前站点下的文章按照年月分组,并且查询分组下的文章数量'''
    from django.db.models.functions import TruncMonth
    # 1. 查的是添加文章的时间:年月
    # 2. 查询分组之后的文章数量
    # 3. month =>  2021-06   => 虚拟字段

    date_list = models.Article.objects.filter(blog=blog).annotate(month=TruncMonth('create_time')).values('month').annotate(c=Count('id')).values('month', 'c')
    # print(date_list)

    return render(request, 'blog.html', locals())
    
    
    
# 修改 blog.html文件 <div class="col-md-3"> :
        <div class="col-md-3">
            <div class="panel panel-primary">
                <div class="panel-body">
                    我的标签
                </div>

                {% for tag in tag_list %}
                <div class="panel-footer">
                    <a href="/{{ username }}/tag/{{ tag.pk }}">{{ tag.title }}( {{ tag.count_num }})</a>
                </div>
                {% endfor %}
            </div>

            <div class="panel panel-success">
                <div class="panel-body">
                     我的分类
                </div>
                {% for category in category_list %}
                    <div class="panel-footer">
                        <a href="/{{ username }}/category/{{ category.pk }}">{{ category.title }}({{ category.count_num }})</a>
                    </div>
                {% endfor %}
            </div>

            <div class="panel panel-danger">
                <div class="panel-body">
                    时间归档
                </div>

                {% for date in date_list %}
                    <div class="panel-footer">
                        <a href="/{{ username }}/archive/{{ date.month|date:'Y-m'}}">{{ date.month|date:'Y-m' }}({{ date.c }})</a>
                    </div>
                {% endfor %}
            </div>
        </div>

image

3. 无限级 分类实现

# 利用新字段 pid >> parent_id 父id
	给下一级的标题增加pid 就可以形成无限级分类
    
    
# 此外 红黑树数据结构 也可以实现

image

image

4. 文章详情页

# 新建公共HTML文件用于模板继承 base.html:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
    <script src="/static/layer-v3.5.1/layer/layer.js"></script>

    <style>
        #wrapper span {
            margin-right: 10px;
        }
    </style>
</head>
<body>

<nav class="navbar navbar-inverse">
    <div class="container-fluid">
        <!-- Brand and toggle get grouped for better mobile display -->
        <div class="navbar-header">
            <button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
                    data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="#">py20BBS</a>
        </div>

        <!-- Collect the nav links, forms, and other content for toggling -->
        <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">

            <ul class="nav navbar-nav">
                <li class="active"><a href="#">Link <span class="sr-only">(current)</span></a></li>
                <li><a href="#">Link</a></li>
                <li class="dropdown">
                    <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
                       aria-expanded="false">Dropdown <span class="caret"></span></a>
                    <ul class="dropdown-menu">
                        <li><a href="#">Action</a></li>
                        <li><a href="#">Another action</a></li>
                        <li><a href="#">Something else here</a></li>
                        <li role="separator" class="divider"></li>
                        <li><a href="#">Separated link</a></li>
                        <li role="separator" class="divider"></li>
                        <li><a href="#">One more separated link</a></li>
                    </ul>
                </li>


            </ul>
            <form class="navbar-form navbar-left">
                <div class="form-group">
                    <input type="text" class="form-control" placeholder="Search">
                </div>
                <button type="submit" class="btn btn-default">Submit</button>
            </form>
            <ul class="nav navbar-nav navbar-right">
                {% if request.session.username %}
                    <li><a href="#">{{ request.session.username }}</a></li>
                    <li class="dropdown">
                        <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
                           aria-expanded="false">更多操作 <span class="caret"></span></a>
                        <ul class="dropdown-menu">
                            <li><a href="#" data-toggle="modal" data-target=".bs-example-modal-lg">修改密码</a></li>
                            <li><a href="#">后台管理</a></li>
                            <li><a href="/logout/">退出系统</a></li>
                        </ul>
                    </li>
                {% else %}
                    <li><a href="/register/">注册</a></li>
                    <li><a href="/login/">登录</a></li>
                {% endif %}

            </ul>
        </div><!-- /.navbar-collapse -->
        <div class="modal fade bs-example-modal-lg" tabindex="-1" role="dialog" aria-labelledby="myLargeModalLabel">
            <div class="modal-dialog modal-lg" role="document">
                <div class="modal-content">
                    <div class="row">
                        <h1 class="text-center">修改密码</h1>
                        <div class="col-md-8 col-md-offset-2">
                            <div class="form-group">
                                <label for="old_pwd">
                                    原密码:
                                </label>
                                <input type="text" id="old_pwd" class="form-control">
                            </div>
                            <div class="form-group">
                                <label for="new_pwd">
                                    新密码:
                                </label>
                                <input type="text" id="new_pwd" class="form-control">
                            </div>
                            <div class="form-group">
                                <label for="re_pwd">确认密码:</label>
                                <input type="text" id="re_pwd" class="form-control">
                            </div>
                            <div class="modal-footer">
                                <button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
                                <button type="button" class="btn btn-primary set_pwd">提交</button>
                            </div>
                        </div>

                    </div>
                </div>
            </div>
        </div>
    </div><!-- /.container-fluid -->
</nav>


<div class="container-fluid">
    <div class="row">

        <div class="col-md-3">
            <div class="panel panel-primary">
                <div class="panel-body">
                    我的标签
                </div>

                {% for tag in tag_list %}
                <div class="panel-footer">
                    <a href="/{{ username }}/tag/{{ tag.pk }}">{{ tag.title }}( {{ tag.count_num }})</a>
                </div>
                {% endfor %}
            </div>

            <div class="panel panel-success">
                <div class="panel-body">
                     我的分类
                </div>
                {% for category in category_list %}
                    <div class="panel-footer">
                        <a href="/{{ username }}/category/{{ category.pk }}">{{ category.title }}({{ category.count_num }})</a>
                    </div>
                {% endfor %}
            </div>

            <div class="panel panel-danger">
                <div class="panel-body">
                    时间归档
                </div>

                {% for date in date_list %}
                    <div class="panel-footer">
                        <a href="/{{ username }}/archive/{{ date.month|date:'Y-m'}}">{{ date.month|date:'Y-m' }}({{ date.c }})</a>
                    </div>
                {% endfor %}
            </div>
        </div>


        <div class="col-md-9">
            {% block content %}

            {% endblock %}
        </div>

    </div>
</div>

</body>
</html>




# blog.html就可以直接继承 base.html:
{% extends 'base.html' %}  
{#// 模板继承#}

{#下面为动态内容#}
{% block content %}

    {% for article in article_list %}
                <div class="media">
                    <h4 class="media-heading"><a href="">{{ article.title }}</a></h4>

                    <div class="media-body">
                        {{ article.desc }}
                    </div>

                    <div id="wrapper" class="pull-right" style="margin-top: 15px">
                        <span>posted</span>
                        <span>@</span>
                        <span>{{ article.create_time|date:'Y-m-d H:i' }}</span>
                        <span class="glyphicon glyphicon-thumbs-up">{{ article.up_num }}</span>
                        <span class="glyphicon glyphicon-thumbs-down">{{ article.down_num }}</span>
                        <span class="glyphicon glyphicon-comment">{{ article.comment_num }}</span>
                    </div>
                </div>
            {% endfor %}

{% endblock %}
    
    
    
# 创建文章详情页 article_detail.html:
{% extends 'base.html' %}

{% block content %}
    <h1>{{ article_detail.title }}</h1>
    <div class="article_content">
        {{ article_detail.content|safe }}
    </div>
{% endblock %}
    
    
    
# 添加路由 路由放在侧边筛选路由上方 避免正则匹配不到:
    # 文章详情页
    url(r'^(?P<username>\w+)/(?P<article_id>\d+)', views.article_detail),
    
    
    
# 添加文章详情页功能 views.py中:
    
from django.db.models import Count
# 8. 文章详情页
def article_detail(request, username, article_id):
    user_obj = models.UserInfo.objects.filter(username=username).first()
    if not user_obj:
        return render(request, '404.html')
    blog = user_obj.blog  # 个人站点

    # 查询文章详情数据
    article_detail = models.Article.objects.filter(pk=article_id, blog=blog).first()
    if not article_detail:
        return render(request, '404.html')

    tag_list = models.Tag.objects.filter(blog=blog).annotate(count_num=Count('article')).values('title', 'count_num', 'pk')

    '''查询当前站点下的所有分类'''
    category_list = models.Category.objects.filter(blog=blog).annotate(count_num=Count('article__pk')).values('title', 'count_num', 'pk')

    '''把当前站点下的文章按照年月分组,并且查询分组下的文章数量'''
    from django.db.models.functions import TruncMonth
    # 1. 查的是添加文章的时间:年月
    # 2. 查询分组之后的文章数量
    # 3. month =>  2021-06   => 虚拟字段
    date_list = models.Article.objects.filter(blog=blog).annotate(month=TruncMonth('create_time')).values('month').annotate(c=Count('id')).values('month', 'c')

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

image

posted @ 2022-03-16 17:35  Deity_JGX  阅读(57)  评论(0编辑  收藏  举报