基于Django的博客BBS项目

本文详细介绍了基于Django开发的博客BBS项目的全过程,从数据库表创建、注册功能实现,到首页搭建、文章点赞点踩、评论功能,以及后台管理和上传图片等。重点涉及了Django的数据库配置、forms组件、静态文件配置、模板继承、业务逻辑设计等关键步骤。
摘要由CSDN通过智能技术生成

项目流程内容概要

第一部分

bbs是一个前后端不分离的全栈项目,前端和后端都需要我们自己-步步的完成

●表创建及同步
●注册功能
	。forms组件
	。用户头像前端实时展示
	ajax
●登陆功能
	。自己实现图片验证码
●搭建bbs首页
	。导航条根据用户是否登陆展示不同的内容

第二部分

●登陆功能
●bbs首页搭建
	。导航条用户功能
●admin后台管理
●首页文章展示
●用户头像展示(media配置)
●图片防盗链
●个人站点页面搭建
●侧边栏展示功能
	。标签
	。分类
	。日期
●侧边栏筛选功能
●将侧边栏制作成inclusion_tag

第三部分

●侧边栏制作成inclusion. tag
●文章的点赞点踩(重点)
●文章的评论(重点)
	。先只做根评论
	。之后再做子评论
	。小bug完善
	
后面内容
●后台管理
●xss攻击
●用户头像修改

第四部分

●后台管理
	文章查增	改删
	前端编辑器(kindeditor富文本编辑器)
●处理XSS攻击以及文章摘要的处理
●编辑器上传图片
●修改用户头像
●bbs小总结	

项目具体流程

1.数据库表创建及同步

由于django自带的sqlite数据库对日期不敏感,所以我们换成MySQL

1.1创建项目

左栏选Django, 右边选本地环境, 打上项目名称, 配上默认应用名, 点击创建

1.2创建数据库

打开Navicat for MySQL 打开连接, 在某一数据库处右键创建数据库, 字符集选择 'utf8'

1.3修改配置文件与__init__文件

1.3.1修改数据库配置
DATABASES = {
   
    'default': {
   
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'bbslib',
        'USER': 'root',
        'PASSWORD': '123456',
        'HOST': '127.0.0.1',
        'PORT': 3306,
        'CHARSET': 'utf8'
    }
}
1.3.2修改任意__init__文件
import pymysql
pymysql.install_as_MySQLdb()

1.4models中创建相关表以及字段

from django.db import models

# Create your models here.

'''
创表思路:
    先写普通字段
    之后再写外键字段
'''
from django.contrib.auth.models import AbstractUser


class UserInfo(AbstractUser):
    # 手机号字段
    phone = models.BooleanField(verbose_name='手机号', null=True)
    # 头像字段
    avatar = models.FileField(upload_to='avatar/', default='avatar/default.png', verbose_name='用户头像')
    '''给avatar字段传文件对象该文件会自动存储到avatar文件下然后avatar字段只保存文件路径avatar/default.png'''
    # 创建时间
    creat_time = models.DateField(auto_now_add=True)

    # 外键字段
    blog = models.OneToOneField(to='Blog', null=True, on_delete=models.CASCADE)


class Blog(models.Model):
    site_name = models.CharField(verbose_name='站点标题', max_length=32)
    sist_title = models.CharField(verbose_name='站点标题', max_length=32)
    # 简单模拟带你认识样式内部原理的操作
    sist_theme = models.CharField(verbose_name='站点样式', max_length=64)  # 存css/js的文件路径


class Category(models.Model):
    name = models.CharField(verbose_name='文章分类', max_length=32)

    # 外键字段
    blog = models.ForeignKey(to='Blog', null=True, on_delete=models.CASCADE)


class Tag(models.Model):
    name = models.CharField(verbose_name='文章标签', max_length=32)

    # 外键字段
    blog = models.ForeignKey(to='Blog', null=True, on_delete=models.CASCADE)


class Article(models.Model):
    title = models.CharField(verbose_name='文章标题', max_length=64)
    desc = models.CharField(verbose_name='文章简介', max_length=255)
    # 文章内容有很多-般情况下都是使用TextField
    content = models.TextField(verbose_name='文章内容')
    create_time = models.DateField(auto_now_add=True)

    # 数据库字段设计优化
    up_num = models.BigIntegerField(verbose_name='点赞数', default=0)
    down_num = models.BigIntegerField(verbose_name='点踩数', default=0)
    comment_num = models.BigIntegerField(verbose_name='评论数', default=0)

    # 外键字段(3个)
    blog = models.ForeignKey(to='Blog', null=True, on_delete=models.CASCADE)
    category = models.ForeignKey(to='Category', null=True, on_delete=models.CASCADE)
    # 文章跟标签是多对多关系, 三种多对多创建方式, 我们选择自己创建第三张表
    tags = models.ManyToManyField(to='Tag',
                                  through='Article2Tag',
                                  through_fields=('article', 'tag')
                                  )


class Article2Tag(models.Model):
    article = models.ForeignKey(to='Article', on_delete=models.CASCADE)
    tag = models.ForeignKey(to='Tag', on_delete=models.CASCADE)


class UpAndDown(models.Model):
    user = models.ForeignKey(to='UserInfo', on_delete=models.CASCADE)
    article = models.ForeignKey(to='Article', on_delete=models.CASCADE)

    # 记录点赞还是点踩
    is_up = models.BooleanField()  # 传布尔值, 存0/1


