bbs项目解读
1.注册功能
具体的效果图如下:
注册功能涉及到的逻辑步骤:
1.搭建前端html页面
2.向后端提交用户输入数据
3.对用户输入的数据格式进行校验
4.页面输入数据格式错误,及时向用户进行提示/正确则保存到数据库
所以,提到校验和提交数据,这就需要我们用到forms组件!!
回顾一下forms组件的功能:
1.生成页面可用的html标签
2.对用户提交的数据进行校验
3.保留上次内容并提示用户
但是!!我们在做项目的时候,不可避免的可能需要用到很多forms组件!之前我们都是写在views.py里面的,但是这样太过冗余,为了接耦合,我们可以新建一个文件夹里面专门放forms组件!!
myforms文件夹
regform.py
loginform.py
userform.py
orderform.py
接下来我们详细解读一下forms组件部分、视图函数部分和前端html部分的代码~~
forms组件部分
from django import forms # forms组件使用的时候需要先导入
from app01 import models # 当校验提交的用户名是否和数据库中的用户名一样时需要导入模型层
class MyForms2(forms.Form): # 定义一个forms组件类,该类继承forms.Form
# forms.CharField为input框,在内部可以通过widget指定input框的类型和样式attrs={}
# min_length最小位数,max_length最大位数,label字段名,不写是默认的类中定义的字段首字母大写的形式
# error_messages为页面输入数据格式不正确时提示的信息
username = forms.CharField(min_length=3,max_length=8,label="用户名",
widget=forms.TextInput(attrs={"class":"form-control"}),
error_messages={
"required":"用户名不能为空",
"min_length":"用户名最少3位",
"max_length":"用户名最多8位"
}
)
password = forms.CharField(label="密码",min_length=3,max_length=8,
widget=forms.PasswordInput(attrs={"class":"form-control"}),
error_messages={
"required": "密码不能为空",
"min_length": "密码最少3位",
"max_length": "密码最多8位"
}
)
confirm_password = forms.CharField(label="确认密码",min_length=3,max_length=8,
widget=forms.PasswordInput(attrs={"class": "form-control"}),
error_messages={
"required": "密码不能为空",
"min_length": "密码最少3位",
"max_length": "密码最多8位"
}
)
email = forms.EmailField(label="邮箱",
widget=forms.EmailInput(attrs={"class": "form-control"}),
error_messages={
"invalid":"邮箱格式不正确",
"required":"邮箱不能为空",
}
)
# 钩子函数,校验的第二道关卡,自定义校验规则,然后返回到前端提示
def clean_username(self): #类里面定义的字段对象会自动创建一个(clear_字段对象名)的函数
# 获取用户名,self.cleaned_data返回的是一个字典{},.get拿到key对应的值
username = self.cleaned_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 password != confirm_password:
self.add_error("confirm_password","两次密码不一致")
# 将钩子函数钩出来数据再放回去,全拿出来就需要全放回去
return self.cleaned_data
视图函数部分
from django.shortcuts import render
from app02.myform2 import MyForms2
from django.http import HttpResponse
from app01 import models
def register2(request):
# 产生一个空对象,将forms组件的字段传进来,再传到html页面
form_obj = MyForms2()
# form表单提交post触发
if request.method == "POST":
# 获取form表单里面的普通键值对
form_obj = MyForms2(request.POST)
# 获取form表单的文件数据
file = request.FILES.get("file")
# 判断数据是否合法
if form_obj.is_valid():
# 移除确认密码,为**打散传到数据库做铺垫
form_obj.cleaned_data.pop("confirm_password")
# 用户提交了文件则触发
if file:
# 往{}这样的字典里添加了一个avatar的key和值
form_obj.cleaned_data["avatar"] = file
# 把字典打散了添加到数据库
models.UserInfo.objects.create_user(**form_obj.cleaned_data)
# 数据合法之后,返回到另一个页面
return HttpResponse("ok")
return render(request,"register2.html",locals())
html部分
向后端提交数据可以用form表单也可以用ajax提交
法1:form表单提交
<div class="container"> <!--bootstrap布局-->
<div class="row">
<div class="col-md-8 col-md-offset-2">
{# 这里我们采用了form表单向后端提交数据,form默认是提交的urlencoded的编码格式,#}
{# urlencoded的格式form表单只会将普通键值对封装到request.POST中,添加enctype="multipart/form-data",#}
{# 可以获取普通键值对和文件。#}
<form action="" novalidate method="post" enctype="multipart/form-data">
{% csrf_token %}
<h1 class="text-center">注册</h1>
{% for form in form_obj %}
<div class="form-group">
<label for="">{{ form.label }}</label>
{{ form }}
{# 这里是只有当以form表单提交的时候才会展示报错信息,如果以ajax就不该以这样的方式添加报错信息#}
<span style="color: red">{{ form.errors.0 }}</span>
</div>
{% endfor %}
<div>
{# 插入的图片可以指定宽度width,以此来规定图片的大小#}
<label for="myimg">头像<img src="/static/img/default.png" alt="" width="80" id="myimg2" ></label>
{# 添加display:none 来隐藏file文本框#}
<input type="file" name="file" id="myimg" style="display: none">
</div>
<input type="submit" value="提交" class="btn-primary btn form-control">
</form>
</div>
</div>
</div>
</body>
<script>
// change 文本域变化事件,当myimg的文本域变化是触发
// 这一步是将提交的头像动态的展示在前端页面上
$("#myimg").change(function (){
{#引出一个文件阅读器对象#}
{#1.先生成一个文件阅读器对象#}
let fileDataObj = new FileReader();
{#2.获取用户上传的头像#}
let fileobj = $(this)[0].files[0];
{#3.将文件对象交给阅读器对象进行读取#}
fileDataObj.readAsDataURL(fileobj);
{#4.利用文件阅读器将图片展示到前端页面,就是修改img的src属性#}
{#这里需要等文件阅读器加载完毕在执行修改src属性的操作#}
fileDataObj.onload=function (){
$("#myimg2").attr("src",fileDataObj.result) // fileDataObj.result是文件阅读器对象读取完毕文件的结果
}
})
</script>