web开发-Django博客系统

项目界面图片预览

项目代码github地址


项目完整流程

项目流程:

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

  (1) 基于用户认证组件和Ajax实现登录验证(图片验证码)

  (2) 基于forms组件和Ajax实现注册功能

  (3) 设计系统首页(文章列表渲染)

  (4) 设计个人站点页面
        主要是orm查询

  (5) 文章详情页

  (6) 实现文章点赞功能

  (7) 实现文章的评论
      ---文章的评论
      ---评论的评论

  (8) 富文本编辑框和防止xss攻击
  (9) 密码修改

2 设计表结构
    用户信息表
    个人站点表
    个人文章分类表
    文章标签
    文章表
    点赞表
    评论表
    文章和标签多对多关系表

  

3 按着每一个功能分别进行开发
  
4 功能测试

5 项目部署上线


一、创建项目和数据迁移

步骤

1、因为user_info表继承了Django的user,需要在setting里面加入AUTH_USER_MODEL=‘blog.user_info’

2、设置数据库

3、开始数据迁移

相关命令

数据库

管理员运行cmd

net start mysql

创建数据库

create database blog;

python

python  manage.py  makemigrations

python  manage.py migrate

二、登陆功能

基于用户认证组件和Ajax实现登录验证(图片验证码)

要点总结:

1、利用PIL模块生成验证码图片

2、利用IO模块调用内存空间,提高验证码图片的生成和获取效率

3、保存当前验证码,存入session

4、刷新验证码,在请求链接末尾加?,即刷新

创建超级用户命令,以便于操作

python36  manage.py  createsuperuser

优化代码和用户体验

1、清空上次错误信息,

2、解耦验证码函数,单独创建工具包utils,放置获取验证码函数

提高要求,插入滑动验证码

利用SDK模块 www.geetest.com   极验滑动验证码官网

需要social-auth-app-django模块配合

三、注册功能

基于forms的注册页面

1、创建myforms组件

2、forms组件渲染注册页面,auto_id,头像另外添加

4、默认头像设置,点击头像打开选择图片框(即点击input)隐藏input框

5--头像预览:
1 获取用户选中的文件对象 $()[0].files[0]
        change事件

2 获取文件对象的路径 new FileReader()
3 修改img的src属性 ,src=文件对象的路径
怎么设置头像选择路径?

       render异步---所以要这样处理(reader.onload=function(){   显示图像的代码    })

Ajax发送注册信息

1、按钮点击事件

2、需要传输文件对象,要用new FormData

FormData对象处理数据

3、优化formData的数据sarializeArray 提取form表单的数据,整理成一个数组

4、显示错误信息,$.each循环错误msg,1先清空,2错误的变成红色框

5、错误信息改为中文

6、局部钩子和全局钩子

7、__all__的错误信息的处理

error_messages 的字段大全?

8、数据校验通过后,1模板中,直接location跳转、2、在视图中,生成用户记录,

9、filefield字段和imagefield字段


media配置

1、关于对静态文件的区分

/static/            JS css img

/media/         用户上传的文件

2、media配置

使用media的好处----

默认头像路径如果是空的判断,设置成默认头像

3、media_url配置


浏览器如何能直接访问到media中的数据


settings.py:
MEDIA_URL="/media/"

urls.py:
from django.views.static import serve

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

注册用户代码优化

去除重复代码逻辑

利用extar={}传入头像值

        

四、系统首页

页面设计

头部导航

登陆之后显示用户名

添加登陆头像

主页文章的渲染

admin的使用,

admin(不是必需的):
Django内部的一个组件:后台数据管理组件(web页面)
    超级用户登陆才能使用
python manage.py createsuperuser    针对用户认证组件对应的用户表

admin注册:
    在app下的admin.py中
admin.site.register(models.UserInfo)

录入文章

注意:在用户注册后,就应该生成相应的站点博客,需要一个页面来注册博客站点

遗留:没有设置账户登陆有效时间


渲染

1、从数据库去除数据

2、标题,直接取出title

      头像,文章对应的user的avatar ,路径前加上media,限制图片大小

      摘要,直接取出desc,bootstrap用法  media-left  和media-right


      发布信息,发布者    &nbsp:  发布时间(修改时区)  &nbsp;评论;点赞   设置样式

提醒:样式文件依然不能完全加载,把文件内容复制到了另一个文件中,重新引入,才生效了

原因:浏览器首先会加载之前吓到到本地的缓存,如果修改的样式文件没有生效,要首先去浏览器的设置---->高级---->清除浏览数据---->清除数据

image


体会:感觉数据库存储,前端的搭配,Django的渲染,是如此的美妙,


五、个人站点页面

1,个人站点url,视图

2、判断是否存在user,用来跳转到用户站点

3、orm查询,跨表和分组查询

分类

标签

日期

注意:Django数据查询好渣,要练

日期的分组查询  extra 和date_format 和   TruncMonth

4、渲染


5、过滤跳转

路由设置有名分组,

模板根据分组设置路径

视图从路径得到的分组名, 查询数据库数据

渲染到主页


六、文章详情页