class Comment(models.Model):
    user = models.ForeignKey(to='UserInfo', on_delete=models.CASCADE)
    article = models.ForeignKey(to='Article', on_delete=models.CASCADE)
    content = models.CharField(verbose_name='评论内容', max_length=255)
    comment_time = models.DateTimeField(verbose_name='评论时间', auto_now_add=True)

    # 自关联
    parent = models.ForeignKey(to='self', null=True, on_delete=models.CASCADE)  # 有些评论就是根评论 null=True
    # parent = models.ForeignKey(to='Comment', null=True)    # 有些评论就是根评论 null=True

"""
在django2.0后,定义外键和一对一关系的时候需要加on_delete选项,此参数为了避免两个表里的数据不一致问题,不然会报错:
TypeError: __init__() missing 1 required positional argument: 'on_delete
"""

1.5同步到数据库

python manage.py makemigrations
python manage.py migrate

1.6forms组件的创建使用

"""
@Time : 2021/9/19 20:36 
@Author : 常雷
@File : myfroms.py 
@Software: PyCharm
"""
# 书写针对用户表的forms组件代码
from django import forms
from app01 import models  # 为了数据库校验


class MyRegForm(forms.Form):
    username = forms.CharField(label='用户名', min_length=3, max_length=8,
                               error_messages={
   
                                   'required': '用户名不能为空',
                                   'min_length': '用户名最少三位',
                                   'max_length': '用户名最多八位',
                               },
                               # 还需要让标签有bootstrap样式
                               widget=forms.widgets.TextInput(attrs={
   'class': 'form-control'})
                               )
    password = forms.CharField(label='密码', min_length=3, max_length=8,
                               error_messages={
   
                                   'required': '密码不能为空',
                                   'min_length': '密码最少三位',
                                   'max_length': '密码最多八位',
                               },
                               # 还需要让标签有bootstrap样式
                               widget=forms.widgets.PasswordInput(attrs={
   'class': 'form-control'})
                               )
    confirm_password = forms.CharField(label='确认密码', min_length=3, max_length=8,
                                       error_messages={
   
                                           'required': '确认密码不能为空',
                                           'min_length': '确认密码最少三位',
                                           'max_length': '确认密码最多八位',
                                       },
                                       # 还需要让标签有bootstrap样式
                                       widget=forms.widgets.PasswordInput(attrs={
   'class': 'form-control'})
                                       )
    email = forms.EmailField(label='邮箱📪',
                             error_messages={
   
                                 'required': '邮箱📪不能为空',
                                 'invalid': '邮箱📪格式不正确',
                             },
                             widget=forms.widgets.EmailInput(attrs={
   'class': 'form-control'})
                             )

    # 钩子函数
    # 局部钩子:校验用户名是否已存在
    def clean_username(self):
        username = self.cleaned_data.get('username')
        # username = self.changed_data.get('username')
        # 去数据库中校验
        is_exist = models.UserInfo.objects.filter(username=username)
        if is_exist:
            # 提示信息
            self.add_error('username', '用户名已存在')
        return username

    # 全局钩子校验两次密码是否一致
    def clean(self):
        password = self.cleaned_data.get('password')
        confirm_password = self.cleaned_data.get('confirm_password')
        if not password == confirm_password:
            # 提示信息
            self.add_error('confirm_password', '两次密码不一致')
        return
'''
Form.errors 
返回一个ErrorDict实例,包含当前表单所有的错误,可以在is_valid之前调用

Form.has_error(field, code=None)
返回指定field是否有错误

Form.add_error(field, error) 
向指定field添加一个错误

Form.non_field_errors()
不属于field的错误,如数据库中有复合主键重复等.
'''

2.书写注册功能

思考:验证用户名等信息?froms组件

我们之前是直接在views.py中书写的forms组件代码
但是为了接耦合应该将所有的forms组件代码单独写到一个地方

如果你的项目至始至终只用到一个forms组件那么你可以直接建一个py文件 书写即可, 但是如果你的项目需要使用多个forms组件,那么你可以创建一个文件夹在文件夹内根据forms组件功能的不同创建不同的py文件

2.1froms组件实现注册

代码示例:

"""
@Time : 2021/9/19 20:36 
@Author : 常雷
@File : myfroms.py 
@Software: PyCharm
"""
# 书写针对用户表的forms组件代码
from django import forms
from app01 import models  # 为了数据库校验


class MyRegForm(forms.Form):
    username = forms.CharField(label='用户名', min_length=3, max_length=8,
                               error_messages={
   
                                   'required': '用户名不能为空',
                                   'min_length': '用户名最少三位',
                                   'max_length': '用户名最多八位',
                               },
                               # 还需要让标签有bootstrap样式
                               widget=forms.widgets.TextInput(attrs={
   'class': 'form-control'})
                               )
    password = forms.CharField(label='密码', min_length=3, max_length=8,
                               error_messages={
   
                                   'required': '密码不能为空',
                                   'min_length': '密码最少三位',
                                   'max_length': '密码最多八位',
                               },
                               # 还需要让标签有bootstrap样式
                               widget=forms.widgets.PasswordInput(attrs={
   'class': 'form-control'})
                               )
    confirm_password = forms.CharField(label='确认密码', min_length=3, max_length=8,
                                       error_messages={
   
                                           'required': '确认密码不能为空',
                                           'min_length': '确认密码最少三位',
                                           'max_length': '确认密码最多八位',
                                       },
                                       # 还需要让标签有bootstrap样式
                                       widget=forms.widgets.PasswordInput(attrs={
   
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值