经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » Python » 查看文章
Form组件
来源:cnblogs  作者:panda/勇  时间:2018/10/22 16:28:55  对本文有异议

Form介绍

  主要功能:

  • 生成页面可用的HTML标签
  • 对用户提交的数据进行校验
  • 保留上次输入内容

 

实现注册功能的普通方式

  views.py

  1. def register(request):
  2. error_msg = ""
  3. if request.method == "POST":
  4. username = request.POST.get("name")
  5. pwd = request.POST.get("pwd")
  6. # 对注册信息做校验
  7. if len(username) < 6:
  8. # 用户长度小于6位
  9. error_msg = "用户名长度不能小于6位"
  10. else:
  11. # 将用户名和密码存到数据库
  12. return HttpResponse("注册成功")
  13. return render(request, "register.html", {"error_msg": error_msg})

  login.html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>注册页面</title>
  6. </head>
  7. <body>
  8. <form action="/reg/" method="post">
  9. {% csrf_token %}
  10. <p>
  11. 用户名:
  12. <input type="text" name="name">
  13. </p>
  14. <p>
  15. 密码:
  16. <input type="password" name="pwd">
  17. </p>
  18. <p>
  19. <input type="submit" value="注册">
  20. <p style="color: red">{{ error_msg }}</p>
  21. </p>
  22. </form>
  23. </body>
  24. </html>

 

实现注册功能的form组件

  views.py

  先定义好一个RegForm类:

  1. from django import forms
  2. # 按照Django form组件的要求自己写一个类
  3. class RegForm(forms.Form):
  4. name = forms.CharField(label="用户名")
  5. pwd = forms.CharField(label="密码")

  再写一个视图函数

  1. # 使用form组件实现注册方式
  2. def register2(request):
  3. form_obj = RegForm()
  4. if request.method == "POST":
  5. # 实例化form对象的时候,把post提交过来的数据直接传进去
  6. form_obj = RegForm(request.POST)
  7. # 调用form_obj校验数据的方法
  8. if form_obj.is_valid():
  9. return HttpResponse("注册成功")
  10. return render(request, "register2.html", {"form_obj": form_obj})

  login2.html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>注册2</title>
  6. </head>
  7. <body>
  8. <form action="/reg2/" method="post" novalidate autocomplete="off">
  9. {% csrf_token %}
  10. <div>
  11. <label for="{{ form_obj.name.id_for_label }}">{{ form_obj.name.label }}</label>
  12. {{ form_obj.name }} {{ form_obj.name.errors.0 }}
  13. </div>
  14. <div>
  15. <label for="{{ form_obj.pwd.id_for_label }}">{{ form_obj.pwd.label }}</label>
  16. {{ form_obj.pwd }} {{ form_obj.pwd.errors.0 }}
  17. </div>
  18. <div>
  19. <input type="submit" class="btn btn-success" value="注册">
  20. </div>
  21. </form>
  22. </body>
  23. </html>

 

