1. 程式人生 > 其它 >BBS專案分佈搭建三(個人站點時間歸檔補充,實現側邊欄跳轉、無線級分類、實現文章詳情頁展示功能)

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())

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>

3. 無限級 分類實現

# 利用新欄位 pid >> parent_id 父id
	給下一級的標題增加pid 就可以形成無限級分類
    
    
# 此外 紅黑樹資料結構 也可以實現

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())