zoukankan      html  css  js  c++  java
  • 5.博客系统| 文章详情页

     文章详情页

    文章详情页的渲染;点赞与踩灭(点赞人即当前登录人); 评论

     1. 文章详情页的设计和数据构建

    urls.py

    #media配置
        re_path(r"media/(?P<path>.*)$", serve, {"document_root":settings.MEDIA_ROOT}),
        re_path('^(?P<username>w+)/articles/(?P<article_id>d+)$',views.article_detail),

    views.py

    def get_classification_data(username):  #查询相关的数据,获取分类的数据  
        user = UserInfo.objects.filter(username=username).first() #个人站点对象
        blog = user.blog   #视图函数里边构建的数据就是为了传到模板里边去使用它们。
        cate_list = models.Category.objects.filter(blog=blog).annotate(c = Count("article__title")).values_list("title", "c")
        tag_list = models.Tag.objects.filter(blog=blog).values("pk").annotate(c = Count("article")).values_list("title","c")
        date_list = models.Article.objects.filter(user=user).extra(select={"y_m": "date_format(create_time,'%%Y-%%m')"}).values("y_m").annotate(c=Count("nid")).values_list("y_m","c")
        return {"blog":blog, "cate_list":cate_list, "tag_list":tag_list, "date_list":date_list}
    
    def article_detail(request, username, article_id):  #127.0.0.1:8000/egon/article/1
    
        context = get_classification_data(username)
        return render(request, "article_detail.html", context)

    base.html(继承)

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style>
            *{
                margin:0;
                padding:0;
            }
            .header{
                100%;
                height: 60px;
                background-color: #369;
            }
            .header .title{
                font-size: 18px;
                font-weight: 100;
                line-height: 60px;
                color: white;
                margin-left: 15px;
                margin-top: -10px;;
            }
            .backend{
                float:right;
                color: white;
                text-decoration: none;
                font-size: 16px;
                margin-right:10px;
                margin-top: 10px;;
            }
            .pub_info{
                margin-top: 10px;
                color: darkgrey;
            }
        </style>
        <link rel="stylesheet" href="/static/blog/bootstrap/css/bootstrap.css">
    </head>
    <body>
    <div class="header">
        <div class="content">
            <p class="title">
                <span>{{ blog.title }}</span>
                <a href="" class="backend">管理</a>
            </p>
        </div>
    </div>
    <div class="container">
        <div class="row">
            <div class="col-md-3">
                <div class="panel panel-warning">
                    <div class="panel-heading">我的标签</div>
                    <div class="panel-body">
                        {% for tag in tag_list %}
                        <p><a href="/{{ username }}/tag/{{ tag.0 }}">{{ tag.0 }}({{ tag.1 }})</a></p>
    
                        {% endfor %}
                    </div>
                </div>
                <div class="panel panel-danger">
                    <div class="panel-heading">随笔分类</div>
                    <div class="panel-body">
                        {% for cate in cate_list %}
                        <p><a href="/{{ username }}/category/{{ cate.0 }}"> {{ cate.0 }}({{ cate.1 }})</a></p>
                        {% endfor %}
                    </div>
                </div>
                <div class="panel panel-success">
                    <div class="panel-heading">随笔归档</div>
                    <div class="panel-body">
                        {% for date in date_list %}
                        <p><a href="/{{ username }}/archive/{{ date.0 }}"> {{ date.0 }}({{ date.1 }})</a></p>
                        {% endfor %}
                    </div>
                </div>
            </div>
            <div class="col-md-9">
               {% block content %}  {# 写个块留着扩展用#}
                
                {% endblock %}
    
            </div>
        </div>
    </div>
    </body>
    </html>

    home_site.html

    {% extends 'base.html' %}  //继承base.html 
    
    {% block content %}  
    <div class="article_list">
                    {% for article in article_list %}
                    <div class="article-item clearfix">
                        <h5><a href="">{{ article.title }}</a> </h5>
                        <div class="article-desc">
                            {{ article.desc }}
                        </div>
                        <div class="small pub_info pull-right">
                            <span>发布于&nbsp;&nbsp;{{ article.create_time|date:"Y-m-d H:i" }}</span>&nbsp;&nbsp;&nbsp;
                            <span class="glyphicon glyphicon-comment"></span>评论({{ article.comment_count }})&nbsp;&nbsp;&nbsp;
                            <span class="glyphicon glyphicon-thumbs-up"></span>点赞({{ article.up_count }})
                        </div>
                    </div>
                        <hr>
                    {% endfor %}
                </div>
    {% endblock %}

    2. 文章详情页的inclution_tag(定义自己的标签)

    样式和数据结合成一个整体

    两种方法:1是可以用函数get_classification_data (构建函数,传到模板文件里边去,如上边那种方法)

         2是可以用inclution_tag(方法二,样式和数据结合成一个整体)

    my_tags.py

    #Author:Kris
    
    from django import template
    from blog import models
    from django.db.models import Count
    
    register = template.Library()
    
    @register.simple_tag
    def multi_tag(x, y):
        return x*y 
                            #参数是要接收一个模板
    @register.inclusion_tag("classification.html") #引入一套模板语法,构建下面这几个就是为了传给模板里边的base.html的col-md-3让它去渲染了 ,可以把它单独拿开放到classfication.html
    def get_classification_style(username): #如果是封装成函数,一调用就返回数据,而它还可以把数据交给一个模板,把数据和样式结合成一个整体
        user = models.UserInfo.objects.filter(username=username).first() #个人站点对象
        blog = user.blog
        cate_list = models.Category.objects.filter(blog=blog).annotate(c = Count("article__title")).values_list("title", "c")
        tag_list = models.Tag.objects.filter(blog=blog).values("pk").annotate(c = Count("article")).values_list("title","c")
        date_list = models.Article.objects.filter(user=user).extra(select={"y_m": "date_format(create_time,'%%Y-%%m')"}).values("y_m").annotate(c=Count("nid")).values_list("y_m","c")
        return {"blog":blog, "cate_list":cate_list, "tag_list":tag_list, "date_list":date_list}  #先解读上边这些数据,然后返回一个字典给classification.htl,渲染之后就是真正的html了,
        ##get_classification_style函数拿到的就是渲染之后的这个html文件。

    定义好标签之后,是在模板里边去使用。

    article_detail.html

    {% extends "base.html" %}
    
    {% block content %}
        {% load my_tags %}  //要先load下 ,相当于python的import
        {% multi_tag 3 9 %} // 27
    {% endblock %}

    base.html

    <div class="col-md-3 menu">
                {% load my_tags %}  //把原来在base.html里边的col-md-3的内容单独作为一个classification.html,然后再load下把它引入进来。
                {% get_classification_style username %} //把那一堆html代码又返回到这个地方来了
    </div>

    classificition.html 

    <div>
        <div class="panel panel-warning">
                    <div class="panel-heading">我的标签</div>
                    <div class="panel-body">
                        {% for tag in tag_list %}
                        <p><a href="/{{ username }}/tag/{{ tag.0 }}">{{ tag.0 }}({{ tag.1 }})</a></p>
    
                        {% endfor %}
                    </div>
                </div>
        <div class="panel panel-danger">
                    <div class="panel-heading">随笔分类</div>
                    <div class="panel-body">
                        {% for cate in cate_list %}
                        <p><a href="/{{ username }}/category/{{ cate.0 }}"> {{ cate.0 }}({{ cate.1 }})</a></p>
                        {% endfor %}
                    </div>
                </div>
        <div class="panel panel-success">
                    <div class="panel-heading">随笔归档</div>
                    <div class="panel-body">
                        {% for date in date_list %}
                        <p><a href="/{{ username }}/archive/{{ date.0 }}"> {{ date.0 }}({{ date.1 }})</a></p>
                        {% endfor %}
                    </div>
                </div>
    </div>

    home_site.html

    {% extends 'base.html' %}
    
    {% block content %}
    <div class="article_list">
                    {% for article in article_list %}
                    <div class="article-item clearfix">
                        <h5><a href="">{{ article.title }}</a> </h5>
                        <div class="article-desc">
                            {{ article.desc }}
                        </div>
                        <div class="small pub_info pull-right">
                            <span>发布于&nbsp;&nbsp;{{ article.create_time|date:"Y-m-d H:i" }}</span>&nbsp;&nbsp;&nbsp;
                            <span class="glyphicon glyphicon-comment"></span>评论({{ article.comment_count }})&nbsp;&nbsp;&nbsp;
                            <span class="glyphicon glyphicon-thumbs-up"></span>点赞({{ article.up_count }})
                        </div>
                    </div>
                        <hr>
                    {% endfor %}
                </div>
    {% endblock %}

     views.py的视图函数访问home_site.html进行渲染,同时继承了base.html进行渲染,渲染base的时候会去调用get_classification_style,先取数据再去交给classification.html这套样式渲染,渲染之后的结果再放到这个col-md-3中,

    views.py

    def home_site(request, username, **kwargs):
        '''
        个人站点视图
        :param request:
        :param username:
        :return:
        '''
        print("kwargs", kwargs) #区分访问的是站点页面还是站点下的跳转页面
        print("username", username)
        user = UserInfo.objects.filter(username = username).first()  #过滤
        #判断用户是否存在
        if not user:
            return render(request, "not_found.html")
        #查询当前站点对象
        blog = user.blog
    
        #当前用户或者当前站点对应所有文章
        #基于对象查询
        #articile_list = user.article_set.all()
        #基于__
        article_list = models.Article.objects.filter(user=user)
        if kwargs:
            condition = kwargs.get("condition")
            param = kwargs.get("param") #2012-12
            if condition == "category": #http://127.0.0.1:8000/egon/category/egon的web/
                article_list = article_list.filter(category__title=param)
            elif condition == "tag": #http://127.0.0.1:8000/egon/tag/web/
                article_list = article_list.filter(tags__title=param)
            else:
                year, month = param.split("-") #http://127.0.0.1:8000/egon/archive/2018-07/
                article_list = article_list.filter(create_time__year=year, create_time__month=month)
        def get_classification_data(username):
        user = UserInfo.objects.filter(username=username).first() #个人站点对象
        blog = user.blog
        cate_list = models.Category.objects.filter(blog=blog).annotate(c = Count("article__title")).values_list("title", "c")
        tag_list = models.Tag.objects.filter(blog=blog).values("pk").annotate(c = Count("article")).values_list("title","c")
        date_list = models.Article.objects.filter(user=user).extra(select={"y_m": "date_format(create_time,'%%Y-%%m')"}).values("y_m").annotate(c=Count("nid")).values_list("y_m","c")
        return {"blog":blog, "cate_list":cate_list, "tag_list":tag_list, "date_list":date_list}
    
    def article_detail(request, username, article_id):
    
        #context = get_classification_data(username)
        return render(request, "article_detail.html", locals())

    3.文章详情页渲染的标签字符串转义

    def article_detail(request, username, article_id):
        '''
        文章详情页
        :param request:
        :param username:
        :param article_id:
        :return:
        '''
        user = models.UserInfo.objects.filter(username=username).first() #个人站点对象
        blog = user.blog
        article_obj = models.Article.objects.filter(pk=article_id).first() #拿到文章对象,要传到模板里边去
        # context = get_classification_data(username)
        comment_list = models.Comment.objects.filter(article_id=article_id)
        return render(request, "article_detail.html", locals())

    article_detail.html 

    {% extends "base.html" %}
    
    {% block content %}
    {#    {% load my_tags %}#}
    {#    {% multi_tag 3 9 %}#}
        <h3 class="text-center">{{ article_obj.title }}</h3>
        <div class="cont">
           {{ article_obj.content |safe }} {# 加这个是为了告诉django的模板不要给我做任何转义,为了安全性;网页源码#}
        </div>
    
    {% endblock %}

     

    作为一个用户提交了JS代码,相当于我可以控制了其他看到这篇文章的用户的浏览器了,可以通过js代码去控制其他信息。这叫XSS恶意攻击。

    Django加了safe转义了给你变成了特殊符号。作为开发人员,在用户提交的时候,不应该允许他提交。

     

  • 相关阅读:
    java web 自定义的权限框架
    java web 中 读取windows图标并显示
    apache httpclient
    Gson json解析工具
    org.apache.commons
    ehcache 缓存管理工具
    springmvc集成Freemarke配置的几点
    SaltStack与ZeroMQ(二)
    Python中的__init__和__new__介绍
    TCP 介绍
  • 原文地址:https://www.cnblogs.com/shengyang17/p/9418334.html
Copyright © 2011-2022 走看看