django forms组件,model from组件
django forms组件,model from组件
内容概要
forms组件简单使用
form组件渲染标签
forms组件校验补充
forms组件参数补充
forms组件源码剖析
modelfrom组件
forms组件
小需求:获取用户数据并发送给后端校验 后端返回不符合校验规则的提示信息
form组件
1.自动校验数据
2.自动生成标签
3.自动展示信息
from django import forms
class MyForm(forms.Form):
username = forms.CharField(min_length=3, max_length=8) # username字段最少三个字符最大八个字符
age = forms.IntegerField(min_value=0, max_value=200) # 年龄最小0 最大200
email = forms.EmailField() # 必须符合邮箱格式
校验数据功能
form_obj = views.MyForm({'username':'jason','age':18,'email':'123'})
form_obj.is_valid() # 1.判断数据是否全部符合要求
False # 只要有一个不符合结果都是False
form_obj.cleaned_data # 2.获取符合校验条件的数据
{'username': 'jason', 'age': 18}
form_obj.errors # 3.获取不符合校验规则的数据及原因
{'email': ['Enter a valid email address.']}
1.只校验类中定义好的字段对应的数据 多传的根本不做任何操作
2.默认情况下类中定义好的字段都是必填的
forms组件渲染标签
<p>forms组件渲染标签的方式1(封装程度过高 扩展性差 主要用于本地测试):</p>
{# {{ form_obj.as_p }}#}
{# {{ form_obj.as_ul }}#}
{# {{ form_obj.as_table }}#}
<p>forms组件渲染标签的方式2(封装程度过低 扩展性高 编写麻烦)</p>
{# {{ form_obj.username.label }}#}
{# {{ form_obj.username }}#}
{# {{ form_obj.age.label }}#}
{# {{ form_obj.age }}#}
{# {{ form_obj.email.label }}#}
{# {{ form_obj.email }}#}
<p>forms组件渲染标签的方式3(封装程度较高 扩展性高 编写简单 推荐使用)</p>
{# {% for form in form_obj %}#}
{# <p>#}
{# {{ form.label }}#}
{# {{ form }}#}
{# </p>#}
{# {% endfor %}#}
注意事项:forms组件负责获取用户数据的标签 也就意味着form标签与按钮都需要自己写
前端的校验是弱不禁风的 最终都需要后端来校验 所以我们在使用forms组件的时候可用直接取消前端帮我们的校验
<form action="" method="post" novalidate>
forms组件展示信息
后端不同请求返回的forms对象一定要是相同的变量名
def ab_forms_func(request):
# 1.产生一个空对象
form_obj = MyForm()
if request.method == 'POST':
form_obj = MyForm(request.POST) # request.POST可以看成是一个字典 直接传给forms类校验 字典中无论有多少键值对都没关系 之在乎类中编写的
if form_obj.is_valid(): # 校验数据是否合法
print(form_obj.cleaned_data)
else:
print(form_obj.errors)
# 2.将该对象传递给html文件
return render(request, 'formsPage.html', locals())
{% for form in form_obj %}
<p>
{{ form.label }}
{{ form }}
<span>{{ form.errors.0 }}</span>
</p>
{% endfor %}
针对错误信息的提示可以修改成各国语言
方式1:自定义错误内容
给字段对象添加errors_messages参数
username = forms.CharField(min_length=3, max_length=8, label='用户名',
error_messages={
'min_length': '用户名最少三个字符',
'max_length': '用户名最多八个字符',
'required': '用户名不能为空'
}
)
方式2:修改系统语言环境
from django.conf import global_settings django内部真正的配置文件
LANGUAGE_CODE = 'zh-hans'
LANGUAGE_CODE = 'en-us'
# Languages we provide translations for, out of the box.
LANGUAGES = [
('af', gettext_noop('Afrikaans')),
('ar', gettext_noop('Arabic')),
('ast', gettext_noop('Asturian')),
('az', gettext_noop('Azerbaijani')),
('bg', gettext_noop('Bulgarian')),
('be', gettext_noop('Belarusian')),
('bn', gettext_noop('Bengali')),
('br', gettext_noop('Breton')),
('bs', gettext_noop('Bosnian')),
('ca', gettext_noop('Catalan')),
('cs', gettext_noop('Czech')),
('cy', gettext_noop('Welsh')),
('da', gettext_noop('Danish')),
('de', gettext_noop('German')),
('dsb', gettext_noop('Lower Sorbian')),
('el', gettext_noop('Greek')),
('en', gettext_noop('English')),
('en-au', gettext_noop('Australian English')),
('en-gb', gettext_noop('British English')),
('eo', gettext_noop('Esperanto')),
('es', gettext_noop('Spanish')),
('es-ar', gettext_noop('Argentinian Spanish')),
('es-co', gettext_noop('Colombian Spanish')),
('es-mx', gettext_noop('Mexican Spanish')),
('es-ni', gettext_noop('Nicaraguan Spanish')),
('es-ve', gettext_noop('Venezuelan Spanish')),
('et', gettext_noop('Estonian')),
('eu', gettext_noop('Basque')),
('fa', gettext_noop('Persian')),
('fi', gettext_noop('Finnish')),
('fr', gettext_noop('French')),
('fy', gettext_noop('Frisian')),
('ga', gettext_noop('Irish')),
('gd', gettext_noop('Scottish Gaelic')),
('gl', gettext_noop('Galician')),
('he', gettext_noop('Hebrew')),
('hi', gettext_noop('Hindi')),
('hr', gettext_noop('Croatian')),
('hsb', gettext_noop('Upper Sorbian')),
('hu', gettext_noop('Hungarian')),
('hy', gettext_noop('Armenian')),
('ia', gettext_noop('Interlingua')),
('id', gettext_noop('Indonesian')),
('io', gettext_noop('Ido')),
('is', gettext_noop('Icelandic')),
('it', gettext_noop('Italian')),
('ja', gettext_noop('Japanese')),
('ka', gettext_noop('Georgian')),
('kab', gettext_noop('Kabyle')),
('kk', gettext_noop('Kazakh')),
('km', gettext_noop('Khmer')),
('kn', gettext_noop('Kannada')),
('ko', gettext_noop('Korean')),
('lb', gettext_noop('Luxembourgish')),
('lt', gettext_noop('Lithuanian')),
('lv', gettext_noop('Latvian')),
('mk', gettext_noop('Macedonian')),
('ml', gettext_noop('Malayalam')),
('mn', gettext_noop('Mongolian')),
('mr', gettext_noop('Marathi')),
('my', gettext_noop('Burmese')),
('nb', gettext_noop('Norwegian Bokmål')),
('ne', gettext_noop('Nepali')),
('nl', gettext_noop('Dutch')),
('nn', gettext_noop('Norwegian Nynorsk')),
('os', gettext_noop('Ossetic')),
('pa', gettext_noop('Punjabi')),
('pl', gettext_noop('Polish')),
('pt', gettext_noop('Portuguese')),
('pt-br', gettext_noop('Brazilian Portuguese')),
('ro', gettext_noop('Romanian')),
('ru', gettext_noop('Russian')),
('sk', gettext_noop('Slovak')),
('sl', gettext_noop('Slovenian')),
('sq', gettext_noop('Albanian')),
('sr', gettext_noop('Serbian')),
('sr-latn', gettext_noop('Serbian Latin')),
('sv', gettext_noop('Swedish')),
('sw', gettext_noop('Swahili')),
('ta', gettext_noop('Tamil')),
('te', gettext_noop('Telugu')),
('th', gettext_noop('Thai')),
('tr', gettext_noop('Turkish')),
('tt', gettext_noop('Tatar')),
('udm', gettext_noop('Udmurt')),
('uk', gettext_noop('Ukrainian')),
('ur', gettext_noop('Urdu')),
('vi', gettext_noop('Vietnamese')),
('zh-hans', gettext_noop('Simplified Chinese')),
('zh-hant', gettext_noop('Traditional Chinese')),
]
forms组件校验补充
forms组件针对字段数据的校验 提供了三种类型的校验方式(可用一起使用)
第一种类型:直接填写参数 max_length
第二种类型:使用正则表达式 validators
第三种类型:钩子函数 编写代码自定义校验规则
钩子函数》》》校验的最后一环 是再字段所有的校验参数之后触发
class Myform(forms.Form):
username = forms.CharField(min_length=3, max_length=8, label='用户名'
, error_messages={
'max_length': '超出长度了',
'min_length': '细狗',
'required': '用户名名内容不能为空'
})
pwd = forms.CharField(max_length=32)
age = forms.IntegerField(max_value=200, min_value=0)
email = forms.EmailField(label='邮箱')
# 局部钩子
def clean_username(self):
username = self.cleaned_data.get('username')
if username == 'ikun':
self.add_error('username', '小黑子')
return username # 使用完毕后返回回去
# 全局钩子
def clean(self):
pwd = self.cleaned_data.get('pwd')
if pwd == '123':
self.add_error('pwd', '密码太简单了')
return self.cleaned_data # 使用完毕后返回回去
forms组件参数补充
min_length 最小字符
max_length 最大字符
min_value 最小值
max_value 最大值
label 字段注释
error_messages 错误提示
validators 正则校验器
initial 默认值
required 是否必填
widget 控制标签的各项属性
widget=forms.widgets.PasswordInput(attrs={'class': 'form-control', 'username': 'jason'})
forms组件源码剖析
切入口:form_obj.is_valued()
@property
def errors(self):
"""Return an ErrorDict for the data provided for the form."""
if self._errors is None: # 这个里self._errors刚开始是None所有向下走
self.full_clean() # 到这里
return self._errors
def is_valid(self):
"""Return True if the form has no errors, or False otherwise."""
# self.is_bound就是传入的数据没什么好看的,然后看self.errors再上面刚好找到是一个属性值方法
return self.is_bound and not self.errors
def full_clean(self):
"""
Clean all of self.data and populate self._errors and self.cleaned_data.
"""
self._errors = ErrorDict() # 生成一个错误字典看见Dict那么她就跟字典有关系
if not self.is_bound: # Stop further processing. 判断有没有传入数据
return
self.cleaned_data = {} # 创建一个存放干净数据的zi'di'a
# If the form is permitted to be empty, and none of the form data has
# changed from the initial data, short circuit any validation.
if self.empty_permitted and not self.has_changed():
return
self._clean_fields() # 清洗字段数据,局部钩子触发
self._clean_form() # 全局钩子
self._post_clean() # 暂时无用为以后提前写下的方法
model form组件
我们学习校验组件的目的 绝大部分是为了数据录入数据库之前各项审核
forms组件使用的时候需要对照模型类编写代码 不够方便
forms组件的强化版 更好用更简便更方便
from django import forms
from User import models
class MyModelForm(forms.ModelForm):
class Meta:
model = models.Book
fields = '__all__'
labels = {
'title': '书名1',
'price': '价格'
}
def model_form(request):
book_obj = models.Book.objects.filter(pk=5).first()
myobj = MyModelForm(initial=book_obj)
if request.method == 'POST':
myobj = MyModelForm(request.POST,instance=book_obj) # instance更快速的修改数据
myobj.save() # instance参数就算修改,没有就是新增数据
print(myobj.is_valid())
print(myobj.cleaned_data)
return render(request, 'formPage.html', locals())