day 66 form组件、forms组件的钩子函数

- 日理万妓 2021-09-30 14:52 365阅读 0赞

forms组件

需求示例:获取用户输入 后端判断用户输入的内容是否合法,如果不合法前端渲染对应的错误信息

传统:

ContractedBlock.gif ExpandedBlockStart.gif

  1. def register(request):
  2. back_dic = {
  3. 'username': '', 'password': ""}
  4. if request.method == 'POST':
  5. username = request.POST.get('username')
  6. pwd = request.POST.get('password')
  7. if '666' in username:
  8. res = "不能有666"
  9. back_dic['username'] = res
  10. if pwd == "123":
  11. res = "密码太简单"
  12. back_dic['password'] = res
  13. return render(request, 'reg.html', locals())

html:

ContractedBlock.gif ExpandedBlockStart.gif

  1. </head>
  2. <body>
  3. <form action="" method="post">
  4. {% csrf_token %}
  5. <p><input type="text" name="username">
  6. <span>{
  7. { back_dic.username }}</span>
  8. </p>
  9. <p><input type="text" name="password">
  10. <span>{
  11. { back_dic.password }}</span>
  12. </p>
  13. <input type="submit">
  14. </form>
  15. </body>
  16. </html>

用forms组件来实现:校验数据、渲染页面、展示提示信息

一、校验数据、【前后端都可以校验数据,前端可以没有,但是后端一定要有】 

  1.校验数据,需要一个类,继承forms.Form

ContractedBlock.gif ExpandedBlockStart.gif

  1. from django import forms
  2. class Myform(forms.Form):
  3. username = forms.CharField(max_length=8)
  4. password = forms.CharField(max_length=6, min_length=3)
  5. email = forms.EmailField()

  2. 给forms组件传参数(字典的形式) 

    obj = views.Myform({‘username’: ‘egion’, ‘passowrod’: ‘123’})

  3.查看数据校验结果

    obj.is_valid()

  4. 查看干净的数据

   obj.cleaned_data ==> 正确的以字典形式放入{‘username’: ‘egondsb2’, ‘password’: ‘123’}

  5. 查看不正确的数据

   obj.errors ==> 错误的放入{‘password’: [‘Ensure this value has at least 3 characters (it has 2).’],

                ‘email’: [‘This field is required.’]}

ContractedBlock.gif ExpandedBlockStart.gif

  1. from app01 import views
  2. obj = views.Myform({
  3. "username":"egondsb", "password": "123"})
  4. obj.is_valid()
  5. False
  6. obj.cleaned_data
  7. {
  8. 'password': '123'}
  9. obj.errors
  10. {
  11. 'username': ['Ensure this value has at most 6 characters (it has 7).'], 'email': ['This field is required.']}

  ps: forms组件中所有的字段默认都是必填的(不能为空)

    在数据都满足forms组件校验规则的情况下,多传的数据不作校验,

补充:正则校验数据

  1. from django.core.validators import RegexValidator
  2. phone = forms.CharField(validators=[RegexValidator(r'^[0-9]+$', '请输入数字'),
  3. RegexValidator(r'^159[0-9]+$', '必须以159开头')])

RegexValidator验证器

ContractedBlock.gif ExpandedBlockStart.gif

  1. from django.forms import Form
  2. from django.forms import widgets
  3. from django.forms import fields
  4. from django.core.validators import RegexValidator
  5. class MyForm(Form):
  6. user = fields.CharField(
  7. validators=[RegexValidator(r'^[0-9]+$', '请输入数字'), RegexValidator(r'^159[0-9]+$', '数字必须以159开头')],
  8. )

自定义验证函数

ContractedBlock.gif

二. 渲染页面、 forms组件只能帮你渲染 获取用户输入(输入框 、选择框 、下拉框 。。。) 提交按钮也得自己写

  前端页面识别到是forms组件时,也会校验数据长度,

  form表单取消前端校验的提示信息:

  initial 初始值, input框里面的初始值

  views:

ContractedBlock.gif ExpandedBlockStart.gif

  1. def reg1(request):
  2. form_obj = Myform()
  3. return render(request, 'reg1.html', locals())

  1.第一种渲染页面的方式【扩展性不高,本地测试】 as_p 、| as_ul

