zoukankan      html  css  js  c++  java
  • 博客系统作业

    博客系统

    1 搞清楚需求(产品经理) 

      1,基于用户认证组件和Ajax实现登录验证(图片验证码)
      2,基于forms组件和Ajax实现注册功能
      3,设计系统首页(文章列表渲染)
      4,设计个人站点页面
      5,文章详情页
      6,实现文章点赞功能
      7,实现文章评论功能
        ---文章的评论
        ---评论的评论
      8,富文本编辑框和防止xss攻击

    2 设计表结构



    from django.contrib.auth.models import User,AbstractUser
     
      class UserInfo(AbstractUser):
        """用户信息"""
        nid=models.AutoField(primary_key=True)
        telephone=models.CharField(max_length=11,null=True,unique=True)
        avatar=models.FileField(upload_to='avatars/',default="/avatars/default.png")
        create_time=models.DateTimeField(verbose_name='创建时间',auto_now_add=True)
        blog=models.OneToOneField(to='blog',to_field='nid',null=True)
        def __str__(self):
            return self.username
            
      class Blog(models.Model):
        """博客信息表(站点表)"""
        nid=models.AutoField(primary_key=True)
        title=models.CharField(verbose_name='个人博客标题',max_length=64)
        site_name=models.CharField(verbose_name='站点名称',max_length=64)
        theme=models.CharField(verbose_name='博客主题',max_length=32)
        
        def __str__(self):
            return self.title
    
      class Category(models.Model):
        """博主个人文章分类表"""
        nid=models.AutoField(primary_key=True)
        title=models.CharField(verbose_name='分类标题',max_length=32)
        blog=models.ForeignKey(verbose_name='所属博客',to='Blog',to_field='nid')
        
        def __str__(self):
            return self.title
    
      class Tag(models.Model):
        nid=models.AutoField(primary_key=True)
        title=models.CharField(verbose_name='标签名称',max_length=32)
        blog=models.ForeignKey(verbose_name='所属博客',to='Blog',to_field='nid')
        
        def __str__(self):
            return self.title        
    
      class Article(models.Model):
        nid=models.AutoField(primary_key=True)
        title=models.CharField(verbose_name='文章标题',max_length=50)
        desc=models.CharField(verbose_name='文章描述',max_length=255)
        create_time=models.DateTimeField(verbose_name='创建时间',auto_now_add=True)
        content=models.TextField()
        
        comment_count=models.IntegerField(default=0)
        up_count=models.IntegerField(default=0)
        down_count=models.IntegerField(default=0)
        
        user=models.ForeignKey(verbose_name='作者',to='UserInfo',to_field='nid')
        category=models.ForeignKey(to="Category",to_field='nid',null=True)
        tags=models.ManyToManyField(
            to='Tag',
            through='Article2Tag',
            through_fields=('article','tag'),
        )
    
        def __str__(self):
            return self.title        
    
      class Article2Tag(models.Model):
        nid=models.AutoField(primary_key=True)
        article=models.ForeignKey(verbose_name='文章',to='Article',to_field='nid')
        tag=models.ForeignKey(verbose_name='标签',to='Tag',to_field='nid')
        
        class Meta:
            unique_together=[
                ('article','tag'),
            ]
        def __str__(self):
            v=self.article.title + '---' + self.tag.title
            return v        
    
      class ArticleUpDown(models.Model):
        """点赞表"""
        nid=models.AutoField(primary_key=True)
        user=models.ForeignKey('UserInfo',null=True)
        article=models.ForeignKey('Article',null=True)
        is_up=models.BooleanField(default=True)
        
        class Meta:
            unique_together=[
                ('article','user'),
            ]
    
      class Comment(models.Model):
        """评论表"""
        nid=models.AutoField(primary_key=True)
        article=models.ForeignKey(verbose_name='评论文章',to='Article',to_field='nid')
        user=models.ForeignKey(verbose_name='评论者',to='UserInfo',to_field='nid')
        content=models.CharField(verbose_name='评论内容',max_length=255)
        create_time=models.DateTimeField(verbose_name='创建时间',auto_now_add=True)
        parent_comment=models.ForeignKey('self',null=True)
        
        def __str__(self):
            return self.content
    View Code       

    3 按着每一个功能进行开发

     验证码

    示例代码:

    # #!/usr/bin/python3
    # # -*- coding: utf-8 -*-
    # # @Time    : 2018/8/30 9:51
    # # @File    : validCode.py
    #
    
    import random
    import sys, os
    
    
    def get_random_color():
        return random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)
    
    
    def get_valid_code_img(request):
        # 方式1:
        # pa_base = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
        # pa_img = os.path.join(pa_base, r'mediaavatarslufei.jpg')
        # with open(pa_img, "rb") as f:
        #     data = f.read()
    
        # 方式2:  # pip install pillow
    
        # from PIL import Image
        #
        # img = Image.new("RGB", (270, 40), color=get_random_color())
        #
        # with open("validCode.png", "wb") as f:
        #     img.save(f, "png")
        #
        # with open("validCode.png", "rb") as f:
        #     data = f.read()
    
        # 方式3:
    
        # from PIL import Image
        # from io import BytesIO
        #
        # img = Image.new("RGB", (270, 40), color=get_random_color())
        # f = BytesIO()
        # img.save(f, "png")
        # data = f.getvalue()
        # 方式4:
    
        from PIL import Image, ImageDraw, ImageFont
        from io import BytesIO
        import random
    
        img = Image.new("RGB", (270, 40), color=get_random_color())
    
        draw = ImageDraw.Draw(img)
        kumo_font = ImageFont.truetype("static/font/kumo.ttf", size=32)
    
        valid_code_str = ""
        for i in range(5):
            random_num = str(random.randint(0, 9))
            random_low_alpha = chr(random.randint(95, 122))
            random_upper_alpha = chr(random.randint(65, 90))
            random_char = random.choice([random_num, random_low_alpha, random_upper_alpha])
            draw.text((i * 50 + 20, 5), random_char, get_random_color(), font=kumo_font)
    
            # 保存验证码字符串
            valid_code_str += random_char
    
        width = 270
        height = 40
        for i in range(10):
            x1 = random.randint(0, width)
            x2 = random.randint(0, width)
            y1 = random.randint(0, height)
            y2 = random.randint(0, height)
            draw.line((x1, y1, x2, y2), fill=get_random_color())
    
        for i in range(100):
            draw.point([random.randint(0, width), random.randint(0, height)], fill=get_random_color())
            x = random.randint(0, width)
            y = random.randint(0, height)
            draw.arc((x, y, x + 4, y + 4), 0, 90, fill=get_random_color())
    
        print("valid_code_str", valid_code_str)
    
        # request.session["valid_code_str"] = valid_code_str
    
        '''
        1 sdajsdq33asdasd
        2 COOKIE {"sessionid":sdajsdq33asdasd}
        3 django-session
          session-key       session-data
          sdajsdq33asdasd   {"valid_code_str":"12345"}
    
    
        '''
    
        f = BytesIO()
        img.save(f, "png")
        data = f.getvalue()
    
        return data
    View Code

    view中调用:

    def get_valid_code_img(request):
        """
        基于PIL模块动态生成响应状态码图片
        :param request:
        :return:
        """
        img_data = validCode.get_valid_code_img(request)
    
        return HttpResponse(img_data)
    View Code

    登录页面login.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <link rel="stylesheet" href="/static/blog/bs/css/bootstrap.css">
    
    </head>
    <body>
    <h3>登录页面</h3>
    <div class="container">
        <div class="row">
            <div class="col-md-6 col-lg-offset-3">
    
                <form>
                    {% csrf_token %}
                    <div class="form-group">
                        <label for="user">用户名</label>
                        <input type="text" id="user" class="form-control">
                    </div>
                    <div class="form-group">
                        <label for="pwd">密码</label>
                        <input type="password" id="pwd" class="form-control">
                    </div>
    
    
                    <div class="form-group">
                        <label for="pwd">验证码</label>
                        <div class="row">
                            <div class="col-md-6">
                                <input type="text" class="form-control" id="valid_code">
                            </div>
                            <div class="col-md-6">
                                <img width="270" height="36" id="valid_code_img" src="/my_demo2/get_valid_code_img/" alt="">
                            </div>
                        </div>
                    </div>
    
    
                    <input type="button" class="btn btn-default login_btn" value="submit"><span class="error"></span>
                    <a href="/register/" class="btn btn-success pull-right">注册</a>
                </form>
    
            </div>
        </div>
    </div>
    
    
    <script src="/static/js/jquery-3.2.1.min.js"></script>
    <script>
    
        // 刷新验证码
        $("#valid_code_img").click(function () {
    
            $(this)[0].src += "?"
    
        });
    
        // 登录验证
        $(".login_btn").click(function () {
    
    
            $.ajax({
                url: "/my_demo2/get_valid_code_img/",
                type: "post",
                data: {
                    user: $("#user").val(),
                    pwd: $("#pwd").val(),
                    valid_code: $("#valid_code").val(),
                    csrfmiddlewaretoken: $("[name='csrfmiddlewaretoken']").val(),
                },
                success: function (data) {
                    console.log(data);
    
                    if (data.user) {
                        if (location.search) {
                            location.href = location.search.slice(6)
                        }
                        else {
                            location.href = "/index/"
                        }
    
                    }
                    else {
                        $(".error").text(data.msg).css({"color": "red", "margin-left": "10px"});
                        setTimeout(function () {
                            $(".error").text("");
                        }, 1000)
    
                    }
                }
            })
    
        })
    
    </script>
    </body>
    </html>
    View Code

     admin使用

    1,在app应用下的admin.py中添加相关models中的所有类

    from django.contrib import admin
    
    # Register your models here.
    from blog import models
    
    admin.site.register(models.UserInfo)
    admin.site.register(models.Tag)
    admin.site.register(models.Article)
    admin.site.register(models.Article2Tag)
    admin.site.register(models.ArticleUpDown)
    admin.site.register(models.Category)
    admin.site.register(models.Comment)
    admin.site.register(models.Blog)
    View Code

    2,google中打开网址:http://127.0.0.1:8000/admin,根据逻辑添加相关数据

     media组件

    settings.py

    # 与用户上传相关的配置
    MEDIA_ROOT = os.path.join(BASE_DIR, "media")
    MEDIA_URL = "/media/"
    

    urls.py

    # media配置:
        re_path(r"media/(?P<path>.*)$", serve, {"document_root": settings.MEDIA_ROOT}),
    

     注册功能头像示例代码

    # 头像文件获取
                avator_obj = request.FILES.get("avator")
                extra = {}
                if avator_obj:
                    extra["avatar"] = avator_obj
                UserInfo.objects.create_user(username=user, password=pwd, email=email, **extra)
    

     日期处理

    mysql中

    date_format
    
    ============date,time,datetime===========
    
    create table t_mul_new(d date,t time,dt datetime);
    
    insert into t_mul_new values(now(),now(),now());
    
    select * from t_mul;
    
    
    mysql> select * from t_mul;
    +------------+----------+---------------------+
    | d          | t        | dt                  |
    +------------+----------+---------------------+
    | 2017-08-01 | 19:42:22 | 2017-08-01 19:42:22 |
    +------------+----------+---------------------+
    1 row in set (0.00 sec)
    
    
    select date_format(dt,"%Y/%m/%d") from t_mul;
    View Code

    extra介绍

    extra(select=None, where=None, params=None, tables=None, order_by=None, select_params=None)
    
    有些情况下,Django的查询语法难以简单的表达复杂的 WHERE 子句,对于这种情况, Django 提供了 extra() QuerySet修改机制 — 它能在 QuerySet生成的SQL从句中注入新子句
    
    extra可以指定一个或多个 参数,例如 select, where or tables. 这些参数都不是必须的,但是你至少要使用一个!要注意这些额外的方式对不同的数据库引擎可能存在移植性问题.(因为你在显式的书写SQL语句),除非万不得已,尽量避免这样做
    

    extra 参数之select

    The select 参数可以让你在 SELECT 从句中添加其他字段信息,它应该是一个字典,存放着属性名到 SQL 从句的映射。
    queryResult=models.Article.objects.extra(select={'is_recent': "create_time > '2017-09-05'"})
    结果集中每个 Entry 对象都有一个额外的属性is_recent, 它是一个布尔值,表示 Article对象的create_time 是否晚于2017-09-05.
    
    练习:
    # 查询当前站点每一个年月的名称以及对应的文章数
    in sqlite:
    
        article_obj=models.Article.objects.extra(select={"standard_time":"strftime('%%Y-%%m-%%d',create_time)"}).values("standard_time","nid","title")
        print(article_obj)
        # <QuerySet [{'title': 'MongoDb 入门教程', 'standard_time': '2017-09-03', 'nid': 1}]>
    
    in mysql
        # ret=models.Article.objects.extra(select={"is_recent":"create_time > '2018-09-05'"}).values("title","is_recent")
        # print(ret)
    
        # 方式1:
        # date_list=models.Article.objects.filter(user=user).extra(select={"y_m_date":"date_format(create_time,'%%Y/%%m')"}).values("y_m_date").annotate(c=Count("nid")).values_list("y_m_date","c")
        # print(date_list)
    
    
        # 方式2:
    
        # from django.db.models.functions import TruncMonth
        #
        # ret=models.Article.objects.filter(user=user).annotate(month=TruncMonth("create_time")).values("month").annotate(c=Count("nid")).values_list("month","c")
        # print("ret----->",ret)
    View Code

     TruncMonth日期归档查询的方式

    from django.db.models.functions import TruncMonth
    
    Sales.objects
        .annotate(month=TruncMonth('timestamp'))  # Truncate to month and add to select list
        .values('month')                          # Group By month
        .annotate(c=Count('id'))                  # Select the count of the grouping
        .values('month', 'c')                     # (might be redundant, haven't tested) select month and count 
    View Code

     base页面(函数)

    基础页面中

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

     业务页面

    {% extends 'base.html' %}
    {% block content %}
    相关html代码
    
    {% endblock %}
    

     view函数(三个列表参数都需要传cate_list、date_list、tag_list)

    def get_classification_data(username):
        user = UserInfo.objects.filter(username=username).first()
        blog = user.blog
    
        cate_list = models.Category.objects.filter(blog=blog).values("pk").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": "date_format(create_time,'%%Y/%%m')"}).values("y_m_date").annotate(
            c=Count("nid")).values_list("y_m_date", "c")
    
        return {"blog": blog, "cate_list": cate_list, "date_list": date_list, "tag_list": tag_list}
    
    
    def article_detail(request, username, article_id):
        """
        文章详情页
        :param request:
        :param username:
        :param article_id:
        :return:
        """
        context = get_classification_data(username)
        return render(request, "article_detail.html", context)
    View Code
    def home_site(request, username, **kwargs):
        """
        个人站点
        :param request:
        :param username:
        :return:
        """
        user = UserInfo.objects.filter(username=username).first()
        # 判断用户是否存在!
        if not user:
            return render(request, "not_found.html")
    
        # 查询当前站点对象
    
        blog = user.blog
        article_list = models.Article.objects.filter(user=user)
    
        if kwargs:
            condition = kwargs.get("condition")
            param = kwargs.get("param")  # 2012-12
    
            if condition == "category":
                article_list = article_list.filter(category__title=param)
            elif condition == "tag":
                article_list = article_list.filter(tags__title=param)
            else:
                year, month = param.split("/")
                article_list = article_list.filter(create_time__year=year, create_time__month=month)
        print(article_list)
        print(article_list.query)
        # # 1 当前用户或者当前站点对应所有文章
        # ret = models.Article.objects.filter(user=user).all()
        # print(ret)
        # # 每一个后的表模型.objects.values("pk").annotate(聚合函数(关联表__统计字段)).values("表模型的所有字段以及统计字段")
        # # 查询每一个分类名称以及对应的文章数
        # ret_cate = models.Category.objects.values("pk").annotate(c=Count("article")).values("title", "c")
        # print(ret_cate)
        #
        # # 查询当前站点的每一个分类名称以及对应的文章数
        cate_list = models.Category.objects.filter(blog=blog).values("pk").annotate(c=Count("article__title")).values_list(
            "title", "c")
        # print(cate_list)
        #
        # # 查询当前站点的每一个标签名称以及对应的文章数
        tag_list = models.Tag.objects.filter(blog=blog).values("pk").annotate(c=Count("article")).values_list("title", "c")
        # print(tag_list)
        date_list = models.Article.objects.filter(user=user).extra(
            select={"y_m_date": "date_format(create_time,'%%Y/%%m')"}).values("y_m_date").annotate(
            c=Count("nid")).values_list("y_m_date", "c")
        # print(date_list)
    
        return render(request, "home_site.html",
                      {"username": username, "blog": blog, "article_list": article_list, "tag_list": tag_list,
                       "cate_list": cate_list, "date_list": date_list, })
    View Code

     base页面(标签)

    blog应用下新建templatetags文件夹(py)

    my_tag.py

    from django import template
    from django.db.models import Count
    from blog import models
    
    register = template.Library()
    
    
    @register.simple_tag
    def multi_tag(x, y):
        return x * y
    
    
    @register.inclusion_tag("classification.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).values("pk").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": "date_format(create_time,'%%Y/%%m')"}).values("y_m_date").annotate(
            c=Count("nid")).values_list("y_m_date", "c")
    
        return {"blog": blog, "cate_list": cate_list, "date_list": date_list, "tag_list": tag_list}
    View Code

    简单调用tag

    {% load my_tags %}
    {% multi_tag 3 9 %}
    {% load my_tags %}
    {% get_classification_style username %}

     视图函数

    def home_site(request, username, **kwargs):
        """
        个人站点
        :param request:
        :param username:
        :return:
        """
        user = UserInfo.objects.filter(username=username).first()
        # 判断用户是否存在!
        if not user:
            return render(request, "not_found.html")
    
        # 查询当前站点对象
    
        blog = user.blog
        article_list = models.Article.objects.filter(user=user)
    
        if kwargs:
            condition = kwargs.get("condition")
            param = kwargs.get("param")  # 2012-12
    
            if condition == "category":
                article_list = article_list.filter(category__title=param)
            elif condition == "tag":
                article_list = article_list.filter(tags__title=param)
            else:
                year, month = param.split("/")
                article_list = article_list.filter(create_time__year=year, create_time__month=month)
    
        return render(request, "home_site.html",
                      {"username": username, "blog": blog, "article_list": article_list})
    
    
    def article_detail(request, username, article_id):
        """
        文章详情页
        :param request:
        :param username:
        :param article_id:
        :return:
        """
        user = UserInfo.objects.filter(username=username).first()
        blog = user.blog
        return render(request, "article_detail.html", locals())
    View Code

     classification.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>
    View Code

     评论es6显示

    页面反引号,视图传参

    html代码
    success: function (data) {
        var create_time = data.create_time;
        var username = data.username;
        var content = data.content;
    
        var s = `<li class="list-group-item">
            <div>
                <span>${create_time}</span>&nbsp;&nbsp;
                <a href=""><span>${username}</span></a>
            </div>
            <div class="comment_con">
                <p>${content}</p>
            </div>
    
        </li>`;
        $("ul.comment_list").append(s);
    }
    view代码:
    def comment(request):
        article_id = request.POST.get("article_id")
        pid = request.POST.get("pid")
        content = request.POST.get("content")
        user_id = request.user.pk
        comment_obj = models.Comment.objects.create(user_id=user_id, article_id=article_id, content=content,
                                                    parent_comment_id=pid)
    
        response = {"create_time": comment_obj.create_time.strftime("%Y-%m-%d %X"), "username": request.user.username,
                    "content": content, }
        
        return JsonResponse(response)
    View Code

     回复按钮

    点击回复,焦点进入文本框立马失去焦点:a标签中属性href要去掉

    html代码
    <a class="pull-right reply_btn" username="{{ comment.user.username }}">回复</a>
    js代码
    // 回复
    $(".reply_btn").click(function () {
        $("#comment_content").focus();
        var val = "@" + $(this).attr("username") + "
    ";
        $('#comment_content').val(val);
    });
    View Code

     评论数

    视图返回[{},{}],页面遍历拼装渲染数据

    视图:
    def get_comment_tree(request):
        article_id = request.GET.get("article_id")
        response = list(models.Comment.objects.filter(article_id=article_id).order_by("pk").values("pk", "content",
                                                                                                   "parent_comment_id"))
    
        return JsonResponse(response, safe=False)
    页面
    <p class="tree_btn">评论树</p>
    <div class="comment_tree">
    
    </div>
    <script>
        $(".tree_btn").click(function () {
            $.ajax({
                url: "/get_comment_tree/",
                type: "get",
                data: {
                    article_id: "{{ article_obj.pk }}"
                },
                success: function (comment_list) {
                    console.log(comment_list);
    
                    $.each(comment_list, function (index, comment_object) {
                        var pk = comment_object.pk;
                        var content = comment_object.content;
                        var parent_comment_id = comment_object.parent_comment_id;
                        var s = '<div class="comment_item" comment_id=' + pk + '><span>' + content + '</span></div>';
    
                        if (!parent_comment_id) {
                            $(".comment_tree").append(s);
                        } else {
                            $("[comment_id=" + parent_comment_id + "]").append(s);
                        }
                    });
                }
            })
        });
    </script>    
    样式:
    .comment_item {
        margin-left: 20px;
    }
    View Code

     事务

    from django.db import transaction
    # 事务操作
    with transaction.atomic():
    	comment_obj = models.Comment.objects.create(user_id=user_id, article_id=article_id, content=content,
    												parent_comment_id=pid)
    	models.Article.objects.filter(pk=article_id).update(comment_count=F("comment_count") + 1)
    

    发送邮件

    单独启动线程发送比较效率高

    视图代码:
    
    article_obj = models.Article.objects.filter(pk=article_id).first()
    # 发送邮件
    
    from django.core.mail import send_mail
    from cnblog import settings
    
    # send_mail(
    #     "您的文章%s新增了一条评论内容"%article_obj.title,
    #     content,
    #     settings.EMAIL_HOST_USER,
    #     ["916852314@qq.com"]
    # )
    
    # 效率高,时间短
    import threading
    
    t = threading.Thread(target=send_mail, args=("您的文章%s新增了一条评论内容" % article_obj.title,
                                                 content,
                                                 settings.EMAIL_HOST_USER,
                                                 ["916852314@qq.com"])
                         )
    t.start()
    
    setting代码:
    
    EMAIL_HOST = 'smtp.exmail.qq.com'  # 如果是 163 改成 smtp.163.com
    EMAIL_PORT = 465        # 如果是 163 改成 25
    EMAIL_HOST_USER = ''           # 帐号
    EMAIL_HOST_PASSWORD = ''  # 密码
    # DEFAULT_FROM_EMAIL = EMAIL_HOST_USER  # 这个打开后view中 settings.EMAIL_HOST_USER可以不加
    EMAIL_USE_SSL = True
    View Code

     safe使用

    文章内容直接存F12样式中的代码,显示加|safe

    <div class="cont">
            {{ article_obj.content|safe }}
        </div>
    

    kindeditor编辑器

    添加文章
    
    首页:kindeditor.net/doc.php
    上传路径:uploadJson:"/upload/",
    是否可拉伸:resizeType:0,
    csrf阻止:extraFileUploadParams:{
                csrfmiddlewaretoken:$("[name='csrfmiddlewaretoken']").val()
            },
    指定传入视图的键:filePostName:"upload_img"
    
    setting.py代码:
    
    # 文本编辑器上传图片url
    path('upload/', views.upload),
    
    views.py代码:
    
    def upload(request):
        """
        编辑器上传文件接受视图函数
        :param request:
        :return:
        """
    
        print(request.FILES)
        img_obj=request.FILES.get("upload_img") # 文件对象
        print(img_obj.name)
    
        path=os.path.join(settings.MEDIA_ROOT,"add_article_img",img_obj.name) # 指定文件上传的路径
    
        with open(path,"wb") as f:
    
            for line in img_obj:
                f.write(line)
        # 把上传的图像返回给编辑器
        response = {
            "error":0,
            "url":"/media/add_article_img/%s"%img_obj.name #编辑器可以识别的路径,直接浏览器可以访问的路径
        }
        import json # 编辑器需要json数据
        return HttpResponse(json.dumps(response))
    
        return HttpResponse("ok")
    View Code

    摘要样式乱:

    desc = content[0:150] # 如果文章是标签html,可以把标签截取断,样式乱
    desc=soup.text[0:150]+"..."	
    

     bs4防止xss攻击

    xss提交html代码要使用html模式,不是文本模式

    from bs4 import BeautifulSoup
    soup=BeautifulSoup(content,"html.parser") # html.parser解析器会把所有html标签解析掉
    desc=soup.text[0:150]+"..."  # 去标签之后的文本
    
    视图代码:
    def add_article(request):
        """
        后台管理的添加书籍视图函数
        :param request:
        :return:
        """
        if request.method == "POST":
            title = request.POST.get("title")
            content = request.POST.get("content")
            # 防止xss攻击,过滤script标签
            soup = BeautifulSoup(content, "html.parser")
            for tag in soup.find_all():
    
                print(tag.name)
                if tag.name == "script":
                    tag.decompose()
            # 构建摘要数据,获取标签字符串的文本前150个符号
    
            desc = soup.text[0:150] + "..."
    
            models.Article.objects.create(title=title, desc=desc, content=content, user=request.user)
            return redirect("/cn_backend/")
    
        return render(request, "backend/add_article.html")
    
    
    简单示例:
    from bs4 import BeautifulSoup
    
    s = "<h1>hello</h1><span>123</span><script>alert(123)</script>"
    
    soup = BeautifulSoup(s, "html.parser")
    
    # print(soup.text)
    
    print(soup.find_all())  # [<h1>hello</h1>, <span>123</span>, <script>alert(123)</script>]
    
    for tag in soup.find_all():
    
        print(tag.name)
        if tag.name == "script":
            tag.decompose()  # 删除掉script标签以及内容
    
    print(str(soup))  # <h1>hello</h1><span>123</span>
    View Code

    pycharm无法安装新模块

    pycharm无法安装新模块
    报错:
    AttributeError: module 'pip' has no attribute 'main'
    解决:
    
    找到安装目录下 helpers/packaging_tool.py文件,找到如下代码:
    def do_install(pkgs):
        try:
            import pip
        except ImportError:
            error_no_pip()
        return pip.main(['install'] + pkgs)
    
    
    def do_uninstall(pkgs):
        try:
            import pip
        except ImportError:
            error_no_pip()
        return pip.main(['uninstall', '-y'] + pkgs)
        
    修改为:
    
    def do_install(pkgs):
        try:
            #import pip
            try:
                from pip._internal import main
            except Exception:
                from pip import main
        except ImportError:
            error_no_pip()
        return main(['install'] + pkgs)
    
    
    def do_uninstall(pkgs):
        try:
            #import pip
            try:
                from pip._internal import main
            except Exception:
                from pip import main
        except ImportError:
            error_no_pip()
        return main(['uninstall', '-y'] + pkgs)        
    View Code

    4 功能测试


    5 项目部署上线

  • 相关阅读:
    Chp18: Hard
    内存泄漏 和 内存溢出
    Chp4: Trees and Graphs
    trie树--详解
    Tries
    Comparable & Comparator
    memory leak
    8个月从CS菜鸟到拿到Google Offer的经历+内推
    Word Ladder II
    Java垃圾回收机制
  • 原文地址:https://www.cnblogs.com/fmgao-technology/p/9546130.html
Copyright © 2011-2022 走看看