zoukankan      html  css  js  c++  java
  • BBS+ BLOG系统(仿博客园)

    一、基本要求

    作业题目:开发BBS+BLOG系统

    作业需求:

    1 基于ajax和用户认证组件实现登录验证
    2 基于ajax和form组件实现注册功能
    3 系统首页文章列表的渲染
    4 个人站点页面设计
    5 文章详细页的继承
    6 点赞与踩灭
    7 评论功能
    8 富文本编辑器的使用
    9 防止xss攻击

    评论处、上传文章处都要防止xss攻击--凡是向网站输入内容的都要防止

    博客系统开发:

    1.注册,登录,首页
    2.个人站点,分组:(分类,标签,归档)
    3.文章详细页
    4.点赞,踩灭
    5.评论楼,评论树
    6.后台管理,发布文章,文件上传
    7.BeautifulSoup
    8.日志

    ----

    演示内容,

    1、注册输入为空,输入已注册过的信息提交

    2、登录为空、输入错误提交

    3、展示首页---注销--重新输入---

    4、个人站点--展示--进入文章详情页

    5、评论--点赞---防xss攻击评论

    6、后台管理--先正常文字图片---在防xss攻击编辑

     一、项目流程:

    项目流程:
    
    1 搞清楚需求(产品经理)
    
      (1) 基于用户认证组件和Ajax实现登录验证(图片验证码)
    
      (2) 基于forms组件和Ajax实现注册功能
    
      (3) 设计系统首页(文章列表渲染)
    
      (4) 设计个人站点页面---跨表查询,分组查询
    
      (5) 文章详情页
    
      (6) 实现文章点赞功能
    
      (7) 实现文章的评论
          ---文章的评论
          ---评论的评论
    
      (8) 富文本编辑框 和 防止xss攻击(防止别人提交js代码)
    
    
    2 设计表结构
    
    
    3 按着每一个功能分别进行开发
      
    
    4 功能测试
    
    
    5 项目部署上线

     二、功能实现

    参考:

    https://www.cnblogs.com/venicid/p/9446064.html

    https://www.cnblogs.com/alice-bj/p/9160388.html

    1、注册、登录、注销、出错页面

     
        2) 注册
            /register/
        3) 登录
            /login/
            /get_validCode/     # 验证码
        4) 注销
            /logout/
        5) 404页面
            not_found.html

    基于用户认证组件和Ajax实现登录验证(图片验证码)
    基于forms组件和ajax实现注册功能

    --------

    引入Bootstrap
     <h3 class="text-primary text-center">注册页面</h3>
    <form>
    <div class="form-group   ">
    <label for="username">username</label>
     <input type="text" class="form-control " placeholder="username" id="username">
     </div>
     </form>

    2、主页、个人站点,文章详情页

    0) 主页 /index/

    1) 个人站点页面(分类、标签、归档) /alex/ 2) 文章详情页(分类、标签、归档) /alex/articles/4 /digg # 点赞 /comment # 评论 /get_comment_tree # 评论树展示 4)media开放目录 /media

    0 博客首页布局

    登录状态和未登陆状态的两种区别

    导航栏设计---Bootstrap--导航条

    主页左右栏设计补充

     知识点:
    
    1.bootstrap搭建页面
    
    2.导航条
        登录:   username / 注销
        未登录: 登录 / 注册
    
    3.for循环
         {% for article in article_list %}
         {% endfor %}

    1 个人站点

    ORM跨表与分组查询

    知识点:
    
    1.文章列表,分类列表,标签列表,日期归档列表
        文章列表:    
        分类列表:     
        标签列表:     
        日期归档列表: 
    
    2.模板继承
        {% extends 'base.html' %}
    
        {% block content %}
        {% endblock content%}}
    
    3.自定义标签
        /blog/templatetags/my_tag.py
    
        @register.inclusion_tag('')
        def get_menu(username):
            ...
            return {} # 去渲染 
    
    4.分组查询 .annotate() / extra()应用
        多表分组
            tag_list = Tag.objects.filter(blog=blog).annotate(
                count = Count('article')).values_list('title', 'count')
    
        单表分组 / DATE_FORMAT() /  extra()
            date_list = Article.objects.filter(user=user).extra(
                select={"create_ym": "DATE_FORMAT(create_time,'%%Y-%%m')"}).values('create_ym').annotate(
                c = Count('nid')).values_list('create_ym', 'c')
    
    5. 时间、区域配置
         TIME_ZONE = 'Asia/Shanghai'
         USE_TZ = False

    2、文章详情页的设计

     知识点:
    
    1.模板继承
        article = Article.objects.filter(pk=article_id).first()
        {% extends 'base.html' %}
        {% block content %}
             ...
            {{ article.articledetail.content|safe }}
        {% endblock content %}

    3、点赞、踩灭

     

    ----------------

    知识点:
    
    1.ajax的post
         var csrfmiddlewaretoken = $('input[name="csrfmiddlewaretoken"]').val();
    
    2.事务
        try:    # article_id 与 user_id 联合唯一 所有使用 try ... 
            with transaction.atomic():
                ArticleUpDown.objects.create(is_up=is_up, article_id=article_id, user_id=user_id)
                ...
                Article.objects.filter(pk=article_id).update(up_count=F('up_count')+1)
    
        except Exception as e:
            ...
    
    3.F查询:
        Article.objects.filter(pk=article_id).update(up_count=F('up_count')+1)

    4、评论楼、评论树

     ajax显示评论

    1.提交根评论
    2.显示根评论
        --- render显示
        --- ajax显示
    3.提交子评论
    4.显示子评论
        --- render显示
        --- ajax显示
    评论楼
    评论树
    1.ajax提交评论
        post (csrfmiddlewaretoken)
        pid = ""      根评论
        pid = value   子评论
    
    2.回复事件
        @alex
        val ="@" + $(this).attr('username')+ '
    ';
    
    3.事务
         with transaction.atomic():
            ...
            多个orm sql操作!
    
    4.F查询,更新
          Article.objects.filter(pk=article_id).update(comment_count=F("comment_count")+1)
    
     评论树:
    
    5.js匿名函数
        (function(){})()
    
    6.ajax get方式获取comment_list
        $.each(comment_list,function(index,comment)){
            ...
            s = '...'
            if(pid){   //子评论
                $('#'+pid).append(s)
            }else{     //根评论
                $('.comment_tree').append(s)
            }
        }
    
    7.JsonResponse() 返回 non-dict objects 需要 safe=False
        def get_comment_tree(request, article_id):
            ret = list(Comment.objects.filter(article_id=article_id).values(
                'pk', 'content', 'parent_comment_id', 'user__username').order_by('nid'))
    
            return JsonResponse(ret, safe=False)

    5、后台管理、KindEditor、BeautifulSoup

     /cn_backend                # 主页
        /cn_backend/add_article/    # 添加文章
        /cn_backend/edit_article/4   # 编辑文章
        /delete                     # 删除

     知识点:
    
    1.新建APP(backend)
        settings:
            INSTALLED_APPS = [..., 'backend.apps.BackendConfig',]
    
    2.url分配
         re_path(r'backend/', include(('backend.urls', 'backend'))),
    
    3.认证装饰器
        @login_required
        settings:
            LOGIN_URL = '/login/'
    
    4.static配置
        STATIC_URL = '/static/'
        STATICFILES_DIRS = [
            os.path.join(BASE_DIR, 'blog', 'static'),
            os.path.join(BASE_DIR, 'backend', 'static'),
        ]
    
    5.编辑器(KindEditor)
        <textarea name="article_con" id="article_box" cols="30" rows="10"></textarea>
        <script src="/static/kindeditor/kindeditor-all.js"></script>
         KindEditor.ready(function (k) {
            window.editor = k.create('#article_box', {
                ...
                ...
                uploadJson: 'upload_img/',
                extraFileUploadParams: {"csrfmiddlewaretoken":$('input[name="csrfmiddlewaretoken"]').val()},
                filePostName: 'img'
            })
         })
    
    6.文件上传
        用户文件存在 /media/article_imgs/...
            media_path = settings.MEDIA_ROOT
            path = os.path.join(media_path, 'article_imgs', img_obj.name)
        返回json
            img_obj = request.FILES.get('img')
            res = {
                "url": "/media/article_imgs/"+img_obj.name,
                "error": 0
            }
            return HttpResponse(json.dumps(res))
    
    7.发布文章
        防止XSS攻击 BeautifulSoup,对网页,解析数据
    
        article_con = request.POST.get('article_con')
        soup = BeautifulSoup(article_con, 'html.parser')
    
        # 过滤script, 删除了所有的script标签
        for tag in soup.find_all():
            if tag.name == 'script':
                tag.decompose()
    
        # soup.prettify() == str(soup)
        return redirect(reverse('backend:index'))

    三、所用技术概述

    1、验证用户是否登录:用户认证组件
    
    实质:session会话跟踪技术
    from django.contrib import auth
    通过中间件auth_middleware.py,采用白名单,对url进行控制,替代装饰器@login_requierd,否则每一个函数都有要加装饰器。
    from django.utils.deprecation import MiddlewareMixin
    2、验证字段:表单forms组件
    
    对每个数据库中的字段进行校验,返回error
    from django import forms
    3、自定义分页器
    
    分页器pagination.py
    解耦
    from blog.utils.pagination import MyPaginator  # 分页器
    4、记录日志log
    
    settings配置文件,终端打印sql语句
    mylog.py 日志文件,解耦,终端打印并在log文件记录用户操作
    import logging
    5、模板继承
    
    {% extends 'base.html' %}
    
    {% block site-header %}
    
    {% endblock %}
    6、ORM表关系
    
    一对一(user blog)
    一对多(user article)
    多对多(article tag)
    7、注意点:
    
    1) 时区:
    settings.py配置
        # TIME_ZONE = 'UTC'
        TIME_ZONE = 'Asia/Shanghai'
        USE_TZ = False
    
    2) 静态文件目录
    STATICFILES_DIRS = [
        os.path.join(BASE_DIR, 'static')
    ]
    8、连接mysql数据库
    
    settings配置
    # 连接mysql数据库
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'NAME': 'cnblog',            # 要连接的数据库,连接前需要创建好
            'USER': 'root',           # 连接数据库的用户名
            'PASSWORD': 'root',          # 连接数据库的密码
            'HOST': '127.0.0.1',     # 连接主机,默认本级
            'PORT': 3306,            # 端口 默认3306
        }
    }
    9、评论后发送邮件
    
    settings文件配置
    # 发送邮件
    EMAIL_USE_SSL = True
    # EMIAL_HOST = 'smtp.exmail.qq.com'       # 如果是163 改成smtp.163.com
    EMAIL_HOST = 'smtp.qq.com'  # 如果是 163 改成 smtp.163.com
    EMAIL_PORT = 465
    EMAIL_HOST_USER = '719633333@qq.com'        # 账号
    EMAIL_HOST_PASSWORD = 'or333333ndzubdie'    # qq邮箱的授权码而不是密码
    DEFAULT_FROM_EMAIL = EMAIL_HOST_USER
    
    
    views视图
    from django.core.mail import send_mail  # 发送邮件
    
    # 多进程发送邮件
    t = threading.Thread(target=send_mail, args=("你的文章【%s】新增了一条评论内容" % article_obj.title,
                                                     content,
                                                     settings.EMAIL_HOST_USER,
                                                     [request.user.email],
                                                     ))
     t.start()
    10、验证码
    
    PIL模块生成验证码
    from PIL import Image, ImageDraw, ImageFont
    11、自定义tag标签
    
    from django import template
    register = template.Library()
    @register.inclusion_tag("blog/classification.html")
    def get_classification_style(username):
    12、数据库事务操作
    
    from django.db import transaction  # 事务操作
    13、富文本编辑框
    
    KindEditor
    14、防止xss攻击
    
    from bs4 import BeautifulSoup

    其他

    xss攻击
    {{ article_obj.content|safe }} safe是让所用提交都通过

    我们在提交阶段认为的剔除非法的标签

     标签页的知识:

    data-toggle="tab"——指明标签项具有切换响应功能;
    .tab-content——包裹标签页的所有内容部分;
    .tab-pane——包裹对应标签项的内容部分;
    .fade——设置标签项切换时有淡入淡出的效果;
    .in——设置标签页第一项淡入的初始化效果;
    .active——设置标签页以及对应标签项的内容处于激活状态;

     ----

     <!-- Nav tabs Bootstrap 中的--选项卡-->
                <ul class="nav nav-tabs" role="tablist">
                    <li role="presentation" class="active"><a href="#home" aria-controls="home" role="tab"
                                                              data-toggle="tab">文章</a></li>
                    <li role="presentation"><a href="#profile" aria-controls="profile" role="tab"
                                               data-toggle="tab">日记</a></li>
                    <li role="presentation"><a href="#messages" aria-controls="messages" role="tab" data-toggle="tab">随笔</a>
                    </li>
                    <li role="presentation"><a href="#settings" aria-controls="settings" role="tab" data-toggle="tab">相册</a>
                    </li>
                </ul>
                <!-- Tab panes -->
                <div class="tab-content">
                    <div role="tabpanel" class="tab-pane active" id="home">
    
                        {% block content %}
    
                        {% endblock %}
                    </div>
                    <div role="tabpanel" class="tab-pane" id="profile">
    
                        <img src="/static/img/meinv2.jpg" alt="">
                        <img src="/static/img/meinv3.jpg" alt="">
                        <img class="pull-right" src="/static/img/meinv.jpg" alt="">
                    </div>
                    <div role="tabpanel" class="tab-pane" id="messages">
    
                        <img width="180" height="180" src="/static/img/hashiqi2.jpg" alt="">
    
                        <img width="180" height="180" src="/static/img/dogg4.jpg" alt="">
                        <img width="180" height="180" src="/static/img/linhaifeng.jpg" alt=""><br>
                        <img width="180" height="180" src="/static/img/dogg3.jpeg" alt="">
                        <img width="180" height="180" src="/static/img/dogge2.jpg" alt="">
    
                        <img width="180" height="180" src="/static/img/dogg5.jpg" alt="">
    
                    </div>
                    <div role="tabpanel" class="tab-pane" id="settings">
    
                    </div>
    View Code

     防止xxs攻击

    <script>alert(1111)</script>

    数据库(pycharm连接mysql数据库)         models.py
    
    注册            /reg/
        上传头像    request.FILES.get('avatar')
    
    登录            /login/
        随机验证码  /get_valid_img/
    
    首页            /index/
    
    个人站点
        分类,标签,归档 /blog/egon/
    
    文章详细页       /blog/egon/articles/2/
    
    点赞,踩灭       /blog/poll/
        ajax的post 事务
    
    评论楼,评论树   /blog/comment/
        根评论,子评论
        render显示,ajax显示
    
    后台管理,发布文章  /backend/index/
        新建APP
        认证装饰器
        编辑器(KindEditor)
        文件上传      /media/article_imgs/...
    
    防止XSS攻击
        BeautifulSoup
  • 相关阅读:
    一天时间用python写门语言
    360以安全之名做搜索,可信,还是欺世盗名?
    Servicemix,Karaf和Camel
    Struts2>action 小强斋
    解决JBoss只能通过localhost(127.0.0.1)而不能通过IP访问 小强斋
    java.sql.SQLException: 关闭的连接 小强斋
    Struts2>action 小强斋
    flex>MXML语法 小强斋
    jsp>tomcat配置虚拟目录 小强斋
    解决JBoss只能通过localhost(127.0.0.1)而不能通过IP访问 小强斋
  • 原文地址:https://www.cnblogs.com/foremostxl/p/10017917.html
Copyright © 2011-2022 走看看