代码优化,函数复用,模板继承,模板能直接接受字典数据context

templatetags自定义标签

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


文章的渲染

        文章字符串转义(排版)

       safe

       xss攻击

七、点赞

绑定事件,通过判断类名获得布尔值

ajax发送的后台

去除文章ID、布尔值、在request.user.pk 中得到登陆用户,即点赞者的id

添加到点赞记录表中

在文章表中同步点赞或者反对值,用到 F查询自加


根据返回状态,前端显示提示消息


点赞代码优化

八、评论

根评论:对文章的评论

            子评论:对评论的评论
            

            111
                444
                   555
            222
            333


            Comment

            nid   user_id  article_id    content      parent_comment_id(null=True)
             1      1          1            111              null
             2      2          1            222              null
             3      3          1            333              null
             4      4          1            444                1 
             5      5          1            555                4

实现流程


60、搭建样式

61、填写评论--->ajax事件提交到后端---->提取---->创建到数据库---->清空评论框

62、显示评论 ---render显示---->提取数据对象--->文章详情页的视图中提取----->渲染样式forloop.counter计数显示楼层

63、显示评论---ajax显示---->提交后,视图中提取,并返回--->从响应返回值里面拿数据----> 视图中提取创建时间(格式化)、评论内容、评论人、--->建立字符串标签(要用ex6语法,不用加号)---->添加到ul中

64、回复按钮事件---获取焦点---赋文本值(@此评论的评论者)

65、提交子评论---pid赋值---自定义属性值(此评论的ID)--->处理content(换行符,切片)----重置pid

66、render显示子评论---

67、ajax显示子评论----

68、评论树---递归,效率低----- >新方式----->

74、事务操作,模块transaction

75、发送邮件----模块------优化速度---开线程

九、后台管理

76、后台设计----文版编辑器kindediditor---文件上传----uploadJson----extraFileUploadParams(带cs_token参数)---filePostName (指定传输的文件名字)---下载到本地服务器---视图返回路径,放在编辑器里

80、文章摘要的保存

---1、列表截取----->2、有样式之后,乱套---截取纯文本才可以---3、bs4—beautifulSoup------4、获取文本

---5、防御xss攻击---过滤标签

十、修改密码

利用auth模块的user对象的方法check_password验证密码,set_password修改密码


