BBS项目
一.BBS项目介绍
1.项目开发流程
- 项目立项 ------> 公司高层决定
- 需求调研和分析 ------> 市场人员,技术人员参与
-需求文档说明- 开发部门开会 ------> 确定项目架构,技术选型,数据库设计
- UI,UD团队(产品经理) ---> 原型图 ---> 切图 ---> 交给前端
- 分任务开发
-前端
-后端:对着原型图 ---> 设计数据库、设计功能- 前后端联调
- 提交版本测试
- 发布上线
2.BBS项目功能
- 注册功能
-校验
-ajax注册
-头像显示和上传- 登录
- 首页文章显示
- 个人站点
-显示这个人写的所有文章
-侧边栏有分类、标签、随笔- 文章详情
- 点赞、点踩
- 评论
-根评论
-子评论- 后台管理
-查看所有文章
-删除文章
-新增文章:xss攻击去除
3.数据库设计
- 用户表
UserInfo ---> 扩写auth的user表- 博客表
Blog ---> 跟用户表做一对一关联- 文章表
Article- 文章分类表
Category- 标签表
Tag- 点赞点踩表
UpAndDown- 评论表
Commit
4.数据库关联关系
用户和博客:一对一
博客和文章:一对多 一个博客下,有很多文章,关联字段写在文章表里
博客和分类:一对多 一个博客下,创建多个分类,关联字段写在分类表中
博客和标签:一对多 一个博客下,创建多个标签,关联字段写在标签表中
文章和分类:一对多 一个文章只能属于一个分类,一个分类下有很多文章,关联字段写在文章中文章和标签:多对多 一个文章可以有多个标签,一个标签下可以有多个文章,多对多关系,创建中间表
点赞和用户:一对多 一个用户可以点很多赞,关联字段写在点赞表中评论和用户:一对多 一个用户可以评论多个,评论的一条记录只属于一个用户,关联字段写在评论表中
文章和点赞:一对多 一篇文章可以被点多次,但是一个点赞的记录只对应一篇文章,关联字段写在点赞表中文章和评论:一对多 一篇文章可以被评论多次,但是一个评论的记录只对应一篇文章,关联字段写在评论表中
5.创建项目迁移表环境搭建
# 解释器环境中有 djagno ==3.2.20# 1 pycharm 创建
# 2 命令创建# 1 国际化
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_L10N = True
USE_TZ = False
# 2 配置了static
STATIC_URL = '/static/'
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]# 3 配置了media
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'# 4 配置了链接mysql
DATABASES = {'default': {'ENGINE': 'django.db.backends.mysql','NAME': 'blog','USER': 'root','PASSWORD': '1234','HOST': '127.0.0.1','PORT': 3306}
}
二.注册功能
1.注册功能基本需求
- 用户名
- 密码
- 确认密码
- 邮箱
- 手机号
- 头像
2.form组件
(1)form组件有哪些用处
- 快速生成前端页面
- 数据校验
- 错误处理
(2)如何使用
校验字段功能
以注册功能为例:
# models.pyclass UserInfo(models.Model):name=models.CharField(max_length=32)pwd=models.CharField(max_length=32)email=models.EmailField()
# HTML里<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title></head>
<body><form action="" method="post">{% csrf_token %}<div><label for="user">用户名</label><p><input type="text" name="name" id="name"></p></div><div><label for="pwd">密码</label><p><input type="password" name="pwd" id="pwd"></p></div><div><label for="r_pwd">确认密码</label><p><input type="password" name="r_pwd" id="r_pwd"></p></div><div><label for="email">邮箱</label><p><input type="text" name="email" id="email"></p></div><input type="submit">
</form></body>
</html>
# views.py# forms组件
from django.forms import widgetswid_01=widgets.TextInput(attrs={"class":"form-control"})
wid_02=widgets.PasswordInput(attrs={"class":"form-control"})class UserForm(forms.Form):name=forms.CharField(max_length=32,widget=wid_01)pwd=forms.CharField(max_length=32,widget=wid_02)r_pwd=forms.CharField(max_length=32,widget=wid_02)email=forms.EmailField(widget=wid_01)tel=forms.CharField(max_length=32,widget=wid_01)def register(request):if request.method=="POST":form=UserForm(request.POST)if form.is_valid():print(form.cleaned_data) # 所有干净的字段以及对应的值else:print(form.cleaned_data) #print(form.errors) # ErrorDict : {"校验错误的字段":["错误信息",]}print(form.errors.get("name")) # ErrorList ["错误信息",]return HttpResponse("OK")form=UserForm()return render(request,"register.html",locals())
渲染标签功能
渲染方式一:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><!-- 最新版本的 Bootstrap 核心 CSS 文件 --><link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
</head>
<body>
<h3>注册页面</h3>
<div class="container"><div class="row"><div class="col-md-6 col-lg-offset-3"><form action="" method="post">{% csrf_token %}<div><label for="">用户名</label>{{ form.name }}</div><div><label for="">密码</label>{{ form.pwd }}</div><div><label for="">确认密码</label>{{ form.r_pwd }}</div><div><label for=""> 邮箱</label>{{ form.email }}</div><input type="submit" class="btn btn-default pull-right"></form></div></div>
</div></body>
</html>
渲染方式二:
<form action="" method="post">{% csrf_token %}{% for field in form %}<div><label for="">{{ field.label }}</label>{{ field }}</div>{% endfor %}<input type="submit" class="btn btn-default pull-right"></form>
渲染方式三:
<form action="" method="post">{% csrf_token %}{{ form.as_p }}<input type="submit" class="btn btn-default pull-right"></form>
渲染错误信息功能
# views.pydef register(request):if request.method=="POST":form=UserForm(request.POST)if form.is_valid():print(form.cleaned_data) # 所有干净的字段以及对应的值else:print(form.cleaned_data) #print(form.errors) # ErrorDict : {"校验错误的字段":["错误信息",]}print(form.errors.get("name")) # ErrorList ["错误信息",]return render(request,"register.html",locals())form=UserForm()return render(request,"register.html",locals())
# 模板<form action="" method="post" novalidate>{% csrf_token %}{% for field in form %}<div><label for="">{{ field.label }}</label>{{ field }} <span class="pull-right" style="color: red">{{ field.errors.0 }}</span></div>{% endfor %}<input type="submit" class="btn btn-default"></form>
组件参数配置
class Ret(Form):name = forms.CharField(max_length=10, min_length=2, label='用户名',error_messages={'required': '该字段不能为空', 'invalid': '格式错误', 'max_length': '太长','min_length': '太短'},widget=widgets.TextInput(attrs={'class':'form-control'}))pwd = forms.CharField(max_length=10, min_length=2, widget=widgets.PasswordInput(attrs={'class':'form-control'}))email = forms.EmailField(label='邮箱', error_messages={'required': '该字段不能为空', 'invalid': '格式错误'})
局部钩子
from django.core.exceptions import NON_FIELD_ERRORS, ValidationError
def clean_name(self):val=self.cleaned_data.get("name")ret=UserInfo.objects.filter(name=val)if not ret:return valelse:raise ValidationError("该用户已注册!")def clean_tel(self):val=self.cleaned_data.get("tel")if len(val)==11:return valelse:raise ValidationError("手机号格式错误")
全局钩子
def clean(self):pwd=self.cleaned_data.get('pwd')r_pwd=self.cleaned_data.get('r_pwd')if pwd and r_pwd:if pwd==r_pwd:return self.cleaned_dataelse:raise ValidationError('两次密码不一致')else:return self.cleaned_data
pwd_err=my_form.errors.get('__all__')
from django import formsfrom django.forms import widgets
from app01.models import UserInfofrom django.core.exceptions import NON_FIELD_ERRORS, ValidationErrorclass UserForm(forms.Form):name=forms.CharField(min_length=4,label="用户名",error_messages={"required":"该字段不能为空"},widget=widgets.TextInput(attrs={"class":"form-control"}))pwd=forms.CharField(min_length=4,label="密码",widget=widgets.PasswordInput(attrs={"class":"form-control"}))r_pwd=forms.CharField(min_length=4,label="确认密码",error_messages={"required":"该字段不能为空"},widget=widgets.TextInput(attrs={"class":"form-control"}))email=forms.EmailField(label="邮箱",error_messages={"required":"该字段不能为空","invalid":"格式错误"},widget=widgets.TextInput(attrs={"class":"form-control"}))tel=forms.CharField(label="手机号",widget=widgets.TextInput(attrs={"class":"form-control"}))def clean_name(self):val=self.cleaned_data.get("name")ret=UserInfo.objects.filter(name=val)if not ret:return valelse:raise ValidationError("该用户已注册!")def clean_tel(self):val=self.cleaned_data.get("tel")if len(val)==11:return valelse:raise ValidationError("手机号格式错误")def clean(self):pwd=self.cleaned_data.get('pwd')r_pwd=self.cleaned_data.get('r_pwd')if pwd and r_pwd:if pwd==r_pwd:return self.cleaned_dataelse:raise ValidationError('两次密码不一致')else:return self.cleaned_data
from django.shortcuts import render,HttpResponsefrom app01.myforms import *def reg(request):if request.method=="POST":print(request.POST)#form=UserForm({"name":"yu","email":"123@qq.com","xxxx":"alex"})form=UserForm(request.POST) # form表单的name属性值应该与forms组件字段名称一致print(form.is_valid()) # 返回布尔值if form.is_valid():print(form.cleaned_data) # {"name":"yuan","email":"123@qq.com"}else:print(form.cleaned_data) # {"email":"123@qq.com"}# print(form.errors) # {"name":[".........."]}# print(type(form.errors)) # ErrorDict# print(form.errors.get("name"))# print(type(form.errors.get("name"))) # ErrorList# print(form.errors.get("name")[0])# 全局钩子错误#print("error",form.errors.get("__all__")[0])errors=form.errors.get("__all__")return render(request,"reg.html",locals())'''form.is_valid() :返回布尔值form.cleaned_data :{"name":"yuan","email":"123@qq.com"}form.errors :{"name":[".........."]}'''form=UserForm()return render(request,"reg.html",locals())
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><style>.error{color: red;}</style><!-- 最新版本的 Bootstrap 核心 CSS 文件 --><link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css"integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
</head>
<body><div class="container"><div class="row"><div class="col-md-6 col-lg-offset-3">{#<h3>简单form</h3>#}{##}{##}{#<form action="" method="post" novalidate>#}{# {% csrf_token %}#}{# <p>用户名<input type="text" name="name"></p>#}{# <p>密码 <input type="text" name="pwd"></p>#}{# <p>确认密码 <input type="text" name="r_pwd"></p>#}{# <p>邮箱 <input type="text" name="email"></p>#}{# <p>手机号 <input type="text" name="tel"></p>#}{# <input type="submit">#}{##}{#</form>#}<hr><h3>forms组件渲染方式1</h3><form action="" method="post" novalidate>{% csrf_token %}<p>{{ form.name.label }}{{ form.name }} <span class="pull-right error">{{ form.name.errors.0 }}</span></p><p>{{ form.pwd.label }}{{ form.pwd }} <span class="pull-right error">{{ form.pwd.errors.0 }}</span></p><p>确认密码{{ form.r_pwd }} <span class="pull-right error">{{ form.r_pwd.errors.0 }}</span><span class="pull-right error">{{ errors.0 }}</span></p><p>邮箱 {{ form.email }} <span class="pull-right error">{{ form.email.errors.0 }}</span></p><p>手机号 {{ form.tel }} <span class="pull-right error">{{ form.tel.errors.0 }}</span></p><input type="submit"></form>{#<h3>forms组件渲染方式2</h3>#}{##}{#<form action="" method="post" novalidate>#}{# {% csrf_token %}#}{##}{# {% for field in form %}#}{##}{# <div>#}{# <label for="">{{ field.label }}</label>#}{# {{ field }}#}{# </div>#}{##}{# {% endfor %}#}{##}{# <input type="submit">#}{#</form>#}{##}{#<h3>forms组件渲染方式3</h3>#}{##}{#<form action="" method="post">#}{# {% csrf_token %}#}{##}{# {{ form.as_p }}#}{##}{# <input type="submit">#}{#</form>#}</div></div>
</div></body>
</html>
(3)总结
- 写一个类,继承forms.Form
- 在类中写属性和方法
- 属性:和我们要校验或者自动生成页面的字段一一对应
- 方法:对字段进行校验:
- clean_字段名:给单个字段校验
- clean:给多个字段校验
- 在视图函数中使用
- 在模板中使用
form表单中,如果定义了button或input类型是'submit',只要点击就会默认触发form表单的提交,如果我们又写了ajax提交就会触发两次从而导致出现问题
相关文章:

BBS项目
一.BBS项目介绍 1.项目开发流程 项目立项 ------> 公司高层决定需求调研和分析 ------> 市场人员,技术人员参与 -需求文档说明开发部门开会 ------> 确定项目架构,技术选型,数据库设计UI,UD团队(产品经…...

Java基础——对象类型转换(向上、向下转型)
非继承关系的类之间对象类型不可以互相类型转换,只有继承关系才可以互相转换。 简单说,对象类型转换的前提要是继承关系。 对象类型转换分为:向上转型和向下转型。多态就是一种自动向上转型。 向上转型:子类对象用父类类型接收…...

期末速成数据库极简版【查询】(2)
目录 select数据查询----表 【1】筛选列 【2】where简单查询 【3】top-n/distinct/排序的查询 【4】常用内置函数 常用日期函数 常用的字符串函数 【5】模糊查询 【6】表数据操作——增/删/改 插入 更新 删除 【7】数据汇总 聚合 分类 🙂&#…...

2023年终总结-轻舟已过万重山
自我介绍 高考大省的读书人 白,陇西布衣,流落楚、汉。-与韩荆州书 我来自孔孟故里山东济宁,也许是小学时的某一天,我第一次接触到了电脑,从此对它产生了强烈的兴趣,高中我有一个愿望:成为一名计…...

手机号,邮箱,密码,验证码正则表达式[Java]
Util类: public abstract class RegexPatterns {/*** 手机号正则*/public static final String PHONE_REGEX "^1([38][0-9]|4[579]|5[0-3,5-9]|6[6]|7[0135678]|9[89])\\d{8}$";/*** 邮箱正则*/public static final String EMAIL_REGEX "^[a-zA-Z…...

普冉(PUYA)单片机开发笔记(7): ADC-轮询式多路采样
概述 应用中经常会有使用单片机进行模数转换的需求。PY32F003 具有 1 个 12 位的模拟数字转换器(ADC),今天我们一起来使用一下这个 ADC。 数据手册中对 ADC 简介如下。 SAR ADC:逐次逼近式 ADC,原理参见“参考链接&a…...

uniapp切换页面时报错问题
我们来看如下错误: 该错误的意思是不能切换到 tabbar 页面。tabbar页面通常是公共页面或者底部导航栏,如果我们用 navigateTo 或者 redirectTo 都不能实现页面切换。 我们有两种方式: 第一种是用 switchTab 来进行切换,但注意切…...

Nginx 简单入门操作
前言:之前的文章有些过就不罗嗦了。 Nginx 基础内容 是什么? Nginx 是一个轻量级的 HTTP 服务器,采用事件驱动、异步非阻塞处理方式的服务器,它具有极好的 IO 性能,常用于 HTTP服务器(包含动静分离)、正向代理、反向代理、负载均衡 等等. Nginx 和 Node.js 在很多方…...

ChatGPT是科学还是艺术?
OpenAI最近谈到GPT4变懒的问题,说“它更像是多人共同参与的艺术创作”,那到底大模型是科学还是艺术?...

线程及实现方式
一、线程 线程是一个基本的CPU执行单元,也是程序执行流的最小单位。引入线程之后,不仅是进程之间可以并发,进程内的各线程之间也可以并发,从而进一步提升了系统的并发度,使得一个进程内也可以并发处理各种任务&#x…...

2023年11月10日 Go生态洞察:十四年Go的成长之路
🌷🍁 博主猫头虎(🐅🐾)带您 Go to New World✨🍁 🦄 博客首页——🐅🐾猫头虎的博客🎐 🐳 《面试题大全专栏》 🦕 文章图文…...

OpenSSL 编程指南
目录 前言初始化SSL库创建SSL 上下文接口(SSL_CTX)安装证书和私钥加载证书(客户端/服务端证书)加载私钥/公钥加载CA证书设置对端证书验证例1 SSL服务端安装证书例2 客户端安装证书创建和安装SSL结构建立TCP/IP连接客户端创建socket服务端创建连接创建SSL结构中的BIOSSL握手服务…...

js优化技巧
一、使用箭头函数简化函数定义 function add(a,b){return a b; }//箭头函数 const add (a,b) > a b;二、使用解构赋值简化变量声明 const firstName person.firstName; const lastName person.lastName;//解构赋值 const {firstName,lastName} person三、使用模板字…...

深入探索 Java 反射机制
文章目录 什么是 Java 反射?反射的核心类和接口反射的基本用法获取 Class 对象的三种方式创建对象实例访问字段和方法调用构造方法 反射的使用场景注意事项结语 Java反射(Reflection)是指在运行时获取类的信息,特别是获取其属性、…...

【ArcGIS Pro微课1000例】0054:Pro3.0创建数据库(文件数据库、移动数据库、企业级数据库)解读
文章目录 一、三种类型数据库解读二、三种类型数据库创建1. 文件数据库2. 移动数据库3. 企业级数据库三、注意事项一、三种类型数据库解读 ArcGIS Pro中主要有三种数据库类型,它们分别是:文件地理数据库、移动地理数据库和企业级地理数据库。它们的区别如下: 存储方式:文件…...

【漏洞复现】华脉智联指挥调度平台命令执行漏洞
Nx01 产品简介 深圳市华脉智联科技有限公司,融合通信系统将公网集群系统、专网宽带集群系统、不同制式、不同频段的短波/超短波对讲、模拟/数字集群系统、办公电话系统、广播系统、集群单兵视频、视频监控系统、视频会议系统等融为一体,集成了专业的有线…...

leetcode第119场双周赛 - 2023 - 12 - 9
比赛地址 : https://leetcode.cn/contest/biweekly-contest-119/ t1 : 直接哈希表 加 暴力 统计就行了 class Solution { public:vector<int> findIntersectionValues(vector<int>& nums1, vector<int>& nums2) {unordered_map<int,int>…...

05. 函数式编程
目录 1、前言 2、什么是函数式编程 2.1、函数是一等公民 2.2、避免状态和可变数据 3、函数式编程的核心概念 3.1、高阶函数 3.2、Lambda(匿名函数) 3.3、递归 & 尾递归优化 3.4、functools模块 3.4.1、partial 3.4.2、reduce 3.4.3、lru_…...

Linux权限(用户角色+文件权限属性)
Linux权限 文章目录 Linux权限一.文件权限1.快速掌握修改权限的方法(修改文件权限属性)2.对比权限的有无,以及具体的体现3.修改权限的第二套方法(修改用户角色)4.文件类型(Linux下一切皆文件) 二…...

短波红外相机的原理及应用场景
短波红外 (简称SWIR,通常指0.9~1.7μm波长的光线) 是一种比可见光波长更长的光。这些光不能通过“肉眼”看到,也不能用“普通相机”检测到。由于被检测物体的材料特性,一些在可见光下无法看到的特性,却能在近红外光下呈现出来&…...

【PyTorch】softmax回归
文章目录 1.理论介绍2. 代码实现2.1. 主要代码2.2. 完整代码2.3. 输出结果 3. Q&A3.1. 运行过程中出现以下警告:3.2. 定义的神经网络中的nn.Flatten()的作用是什么?3.3. num_workers有什么作用?它的值怎么确定? 1.理论介绍 背…...

12.8 作业 C++
使用手动连接,将登录框中的取消按钮使用qt4版本的连接到自定义的槽函数中,在自定义的槽函数中调用关闭函数 将登录按钮使用qt5版本的连接到自定义的槽函数中,在槽函数中判断ui界面上输入的账号是否为"admin",密码是否为…...

10.机器人系统仿真(urdf集成gazebo、rviz)
目录 1 机器人系统仿真的必要性与本篇学习目的 1.1 机器人系统仿真的必要性 1.2 一些概念 URDF是 Unified Robot Description Format 的首字母缩写,直译为统一(标准化)机器人描述格式,可以以一种 XML 的方式描述机器人的部分结构,比如底盘…...

城市基础设施智慧路灯改造的特点
智慧城市建设稳步有序推进。作为智慧城市的基础设施,智能照明是智慧城市的重要组成部分,而叁仟智慧路灯是智慧城市理念下的新产品。随着物联网和智能控制技术的飞速发展,路灯被赋予了新的任务和角色。除了使道路照明智能化和节能化外…...

配置BFD多跳检测示例
BFD简介 定义 双向转发检测BFD(Bidirectional Forwarding Detection)是一种全网统一的检测机制,用于快速检测、监控网络中链路或者IP路由的转发连通状况。 目的 为了减小设备故障对业务的影响,提高网络的可靠性,网…...

爬虫学习-基础库的使用(requests)
目录 一、安装以及实例引入 (1)requests库下载 (2)实例测试 二、GET请求 (1)基本实例 (2)抓取网页 (3)抓取二进制数据 (4)添…...

4.8 构建onnx结构模型-Less
前言 构建onnx方式通常有两种: 1、通过代码转换成onnx结构,比如pytorch —> onnx 2、通过onnx 自定义结点,图,生成onnx结构 本文主要是简单学习和使用两种不同onnx结构, 下面以 Less 结点进行分析 方式 方法一&a…...

Java调试技巧之垃圾回收机制解析
Java作为一种高级编程语言,以其跨平台、面向对象、自动内存管理等特性而广受开发者的喜爱。其中,自动内存管理是Java的一大亮点,通过垃圾回收机制实现对内存的自动分配和释放,极大地简化了开发者的工作。本文将深入探讨Java的垃圾…...

logstash插件简单介绍
logstash插件 输入插件(input) Input:输入插件。 Input plugins | Logstash Reference [8.11] | Elastic 所有输入插件都支持的配置选项 SettingInput typeRequiredDefaultDescriptionadd_fieldhashNo{}添加一个字段到一个事件codeccodecNoplain用于输入数据的…...

联邦多任务蒸馏助力多接入边缘计算下的个性化服务 | TPDS 2023
联邦多任务蒸馏助力多接入边缘计算下的个性化服务 | TPDS 2023 随着移动智能设备的普及和人工智能技术的发展,越来越多的分布式数据在终端被产生与收集,并以多接入边缘计算(MEC)的形式进行处理和分析。但是由于用户的行为模式与服务需求的多样,不同设备上的数据分布…...