ContractedBlock.gif ExpandedBlockStart.gif

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. <form action="" method="post">
  9. {
  10. % csrf_token %}
  11. <p>forms第一种渲染标签的方式</p>
  12. {
  13. # {
  14. { form_obj.as_p }} p标签包裹着#}
  15. {
  16. { form_obj.as_ul }} li标签包裹着
  17. {
  18. #lable展示的信息默认情况下是字段名首字母大写#}
  19. </form>
  20. </body>
  21. </html>

  

  2. 第二种,输入框与label名需自己写,缺点是,当字段比较多时,需要一个个的写,麻烦!包裹p标签

ContractedBlock.gif ExpandedBlockStart.gif

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. <form action="" method="post">
  9. <p>forms第二种渲染标签的方式</p>
  10. <p>
  11. {
  12. { form_obj.username.label }}{
  13. { form_obj.username }} {
  14. # forms对象点字段名拿到的是对应的输入框 #}
  15. </p>
  16. <p>
  17. {
  18. { form_obj.password.label }}{
  19. { form_obj.password }} {
  20. # forms对象点字段名拿到的是对应的输入框 #}
  21. </p>
  22. </form>

  

  3.第三种,常用方式

ContractedBlock.gif ExpandedBlockStart.gif

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. <form action="" method="post" novalidate>
  9. {
  10. % csrf_token %}
  11. {
  12. % for foo in form_obj %}
  13. <p>{
  14. { foo.label }}{
  15. { foo }}
  16. <span>{
  17. { foo.errors.0 }}</span>
  18. </p>
  19. {
  20. % endfor %}
  21. <input type="submit">
  22. </form>
  23. </body>
  24. </html>

Django Form所有内置字段

ContractedBlock.gif ExpandedBlockStart.gif

  1. Field
  2. required=True, 是否允许为空
  3. widget=None, HTML插件
  4. label=None, 用于生成Label标签或显示内容
  5. initial=None, 初始值
  6. help_text='', 帮助信息(在标签旁边显示)
  7. error_messages=None, 错误信息 {
  8. 'required': '不能为空', 'invalid': '格式错误'}
  9. validators=[], 自定义验证规则
  10. localize=False, 是否支持本地化
  11. disabled=False, 是否可以编辑
  12. label_suffix=None Label内容后缀
  13. CharField(Field)
  14. max_length=None, 最大长度
  15. min_length=None, 最小长度
  16. strip=True 是否移除用户输入空白
  17. IntegerField(Field)
  18. max_value=None, 最大值
  19. min_value=None, 最小值
  20. FloatField(IntegerField)
  21. ...
  22. DecimalField(IntegerField)
  23. max_value=None, 最大值
  24. min_value=None, 最小值
  25. max_digits=None, 总长度
  26. decimal_places=None, 小数位长度
  27. BaseTemporalField(Field)
  28. input_formats=None 时间格式化
  29. DateField(BaseTemporalField) 格式:2015-09-01
  30. TimeField(BaseTemporalField) 格式:11:12
  31. DateTimeField(BaseTemporalField)格式:2015-09-01 11:12
  32. DurationField(Field) 时间间隔:%d %H:%M:%S.%f
  33. ...
  34. RegexField(CharField)
  35. regex, 自定制正则表达式
  36. max_length=None, 最大长度
  37. min_length=None, 最小长度
  38. error_message=None, 忽略,错误信息使用 error_messages={
  39. 'invalid': '...'}
  40. EmailField(CharField)
  41. ...
  42. FileField(Field)
  43. allow_empty_file=False 是否允许空文件
  44. ImageField(FileField)
  45. ...
  46. 注:需要PIL模块,pip3 install Pillow
  47. 以上两个字典使用时,需要注意两点:
  48. - form表单中 enctype="multipart/form-data"
  49. - view函数中 obj = MyForm(request.POST, request.FILES)
  50. URLField(Field)
  51. ...
  52. BooleanField(Field)
  53. ...
  54. NullBooleanField(BooleanField)
  55. ...
  56. ChoiceField(Field)
  57. ...
  58. choices=(), 选项,如:choices = ((0,'上海'),(1,'北京'),)
  59. required=True, 是否必填
  60. widget=None, 插件,默认select插件
  61. label=None, Label内容
  62. initial=None, 初始值
  63. help_text='', 帮助提示
  64. ModelChoiceField(ChoiceField)
  65. ... django.forms.models.ModelChoiceField
  66. queryset, # 查询数据库中的数据
  67. empty_label="---------", # 默认空显示内容
  68. to_field_name=None, # HTML中value的值对应的字段
  69. limit_choices_to=None # ModelForm中对queryset二次筛选
  70. ModelMultipleChoiceField(ModelChoiceField)
  71. ... django.forms.models.ModelMultipleChoiceField
  72. TypedChoiceField(ChoiceField)
  73. coerce = lambda val: val 对选中的值进行一次转换
  74. empty_value= '' 空值的默认值
  75. MultipleChoiceField(ChoiceField)
  76. ...
  77. TypedMultipleChoiceField(MultipleChoiceField)
  78. coerce = lambda val: val 对选中的每一个值进行一次转换
  79. empty_value= '' 空值的默认值
  80. ComboField(Field)
  81. fields=() 使用多个验证,如下:即验证最大长度20,又验证邮箱格式
  82. fields.ComboField(fields=[fields.CharField(max_length=20), fields.EmailField(),])
  83. MultiValueField(Field)
  84. PS: 抽象类,子类中可以实现聚合多个字典去匹配一个值,要配合MultiWidget使用
  85. SplitDateTimeField(MultiValueField)
  86. input_date_formats=None, 格式列表:['%Y--%m--%d', '%m%d/%Y', '%m/%d/%y']
  87. input_time_formats=None 格式列表:['%H:%M:%S', '%H:%M:%S.%f', '%H:%M']
  88. FilePathField(ChoiceField) 文件选项,目录下文件显示在页面中
  89. path, 文件夹路径
  90. match=None, 正则匹配
  91. recursive=False, 递归下面的文件夹
  92. allow_files=True, 允许文件
  93. allow_folders=False, 允许文件夹
  94. required=True,
  95. widget=None,
  96. label=None,
  97. initial=None,
  98. help_text=''
  99. GenericIPAddressField
  100. protocol='both', both,ipv4,ipv6支持的IP格式
  101. unpack_ipv4=False 解析ipv4地址,如果是::ffff:192.0.2.1时候,可解析为192.0.2.1 PSprotocol必须为both才能启用
  102. SlugField(CharField) 数字,字母,下划线,减号(连字符)
  103. ...
  104. UUIDField(CharField) uuid类型

三.展示信息

 1. label名,错误息信, 密码密文【from django.forms import widgets】,等可以在类中先定义

ContractedBlock.gif ExpandedBlockStart.gif

  1. from django import forms
  2. from django.forms import widgets
  3. class Myform(forms.Form):
  4. username = forms.CharField(max_length=8, label="用户名", initial="张三", error_messages={
  5. "required": "用户名不能为空",
  6. "max_length": "用户名长度不能超过8位"})
  7. password = forms.CharField(max_length=6, min_length=3,
  8. widget=forms.widgets.PasswordInput(attrs={
  9. "class": "form-control c1"}),
  10. error_messages={
  11. "required": "邮箱不能为空", "invalid": "邮箱格式不正确"})
  12. email = forms.EmailField()

choice字段、 多选checkbox、单选select、radioSelect、password

ContractedBlock.gif ExpandedBlockStart.gif

  1. class Myform2(forms.Form):
  2. gender = forms.fields.ChoiceField(
  3. choices=((1, "男"), (2, "女"), (3, "保密")),
  4. label="性别",
  5. initial=3,
  6. widget=forms.widgets.RadioSelect()
  7. )
  8. hobby = forms.MultipleChoiceField(
  9. choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
  10. label="爱好",
  11. initial=[1, 3],
  12. widget=forms.widgets.CheckboxSelectMultiple()
  13. )
  14. keep = forms.ChoiceField(
  15. label="是否记住密码",
  16. initial="checked",
  17. widget=forms.widgets.CheckboxInput()
  18. )
  19. hobby1 = forms.ChoiceField(
  20. choices=((1, "篮球"), (2, "足球"), (3, "双色球"), ),
  21. label="爱好",
  22. initial=3,
  23. widget=forms.widgets.Select()
  24. )
  25. username = forms.CharField(
  26. min_length=8,
  27. label="用户名",
  28. initial="张三",
  29. error_messages={
  30. "required": "不能为空",
  31. "invalid": "格式错误",
  32. "min_length": "用户名最短8位"
  33. }
  34. )
  35. def reg2(request):
  36. myform2 = Myform2()
  37. if request.method == "POST":
  38. myform2 = Myform2(request.POST)
  39. if myform2.is_valid():
  40. print(myform2.cleaned_data)
  41. return render(request, "reg2.html", locals())

在django中测试脚本:

1.新建一个test文件:

ContractedBlock.gif ExpandedBlockStart.gif

  1. import os
  2. import sys
  3. if __name__ == "__main__":
  4. os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day66ajaxformdata.settings")
  5. import django
  6. django.setup()
  7. # 将要测试的代码导入
  8. from app01 import models
  9. print(models.Userinfo.objects.all())

ContractedBlock.gif ExpandedBlockStart.gif

  1. import os
  2. import sys
  3. if __name__ == "__main__":
  4. os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day66ajaxformdata.settings")
  5. import django
  6. django.setup()
  7. # 将要测试的代码导入
  8. # from app01 import models
  9. # print(models.Userinfo.objects.all())
  10. from app01 import views
  11. obj = views.Myform({
  12. 'username': "egon", "password": '123'})
  13. print(obj.is_valid())
  1. python console 中测试,直接导入需要测试的文件,下面以测试上面forms组件为例

  python Console中

ContractedBlock.gif ExpandedBlockStart.gif

  1. from app01 import views
  2. obj = views.Myform({
  3. "username":"egondsb", "password": "123"})
  4. obj.is_valid() # 校验数据结果
  5. False
  6. obj.cleaned_data
  7. {
  8. 'password': '123'}
  9. obj.errors
  10. {
  11. 'username': ['Ensure this value has at most 6 characters (it has 7).'], 'email': ['This field is required.']}

forms组件的钩子函数 Hook方法【在form类中写钩子函数】

数据校验顺序:先校验字段中的条件,再走钩子函数规则

局部钩子【校验单个字段】 : 在用户名中不能有666字样

ContractedBlock.gif ExpandedBlockStart.gif

  1. from django import forms
  2. from django.forms import widgets
  3. from django.core.validators import RegexValidator
  4. class Myform(forms.Form):
  5. username = forms.CharField(max_length=8, label="用户名", initial="张三", error_messages={
  6. "required": "用户名不能为空",
  7. "max_length": "用户名长度不能超过8位"})
  8. password = forms.CharField(max_length=6, min_length=3,
  9. widget=forms.widgets.PasswordInput(attrs={
  10. "class": "form-control c1"}),
  11. error_messages={
  12. "required": "邮箱不能为空", "invalid": "邮箱格式不正确"})
  13. email = forms.EmailField()
  14. phone = forms.CharField(validators=[RegexValidator(r'^[0-9]+$', '请输入数字'),
  15. RegexValidator(r'^159[0-9]+$', '必须以159开头')])
  16. def clean_username(self):
  17. # 用户名不能有666
  18. username = self.cleaned_data.get('username')
  19. if "666" in username:
  20. self.add_error('username', '光喊666是不行的')
  21. return username

全局钩子【校验多个字段】:两次密码需一致

ContractedBlock.gif ExpandedBlockStart.gif

  1. from django import forms
  2. from django.forms import widgets
  3. from django.core.validators import RegexValidator
  4. class Myform(forms.Form):
  5. username = forms.CharField(max_length=8, label="用户名", initial="张三", error_messages={
  6. "required": "用户名不能为空",
  7. "max_length": "用户名长度不能超过8位"})
  8. password = forms.CharField(max_length=6, min_length=3,
  9. widget=forms.widgets.PasswordInput(attrs={
  10. "class": "form-control c1"}),)
  11. confirm_password = forms.CharField(max_length=8, min_length=3, label="确认密码",
  12. widget=forms.widgets.PasswordInput(attrs={
  13. "class": "form-control c1"}))
  14. email = forms.EmailField(error_messages={
  15. "required": "邮箱不能为空", "invalid": "邮箱格式不正确"})
  16. phone = forms.CharField(validators=[RegexValidator(r'^[0-9]+$', '请输入数字'),
  17. RegexValidator(r'^159[0-9]+$', '必须以159开头')])
  18. def clean_username(self):
  19. # 用户名不能有666
  20. username = self.cleaned_data.get('username')
  21. if "666" in username:
  22. self.add_error('username', '光喊666是不行的')
  23. return username
  24. def clean(self):
  25. password = self.cleaned_data.get('password')
  26. confirm_password = self.cleaned_data.get('confirm_password')
  27. if password != confirm_password:
  28. self.add_error("confirm_password", "两次密码不一致")
  29. return self.cleaned_data

转载于:https://www.cnblogs.com/qingqinxu/p/11226097.html

发表评论

表情:
评论列表 (有 0 条评论,365人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Django Form

    常用功能 From 组件主要有以下几大功能: 生成 HTML 标签 验证用户数据(显示错误信息) HTML Form 提交保留上次提交数据 初始