十一、要点记录(按照文件目录的顺序)


         1、templates下的mytags--->自定义标签
             # inclustion_tag中引入模板,将数据和模板绑定在了一起
             效果:左侧和顶部样式和个人站点一样,使用模板继承,自定义标签来复用代码,并且使样式和数据一体
        
         2、获取随机验证码
             1、相关模块
                 from PIL import Image, ImageDraw, ImageFont  生成图片和在图片上添加文字,噪点噪线
                 from io import BytesIO 调用内存空间
                 import random
             2、生成的验证码保存在session中,防止各个浏览器用户冲突
                 request.session['valid_code_str'] = valid_code_str
         3、模型层
             1、定义用户表,给系统自带的auth表添加自己的字段
                 相关模块from django.contrib.auth.models import AbstractUser 需要继承这个类

            2、打印真个对象时,显示标题名,可自定义
                 def __str__(self):
                     return self.title
             3、联合唯一
                     class Meta:
                         unique_together = [
                             ('article', 'tag'),
                         ]
         4、forms组件
             1、检验字段
             2、钩子
                 cleaned_data 校验完的数据
                 __all__全局错误名

                全局钩子
                 局部钩子
             3、相关模块
                 from django.forms import widgets  添加渲染到class
                 from django.core.exceptions import ValidationError  用来生成 提示错误
         5、分页器
             1、from django.core.paginator import Paginator
             2、获取要处理的列表--->生成分页器对象--->当前页码--->当前页--->页码列表
                 返回调用者,当前页和页码列表
             3、根据请求页码,会有不同的页码列表展示逻辑,以确保页码不会超宽导致页码编程两行
                 确保不会出现负数的逻辑
         6、路由层的设置
             path
                
             re_path
                 处理需要匹配的格式
                     ^  $  |
             有名分组
                 <int:name>
                 (?P<name>)
             有的路由会会被覆盖的问题
                 放在上面,防止被覆盖
         7、视图函数
             1、插入数据还是用的笨方法
                 文本获取字符串,然后切割
             2、主要模块
                     from django.shortcuts import render, HttpResponse, redirect
                     from django.http import JsonResponse   直接json返回内容
                     from django.contrib import auth
                     from django.db.models import Count, F, Sum 数据库方法
                     from django.db.models.functions import TruncMonth 时间达到月份
                     from django.db import transaction 事务操作
                     from django.core.mail import send_mail 发送邮件
                     from django.contrib.auth.decorators import login_required
                     from bs4 import BeautifulSoup 过滤非法标签
                     import json
                     import os
                     import random
                     from threading import Thread  线程用于发送邮件,提高程序速度
             3、添加新文章
                 1、ajax发送数组
                     前端定traditional:True
                     后台:array = request.POST.getlist('ids')  #django接收数组
                 2、bs4用来获取html的文本内容
                     过滤非法字符串
                 3、kinded编辑器发送图片文件
                    
                 4、获取编辑器内容
                     同步编辑器和标签
                     html = editor.html();
                     editor.sync();

                    editor.html()
                 5、图片上传
                     前端
                         uploadJson:'/upload/' 设置上传路由
                         filePostName:'up_load_img' 文件的别名
                     后端
                         视图函数
                         获取到对象--img = request.FILES.get('up_load_img')
                         保存
                         返回方式,错误和保存在服务器的
                             response = {
                                 'error': 0,
                                 'url': '/media/add_article_img/%s' % img.name
                             }
                         return JsonResponse(response)
             4、评论
                 1、事务,因为涉及到多个表
                 2、发送邮件到作者邮箱
                     多线程处理邮件发送,不影响前端体验
                     setting的设置
                         邮件服务器,授权码
                 3、返回本条消息内容到浏览器,浏览器添加本条评论到页面
                     因为插入数据库后返回就是数据库对象,可以直接获取其中的字段,用来返回
                 4、前端评论树样式
                     1、每条消息设置一条虚线背景图片
                     2、子评论单独添加一张透明的图片定位在左上角,只要下面的虚线边框
                     3、调整位置,使其像一个树结构
                     4、还不够完整,多出了虚线还没有处理
                     核心:
                         子评论利用有父评论ID,找到父级,添加在父级之后
                         再利用css,magin-left得到基本评论树的框架
                 5、没有评论逻辑判断
            
             5、点赞和踩灭
                 true 是赞 False 是踩
                 1、登陆者即是点赞人
                     不能操作自己文章的逻辑,判断是不是自己的文章,返回状态
                     判断记录表中是否有该用户对该文章的操作
                 2、事务操作
                 3、判断是点在还是踩灭
                     前端html中
                         核心--取值判断是否有digg(赞图标所在的标签)类,得到布尔值
                         取值时用了json--->is_up = json.loads(request.POST.get('is_up'))
                 4、前端数字的自加
                 5、若是不能操作
                     返回is_up,和失败标志,前端根据is_up,显示相应的消息
                         var val=data.handle? '您已经推荐过了': '您已经反对过了';
             6、个人站点
                 1、使用自定义标签
                 2、复用函数,返回字典--->得到返回字典·以context字典传入数据,-->前端直接调用key
                 3、路由匹配,查询文章分类,标签,以及归档日期
                     re_path(r'^(?P<username>\w+)/(?P<conditon>tag|category|archive)/(?P<param>.*)/$', views.home_site),

            7、注销
                 用户认证模块auth.logout(request)
             8、注册
                 1、forms组件
                 2、头像
                     取头像在FILES中avatar_obj = request.FILES.get('avator')
                     当用户没有传头像的判断
                         extra,若取到了,加到这个字典中,插入时用extra
                     前端头像预览
                         获取头像路径,覆盖原头像
                             reader=new FileReader()
                             reader.readAsDataURL(file_obj);
                             // 修改img的src的属性,覆盖原图片
                             reader.onload=function () {
                             $('#avator_img').attr('src',reader.result)
         };
                 3、提交注册数据
                    需要 form_data=new FormData();然后append
                         var requset_data=$('#form').serializeArray();
                         $.each(requset_data,function (index,data) {
                             form_data.append(data.name,data.value)
                     // 编码类型两个参数
                     contentType:false,
                     processData:false,
                 4、全局错误的展示

            9、登陆
                 auth模块
                 从session中取出验证码与前端对比
                 user = auth.authenticate(username=user, password=pwd)
                 注册session
                 auth.login(requset, user)
         8、media文件夹
             settings的设定
                 MEDIA_URL = '/media/'
                 MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
             路由设置

            作用:放置用户上传的媒体文件,头像等
         9、settings
             1、添加APP
             2、配置数据库信息
             3、时区的设置
             4、USE_TZ设置成False
             5、static
             6、media
             7、邮箱配置
             8、session的过期时间
         10、路由补充
             include 路由分支
             在路由中注册media
            ** re_path(r"media/(?P<path>.*)$",serve,{"document_root":settings.MEDIA_ROOT})
         11、static
             静态文件分开单独放
         12、templates,模板层
             base模板继承
             include引用模板
         13、其他
             多选下拉框组件
                 引入css和js
                     class加入selectpicker
                     多选multiple
                     输入框标题title="--请选择"
                     取值,和普通标签相同
                     刷新option,$('.selectpicker').selectpicker('refresh');
            
         14、css和js
             弹出模态框bootstrap
             添加cstoken,才能通过post发送ajax数据
                 csrfmiddlewaretoken:$('[name=csrfmiddlewaretoken]').val()
             form使用form-group、form-control
             时间格式的处理
                 <td>{{ article.create_time|date:'Y-m-d H:i' }}</td>
                 文档的安全safe
         15、文本编辑器
             引入
             参数配置
                 文件上传
             同步数据到输入框
             获取数据
             赋值

posted @ 2018-09-22 12:30  游小刀  阅读(618)  评论(0编辑  收藏  举报
levels of contents