Django之form组件
Django的form组件就是把model和form组合气起来
缓存机制
就比如我们去访问一个网站,然后发起一个请求,那么此时服务器就会去帮我们去数据库进行增删查改渲染页面。
然后返回一个我们想要的页面
但是当这个网站的访问量很大,每一次进行的后台操作,都会消耗服务器的资源,那么此时,就会用缓存来减轻压力。将经常用到的数据给缓存起来,当有用户需要的时候就直接给,这样就会减少资源浪费。
Django提供的6种缓存机制
开发调试缓存
内存缓存
文件缓存
数据库缓存
Memcache缓存(使用python-memcache模块)
Memcacae缓存(使用pylibmc模块)
经常用到的是文件缓存和Memcahe缓存
models常用的13个API查询
1.all 查询全部
2.filter 过滤(后面加条件)
3.get 只能查询确切的一条,查询不到或者查询到多条都会报错
4.exclude 除了.....和filter是相反的
5.order_by 排序,默认升序排序,必须由参数,倒叙就在参数前面加负号即可
举例:Book.objects.all().order_by("-price")
6.values
7.values_list
8.distinct 去重
9.count 计数
10.first
11.last
12.Book.objects.all()[2:5]
13.exist
有关only和defer
d = models.User.objects.all().only("name","email") #拿到的还是一个QuerySet集合,仅仅取name和email
for item in d:
print(item.id)
print(item.name)
print(item.pwd) #只要表里有这个字段,一样会取到值,额外的会再发一次请求
d = models.User.objects.all().defer("name","email") #阻止,不取name和email
for item in datalist:
print(item.id)
print(item.pwd
ps:如果用only的话就尽量用only里面的字段,用别的查询效率太低,我们尽量的去减少连接数据库的次数
Form组件
form组件的作用
1.用户请求验证
2.自动生成错误信息
3.根据我们的情况而定,就比如注册时我们写错了用户名,但是别的信息正确,就只会让我们再次输入用 户名,其余的数据保留
4.在form表单中会简单很多,由三种方法,具体在下面介绍
5.如果全部输入正确就是打包提交
widgets
每一个表单都有一个对应的widgets类,它对应一个HTML表单widget,
# 给html添加属性
widget=widgets.TextInput(attrs={"class": "form-control"}),
Form组件的字段
一般我们会在自己创建的应用下面创建一个py文件
forms.py
form django import forms
class RegisterForm(forms.Form):
user = forms.CharField(max_length=18, min_length=4,
widget=widgets.TextInput(attrs={"class": "form-control"}),
error_messages={
"required": "用户名不能为空",
"max_length": "最大长度为18",
"min_length": "最小长度为4"
}
)
pwd = forms.CharField(max_length=20, min_length=4,
widget=widgets.PasswordInput(attrs={"class": "form-control"}),
error_messages={
"required": "密码不能为空",
"max_length": "最大长度为20",
"min_length": "最小长度为4"
})
repeat_pwd = forms.CharField(max_length=20, min_length=4,
widget=widgets.PasswordInput(attrs={"class": "form-control"}),
error_messages={
"required": "密码不能为空",
"max_length": "最大长度为20",
"min_length": "最小长度为4"
})
email = forms.EmailField(max_length=20,
# 给html添加属性
widget=widgets.TextInput(attrs={"class": "form-control"}),
error_messages={
"required": "邮箱不能为空",
"max_length": "最大长度为20",
"invalid": "格式错误"
}
)
tel = forms.CharField(
widget=widgets.TextInput(attrs={"class": "form-control"}),
error_messages={
"required": "电话号码不能为空",
}
)
字段的数据
不管表单提交的是什么数据,一旦通过调用is_valid()成功验证返回True,那么验证后的表单数据将位于form.cleaned_data的字典中,
这些数据已经转换为python类型
但是此时依然可以在从request.POST中直接访问到未验证到的数据,但是访问验证后的数据更好一些(具体的在例子中具解释)
绑定和未绑定表单的区别
未绑定的表单没有关联的数据。当渲染给用户时,它将为空或包含默认的值。
绑定的表单具有提交的数据,因此可以用来检验数据是否合法。如果渲染一个不合法的绑定的表单,
它将包含内联的错误信息,告诉用户如何纠正数据。
表单在html中渲染的三种方法
1.用p标签包起来的
<form action="" novalidate method="post">
{% csrf_token %}
{{ form_obj.as_p }}
<input type="submit">
</form>
2.尽量用这一种
<form action="" novalidate method="post">
{% csrf_token %}
<div>
<label for="">用户名</label>
{{ form_obj.user }} <span>{{ form_obj.errors.user.0 }}</span>
</div>
<div>
<label for="">密码</label>
{{ form_obj.pwd }}<span>{{ form_obj.errors.pwd.0 }}</span>
</div>
<input type="submit">
</form>
3.循环
form action="" novalidate method="post">
{% csrf_token %}
{% for field in form_obj %}
<div>
<label for="">{{ field.label }}</label>
{{ field }}
</div>
{% endfor %}
<input type="submit">
</form>
Form组件的钩子
局部钩子
这个的意思也就是我们在字段里面没有设置,但是却是我们需要的,就单拿出来进行校验
因为是局部的,也就是针对一个字段的,所以名字用clean_user(字段名)
# 校验用户名(局部钩子)
def clean_user(self):
val = self.cleaned_data.get("user")
user_obj = models.User.objects.filter(user=val)
if not val.isdigit() and not user_obj:
return val
elif user_obj:
raise ValidationError("该用户已注册")
else:
raise ValidationError("用户名不能为纯数字")
全局钩子
针对多个联合校验,所以直接用clean
# 全局钩子函数
def clean(self):
pwd = self.cleaned_data.get("pwd")
repeat_pwd = self.cleaned_data.get("repeat_pwd")
if pwd == repeat_pwd:
return self.cleaned_data
else:
raise ValidationError("两次密码不一致")
注册举例
(这里因为东西少,所以forms.py和views在一起写着)
urls
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
# url(r'^admin/', admin.site.urls),
url(r'^register/',views.register),
]
views中
from django.shortcuts import render, redirect, HttpResponse
from app01 import models
from django import forms
from django.forms import widgets
from django.forms import ValidationError
# Create your views here.
class RegisterForm(forms.Form):
user = forms.CharField(max_length=18, min_length=4,
widget=widgets.TextInput(attrs={"class": "form-control"}),
error_messages={
"required": "用户名不能为空",
"max_length": "最大长度为18",
"min_length": "最小长度为4"
}
)
pwd = forms.CharField(max_length=20, min_length=4,
widget=widgets.PasswordInput(attrs={"class": "form-control"}),
error_messages={
"required": "密码不能为空",
"max_length": "最大长度为20",
"min_length": "最小长度为4"
})
repeat_pwd = forms.CharField(max_length=20, min_length=4,
widget=widgets.PasswordInput(attrs={"class": "form-control"}),
error_messages={
"required": "密码不能为空",
"max_length": "最大长度为20",
"min_length": "最小长度为4"
})
email = forms.EmailField(max_length=20,
# 给html添加属性
widget=widgets.TextInput(attrs={"class": "form-control"}),
error_messages={
"required": "邮箱不能为空",
"max_length": "最大长度为20",
"invalid": "格式错误"
}
)
tel = forms.CharField(
widget=widgets.TextInput(attrs={"class": "form-control"}),
error_messages={
"required": "电话号码不能为空",
}
)
# 校验用户名(局部钩子)
def clean_user(self):
val = self.cleaned_data.get("user")
user_obj = models.User.objects.filter(user=val)
if not val.isdigit() and not user_obj:
return val
elif user_obj:
raise ValidationError("该用户已注册")
else:
raise ValidationError("用户名不能为纯数字")
# 全局钩子函数
def clean(self):
pwd = self.cleaned_data.get("pwd")
repeat_pwd = self.cleaned_data.get("repeat_pwd")
if pwd == repeat_pwd:
return self.cleaned_data
else:
raise ValidationError("两次密码不一致")
def clean_tel(self):
te = self.cleaned_data.get("tel")
if te.isdigit():
return te
else:
raise ValidationError("电话号码必须是数字")
def register(request):
if request.method == "POST":
print("POST:", request.POST)
form_obj = RegisterForm(request.POST)
if form_obj.is_valid():
# 这里的意思是数据全部合格
# 取出合格数据
print(form_obj.cleaned_data)
return HttpResponse("登录成功")
else:
print(form_obj.errors)
repeat_pwd = form_obj.errors.get("__all__") # 两次密码不一致就来这里打印错误信息
print(form_obj.cleaned_data)
return render(request, "register.html", {"form_obj": form_obj,})
form_obj = RegisterForm() # 这个是没有数据的表单
return render(request, "register.html", {"form_obj": form_obj})
templates
regirster.py <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <script src="/static/bootstrap/dist/css/bootstrap.min.css"></script> <div class="container" > <div class="row"> <form class="form-horizontal " action="" method="post" novalidate> {# novalidate 不让浏览器做验证#} {% csrf_token %} <div class="form-group"> <label class="control-label" for="">用户名:</label> <div class="input-group"> {{ form_obj.user }}<span>{{ form_obj.errors.user.0 }}</span> </div> </div> <div class="form-group"> <label class="control-label" for="">密码:</label> <div class="input-group"> {{ form_obj.pwd }}<span>{{ form_obj.errors.pwd.0 }}</span> </div> </div> <div class="form-group"> <label class="control-label" for="">确认密码:</label> <div class="input-group"> {{ form_obj.repeat_pwd }}<span>{{ form_obj.errors.repeat_pwd.0 }}</span> </div> </div> <div class="form-group"> <label class="control-label" for="">邮箱:</label> <div class="input-group"> {{ form_obj.email }} <span>{{ form_obj.errors.email.0 }}</span> </div> </div> <div class="form-group"> <label class="control-label" for="">手机号:</label> <div class="input-group"> {{ form_obj.tel }} <span>{{ form_obj.errors.tel.0 }}</span> </div> </div> <div class="form-group"> <input type="submit" value="提交"> </div> </form> </div> </div> </body> </html>