常用字段与插件

  创建Form类时,主要涉及到'字段'和'插件', 字段用于对用户请求数据的验证,插件用于自动生成HTML;

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

  1. class LoginForm(forms.Form):
  2. username = forms.CharField(
  3. min_length=8,
  4. label="用户名",
  5. initial="张三" # 设置默认值
  6. )
  7. pwd = forms.CharField(min_length=6, label="密码")

  error_messages  重写错误信息

  1. class LoginForm(forms.Form):
  2. username = forms.CharField(
  3. min_length=8,
  4. label="用户名",
  5. initial="张三",
  6. error_messages={
  7. "required": "不能为空",
  8. "invalid": "格式错误",
  9. "min_length": "用户名最短8位"
  10. }
  11. )
  12. pwd = forms.CharField(min_length=6, label="密码")

  password

  1. class LoginForm(forms.Form):
  2. ...
  3. pwd = forms.CharField(
  4. min_length=6,
  5. label="密码",
  6. widget=forms.widgets.PasswordInput(attrs={'class': 'c1'}, render_value=True)
  7. )

  radioSelect  单radio值为字符串

  1. class LoginForm(forms.Form):
  2. username = forms.CharField(
  3. min_length=8,
  4. label="用户名",
  5. initial="张三",
  6. error_messages={
  7. "required": "不能为空",
  8. "invalid": "格式错误",
  9. "min_length": "用户名最短8位"
  10. }
  11. )
  12. pwd = forms.CharField(min_length=6, label="密码")
  13. gender = forms.fields.ChoiceField(
  14. choices=((1, ""), (2, ""), (3, "保密")),
  15. label="性别",
  16. initial=3,
  17. widget=forms.widgets.RadioSelect()
  18. )

  单选Select

  1. class LoginForm(forms.Form):
  2. ...
  3. hobby = forms.fields.ChoiceField(
  4. choices=((1, "篮球"), (2, "足球"), (3, "双色球"), ),
  5. label="爱好",
  6. initial=3,
  7. widget=forms.widgets.Select()
  8. )

  多选Select

  1. class LoginForm(forms.Form):
  2. ...
  3. hobby = forms.fields.MultipleChoiceField(
  4. choices=((1, "篮球"), (2, "足球"), (3, "双色球"), ),
  5. label="爱好",
  6. initial=[1, 3],
  7. widget=forms.widgets.SelectMultiple()
  8. )

  单选checkbox

  1. class LoginForm(forms.Form):
  2. ...
  3. keep = forms.fields.ChoiceField(
  4. label="是否记住密码",
  5. initial="checked",
  6. widget=forms.widgets.CheckboxInput()
  7. )

  多选checkbox

  1. class LoginForm(forms.Form):
  2. ...
  3. hobby = forms.fields.MultipleChoiceField(
  4. choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
  5. label="爱好",
  6. initial=[1, 3],
  7. widget=forms.widgets.CheckboxSelectMultiple()
  8. )

  关于choice的注意事项:

  在使用选择标签时,需要注意choices的选项可以从数据库中获取,但是由于是静态字段 ***获取的值无法实时更新***,那么需要自定义构造方法从而达到此目的。

  

  方式一:

  1. from django.forms import Form
  2. from django.forms import widgets
  3. from django.forms import fields
  4. class MyForm(Form):
  5. user = fields.ChoiceField(
  6. # choices=((1, '上海'), (2, '北京'),),
  7. initial=2,
  8. widget=widgets.Select
  9. )
  10. def __init__(self, *args, **kwargs):
  11. super(MyForm,self).__init__(*args, **kwargs)
  12. # self.fields['user'].choices = ((1, '上海'), (2, '北京'),)
  13. #
  14. self.fields['user'].choices = models.Classes.objects.all().values_list('id','caption')

 

  方式二:

  1. from django import forms
  2. from django.forms import fields
  3. from django.forms import models as form_model
  4. class FInfo(forms.Form):
  5. authors = form_model.ModelMultipleChoiceField(queryset=models.NNewType.objects.all()) # 多选
  6. # authors = form_model.ModelChoiceField(queryset=models.NNewType.objects.all()) # 单选

 

Django  Form所有内置字段

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

 

