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
原文地址:https://www.cnblogs.com/foremostxl/p/10017917.html