第一章 django安装与介绍
第二章 django基础使用
第三章 路由层
第四章 虚拟环境、django版本区别、视图层
第五章 模板层
第六章 模型层(上)
第七章 模型层(下)
第八章 ajax
第九章 sweetalert前端插件、序列化组件、批量数据操作、分页器、Forms组件(上)
第十章 forms组件(下)、ModelForm简单使用、cookie与session简单使用
钩子函数的含义其实就是在程序的执行过程中穿插额外的逻辑,钩子函数是数据经过了字段第一层参数校验之后才会执行
使用钩子函数之前需要建立form组件类
from django import forms
from app01 import models
from django.core.exceptions import ValidationError
class MyForm(forms.Form):
username = forms.CharField(max_length=20, min_length=6,label='用户名', error_messages={
'min_length': '用户名最短为6位',
'max_lenght': '用户名最长为16位',
'required': '用户名不能为空',
})
password = forms.CharField(max_length=16, min_length=6,label='密码',error_messages={
'min_length': '用户名最短为6位',
'max_lenght': '用户名最长为16位',
'required': '密码不能为空',
})
email = forms.EmailField(required=True,label='邮箱', error_messages={
'invalid':'邮箱格式错误',
})
局部钩子只是针对form组件中的一个字段
eg:
使用局部钩子检测用户名是否存在
def clean_username(self):
username = self.cleaned_data.get('username')
is_has = models.User.objects.filter(username=username)
if is_has:
# self.add_error("username", "用户名已存在") # form组件提供的错误信息方法
raise ValidationError('用户名已存在') # 通过分析form组件代码发现可以使用python的异常来提供错误信息
return username
全局钩子针对form组件中的全部字段
eg:
使用全局钩子检测密码开头是否为大写字母
def clean(self):
# 1.获取字段数据
password = self.cleaned_data.get('password')
if not re.findall('^[A-Z]', password):
self.add_error('password', "密码开头必须为大写字母")
# 最后将整个数据返回
return self.cleaned_data
参数名 | 参数作用 |
---|---|
min_length | 最小长度 |
max_length | 最大长度 |
label | 字段名称 |
error_messages | 错误提示 |
min_value | 最小值 |
max_value | 最大值 |
initial | 默认值 |
validators | 正则校验器 |
widget | 控制渲染出来的标签各项属性 |
choices | 选择类型的标签内部对应关系 |
eg:
validators使用示例
from django.core.validators import RegexValidator
phone = forms.CharField(
validators=[
RegexValidator(r'^[0-9]+$', '请输入数字'),
RegexValidator(r'^184[0-9]+$', '数字必须以184开头')],
# RegexValidator可以使用多个他们之间的关系为且
)
widget使用示例
forms.widgets.控制type的类型(attrs=控制各项属性:class id 等标签属性…)
password = forms.CharField( widget=forms.widgets.PasswordInput(attrs={'class':'form-control'})
)
Field
required=True, 是否允许为空
widget=None, HTML插件
label=None, 用于生成Label标签或显示内容
initial=None, 初始值
help_text='', 帮助信息(在标签旁边显示)
error_messages=None, 错误信息 {'required': '不能为空', 'invalid': '格式错误'}
validators=[], 自定义验证规则
localize=False, 是否支持本地化
disabled=False, 是否可以编辑
label_suffix=None Label内容后缀
CharField(Field)
max_length=None, 最大长度
min_length=None, 最小长度
strip=True 是否移除用户输入空白
IntegerField(Field)
max_value=None, 最大值
min_value=None, 最小值
FloatField(IntegerField)
...
DecimalField(IntegerField)
max_value=None, 最大值
min_value=None, 最小值
max_digits=None, 总长度
decimal_places=None, 小数位长度
BaseTemporalField(Field)
input_formats=None 时间格式化
DateField(BaseTemporalField) 格式:2015-09-01
TimeField(BaseTemporalField) 格式:11:12
DateTimeField(BaseTemporalField)格式:2015-09-01 11:12
DurationField(Field) 时间间隔:%d %H:%M:%S.%f
...
RegexField(CharField)
regex, 自定制正则表达式
max_length=None, 最大长度
min_length=None, 最小长度
error_message=None, 忽略,错误信息使用 error_messages={'invalid': '...'}
EmailField(CharField)
...
FileField(Field)
allow_empty_file=False 是否允许空文件
ImageField(FileField)
...
注:需要PIL模块,pip3 install Pillow
以上两个字典使用时,需要注意两点:
- form表单中 enctype="multipart/form-data"
- view函数中 obj = MyForm(request.POST, request.FILES)
# 1.
class Form(six.with_metaclass(DeclarativeFieldsMetaclass, BaseForm)):
# 2.
class BaseForm(object):
def __init__(self, data=None, files=None, # 此处指列举了一部分 这俩个参数很重要
# 3.一些form组件的常用属性方法都在BaseForm中
@property
def errors(self): # 错误信息的处理方法
def is_valid(self): # form组件获取的数据验证是否为true的方法
def as_table(self): # form组件渲染标签
def as_ul(self):# form组件渲染标签
def as_p(self):# form组件渲染标签
forms组件主要配合models里面的默写类一起使用 但是默写类里面的字段需要在forms类中相当于重写一遍,代码冗余所以django将model和form结合起来制作了一个更方便的类,目前先简单使用
class MyUser(forms.ModelForm):
class Meta: # 此处类名必须是Meta
model = models.User # 指定关联的表
fields = '__all__' # 所有的字段全部生成对应的forms字段
labels = { # label标签名字
'username': '用户名',
'password': '密码',
'email': '邮箱'
}
widgets = { # 标签样式
"name": forms.widgets.TextInput(attrs={"class": "form-control"}),
}
eg:
代码示例
1.创建modelform继承类
class MyModelForm(forms.ModelForm):
class Meta:
model = models.User
fields = '__all__'
labels = {
'username': '用户名',
'password': '密码',
'email': '邮箱'
}
widgets = {
"username": forms.widgets.TextInput(attrs={"class": "form-control"}),
"password": forms.widgets.PasswordInput(attrs={"class": "form-control"}),
"email": forms.widgets.EmailInput(attrs={"class": "form-control"}),
}
2.视图层
def register(request):
datas = request.POST
form = MyModelForm()
# user = models.User.objects.filter(username=form.cleaned_data.get('username')).first()
if request.method == 'POST':
# 此处可以添加一个关键字参数来选择是更新还是新增
form = MyModelForm(data=datas) # 没有添加instance所以是新增
# form = MyModelForm(datas, instance=user) # 添加instance指定对那个对象镜像修改所以是更新
if form.is_valid():
form.save() # 执行数据的更新或者新增
# models.User.objects.create(**form.cleaned_data)# 使用form组件时的新增数据
# models.User.objects.filter(username=form.cleaned_data.get('username')).update(**form.cleaned_data)# 使用form组件时的更新数据
return render(request, 'register.html', locals())
3.模板层
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>注册title>
<link rel="stylesheet" href="/static/bootstrap-3.4.1-dist/css/bootstrap.css">
head>
<body>
<div class="container">
<form action="" method="post">
{% for foo in form %}
<div class="row">
<label>{{ foo.label }}label>
{{ foo }}<span style="color: red">{{ foo.errors.0 }}span>
div>
{% endfor %}
<input type="submit" value="注册" class="btn-success btn btn-default">
form>
div>
body>
html>
Cookie翻译成中文的意思是‘小甜饼’,是由W3C组织提出,最早由Netscape社区发展的一种机制。目前Cookie已经成为标准,所有的主流浏览器如IE、Netscape、Firefox、Opera等都支持Cookie。
服务器单从网络连接上无从知道客户身份。怎么办呢?就给客户端们颁发一个通行证吧,每人一个,无论谁访问都必须携带自己通行证。这样服务器就能从通行证上确认客户身份了。这就是Cookie的工作原理。
Cookie是客户端保存用户信息的一种机制,用来记录用户的一些信息,也是实现Session的一种方式。Cookie存储的数据量有限,且都是保存在客户端浏览器中。不同的浏览器有不同的存储大小,但一般不超过4KB。因此使用Cookie实际上只能存储一小段的文本信息(key-value格式)。
在WEB开发中,服务器可以为每个用户浏览器创建一个会话对象(session对象),注意:一个浏览器独占一个session对象(默认情况下)。因此,在需要保存用户数据时,服务器程序可以把用户数据写到用户浏览器独占的session中,当用户使用浏览器访问其它程序时,其它程序可以从用户的session中取出该用户的数据,为用户服务。
return HttpResonse()
return render()
return redirect()
…
不直接返回对象 而是先用变量名指代 然后操作对象方法
res = HttpResonse()
res.set_cookie()
return res
res = render()
return res
res = redirect()
return res
res.set_cookie() # 设置
res.COOKIE.get() # 获取
有很多视图函数需要添加登录认证 有时候又需要取消登录认证这个时候需要使用装饰器
示例:
未登陆时无法进入首页或主页,未登录用户在访问主页或首页时会自动跳转到登录页面,但登陆完毕后会跳转回之前想访问的页面
登录装饰器:
from django.shortcuts import redirect
def is_login(func):
def inner(request, *args, **kwargs):
url = request.path
if not request.COOKIES:
return redirect(f'/login/?last={url}')
res = func(request, *args, **kwargs)
return res
return inner
登录视图函数:
def login(request):
form = MyForm1()
if request.method == 'POST':
datas = request.POST
form = MyForm1(datas)
if form.is_valid():
username = form.cleaned_data.get('username')
uobj = models.User.objects.filter(username=username)
if uobj:
password = form.cleaned_data.get('password')
if password == uobj.first().password:
if not request.GET:
response = redirect('/home/')
response.set_cookie('username', username)
return response
url = request.GET["last"]
response = redirect(url)
response.set_cookie('username', username)
return response
return render(request, 'login.html', locals())
主页和首页的视图函数
@is_login
def home(request):
username = request.COOKIES.get("username")
return render(request, 'home.html', locals())
@is_login
def index(request):
username = request.COOKIES.get('username')
return render(request, 'index.html', locals())
form组件
from django import forms
from app01 import models
from django.core.exceptions import ValidationError
import re
class MyForm(forms.Form):
username = forms.CharField(max_length=20, min_length=6,label='用户名', error_messages={
'min_length': '用户名最短为6位',
'max_lenght': '用户名最长为16位',
'required': '用户名不能为空',
})
password = forms.CharField(max_length=16, min_length=6,label='密码',error_messages={
'min_length': '用户名最短为6位',
'max_lenght': '用户名最长为16位',
'required': '密码不能为空',
})
email = forms.EmailField(required=True,label='邮箱', error_messages={
'invalid':'邮箱格式错误',
})
def clean(self):
# 1.获取字段数据
password = self.cleaned_data.get('password')
if not re.findall('^[A-Z]', password):
self.add_error('password', "密码开头必须为大写字母")
# 最后将整个数据返回
username = self.cleaned_data.get('username')
is_has = models.User.objects.filter(username=username)
if is_has:
# self.add_error("username", "用户名已存在") # form组件提供的错误信息方法
raise ValidationError('用户名已存在') # 通过分析form组件代码发现可以使用python的异常来提供错误信息
return self.cleaned_data
class MyForm1(forms.Form):
username = forms.CharField(max_length=20, min_length=6, label='用户名', error_messages={
'min_length': '用户名最短为6位',
'max_lenght': '用户名最长为16位',
'required': '用户名不能为空',
})
password = forms.CharField(max_length=16, min_length=6, label='密码', error_messages={
'min_length': '用户名最短为6位',
'max_lenght': '用户名最长为16位',
'required': '密码不能为空',
})