校验

  方式一:

  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. )

 

  方式二

  1. import re
  2. from django.forms import Form
  3. from django.forms import widgets
  4. from django.forms import fields
  5. from django.core.exceptions import ValidationError
  6. # 自定义验证规则
  7. def mobile_validate(value):
  8. mobile_re = re.compile(r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$')
  9. if not mobile_re.match(value):
  10. raise ValidationError('手机号码格式错误')
  11. class PublishForm(Form):
  12. title = fields.CharField(max_length=20,
  13. min_length=5,
  14. error_messages={'required': '标题不能为空',
  15. 'min_length': '标题最少为5个字符',
  16. 'max_length': '标题最多为20个字符'},
  17. widget=widgets.TextInput(attrs={'class': "form-control",
  18. 'placeholder': '标题5-20个字符'}))
  19. # 使用自定义验证规则
  20. phone = fields.CharField(validators=[mobile_validate, ],
  21. error_messages={'required': '手机不能为空'},
  22. widget=widgets.TextInput(attrs={'class': "form-control",
  23. 'placeholder': u'手机号码'}))
  24. email = fields.EmailField(required=False,
  25. error_messages={'required': u'邮箱不能为空','invalid': u'邮箱格式错误'},
  26. widget=widgets.TextInput(attrs={'class': "form-control", 'placeholder': u'邮箱'}))

 

应用Bootstrap样式

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="x-ua-compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1">
  7. <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css">
  8. <title>login</title>
  9. </head>
  10. <body>
  11. <div class="container">
  12. <div class="row">
  13. <form action="/login2/" method="post" novalidate class="form-horizontal">
  14. {% csrf_token %}
  15. <div class="form-group">
  16. <label for="{{ form_obj.username.id_for_label }}"
  17. class="col-md-2 control-label">{{ form_obj.username.label }}</label>
  18. <div class="col-md-10">
  19. {{ form_obj.username }}
  20. <span class="help-block">{{ form_obj.username.errors.0 }}</span>
  21. </div>
  22. </div>
  23. <div class="form-group">
  24. <label for="{{ form_obj.pwd.id_for_label }}" class="col-md-2 control-label">{{ form_obj.pwd.label }}</label>
  25. <div class="col-md-10">
  26. {{ form_obj.pwd }}
  27. <span class="help-block">{{ form_obj.pwd.errors.0 }}</span>
  28. </div>
  29. </div>
  30. <div class="form-group">
  31. <label class="col-md-2 control-label">{{ form_obj.gender.label }}</label>
  32. <div class="col-md-10">
  33. <div class="radio">
  34. {% for radio in form_obj.gender %}
  35. <label for="{{ radio.id_for_label }}">
  36. {{ radio.tag }}{{ radio.choice_label }}
  37. </label>
  38. {% endfor %}
  39. </div>
  40. </div>
  41. </div>
  42. <div class="form-group">
  43. <div class="col-md-offset-2 col-md-10">
  44. <button type="submit" class="btn btn-default">注册</button>
  45. </div>
  46. </div>
  47. </form>
  48. </div>
  49. </div>
  50.  
  51. <script src="/static/jquery-3.2.1.min.js"></script>
  52. <script src="/static/bootstrap/js/bootstrap.min.js"></script>
  53. </body>
  54. </html>

 

批量添加  可以通过重写form类的init方法来实现

  1. class LoginForm(forms.Form):
  2. username = forms.CharField(
  3. min_length=8,
  4. label="用户名",
  5. initial="张三",
  6. error_messages={
  7. "required": "不能为空",
  8. "invalid": "格式错误",
  9. "min_length": "用户名最短8位"
  10. }
  11. ...
  12. def __init__(self, *args, **kwargs):
  13. super(LoginForm, self).__init__(*args, **kwargs)
  14. for field in iter(self.fields):
  15. self.fields[field].widget.attrs.update({
  16. 'class': 'form-control'
  17. })

 

ModelForm  form与model的终极结合

  1. class BookForm(forms.ModelForm):
  2. class Meta:
  3. model = models.Book
  4. fields = "__all__"
  5. labels = {
  6. "title": "书名",
  7. "price": "价格"
  8. }
  9. widgets = {
  10. "password": forms.widgets.PasswordInput(attrs={"class": "c1"}),
  11. }

 

  class Meta下常用参数:

  1. model = models.Student # 对应的Model中的类
  2. fields = "__all__" # 字段,如果是__all__,就是表示列出所有的字段
  3. exclude = None # 排除的字段
  4. labels = None # 提示信息
  5. help_texts = None # 帮助提示信息
  6. widgets = None # 自定义插件
  7. error_messages = None # 自定义错误信息

 

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号