快速入门

  1. from django.forms import Form, fields
  2. class LoginForm(Form):
  3. # 不能为空 长度6~18
  4. # error_messages 定义错误信息
  5. # username 和表单中字段名匹配
  6. username = fields.CharField(max_length=18, min_length=6, required=True, error_messages={
  7. 'required': '用户名不能为空',
  8. 'min_length': '用户名不能少于6个字符',
  9. })
  10. password = fields.CharField(min_length=16, required=True)
  11. def login(request):
  12. obj = LobinForm(request.POST)
  13. if obj.is_valid(): # 判断是否校验成功
  14. obj.cleaned_data # dict 效验成功后的数据
  15. else:
  16. obj.errors # 对象 所有的错误信息
  17. obj.errors['username'] # 获取针对username的所有错误信息
  18. obj.errors['username'][0] # 获取针对username的第一条错误信息
  19. obj.non_field_errors # 获取clean() 函数抛出的错误信息

字段和参数

字段

  1. CharField # 字符串验证
  2. IntegerField # 数字
  3. EmailField # email
  4. URLField # URL
  5. SlugField #
  6. GenericIPAddressField # IP地址
  7. DateField # 日期
  8. DateTimeField # 时间
  9. RegexField # 自定制表达式

参数

  1. '''Field'''
  2. required # 不能为空 默认 =True
  3. error_messages # 错误信息定义
  4. # 所有格式错误的key为 invalid
  5. # 如:IntegerField必须为数字
  6. show_hidden_initial
  7. # 是否在当前插件后面再加一个隐藏的且具有默认值的插件(可用于检验两次输入是否一致)= False
  8. validators # 自定义验证规则
  9. lacalize # 是否支持本地化(时间) =False
  10. # 以下自动生成HTML标签
  11. widget # html插件 指定html标签是哪种
  12. label # 用于生产Label标签或显示内容
  13. initial # 初始值
  14. help_text # 帮助信息(在标签旁边显示)
  15. disabled # 是否可以编辑() =False
  16. label_suffix # Label内容后缀
  17. '''CharField'''
  18. max_length # 最大长度
  19. min_length # 最小长度
  20. strip # 是否移除用户输入空白 = True
  21. '''IntegerField'''
  22. max_value # 最大值
  23. min_value # 最小值

自动生成HTML

保留上次输入的内容

  1. from django.forms import Form, fields, widgets
  2. class TestForm(Form):
  3. username = fields.CharField(
  4. min_length=6, max_length=16,
  5. label='用户名',
  6. help_text='请输入6~16位的用户名', label_suffix=':'
  7. # 不设置widget默认为input text框
  8. )
  9. password = fields.CharField(
  10. min_length=6, max_length=16, widget=widgets.PasswordInput, # 指定为input密码框
  11. label='密码', help_text='请输入6~16位的密码', label_suffix=':'
  12. )
  13. def register(request):
  14. if request.method == 'GET':
  15. # 将obj传入模板中可以生成没有值的input
  16. obj = TestForm()
  17. return render(request, 'register.html', {'obj': obj})
  18. else:
  19. # 将obj传入模板中可以生成带值的input
  20. obj = TestForm(request.POST)
  21. if obj.is_valid():
  22. return HttpResponse('ok')
  23. else:
  24. return render(request, 'register.html', {'obj': obj})
  1. <form action="/register" method="post">
  2. {{ obj.username }} {# 只是生成单个input框 #}
  3. {{ obj.password }}
  4. <button >注册</button>
  5. </form>
  6. 显示如下图
  1. <form action="/register" method="post">
  2. {# 会生成所有input框,并生成label和帮助信息 #}
  3. {{ obj.as_p }}
  4. {# 其他 生成ul 和 table #}
  5. <ul>
  6. {{ obj.as_ul }}
  7. </ul>
  8. <table>
  9. {{ obj.as_table }}
  10. </table>
  11. <button >注册</button>
  12. </form>
  13. 显示如下图

widgets

  1. # 自定义样式 attrs属性
  2. # 每个widget插件都有attrs属性
  3. widget=widgets.TextInput(
  4. attrs={
  5. 'class': 'form-control',
  6. 'placeholder': '请输入...'
  7. }
  8. )
  9. widgets.PasswordInput
  10. # select 单选
  11. s_id = fields.IntegerField(
  12. initial=1, # 设置默认选项
  13. widget=widgets.Select(choices=[(1, '上海'), (2, '杭州')])
  14. )
  15. s_id = fields.ChoiceField(
  16. choices=[(1, '上海'), (2, '杭州')],
  17. widget=widgets.Select()
  18. )
  19. # 多选
  20. xx = fields.MultipleChoiceField(
  21. choices=[(1, '上海'), (2, '杭州')],
  22. widget=widgets.SelectMultiple()
  23. )
  24. # CheckBox
  25. t = fields.CharField(
  26. widget=widgets.CheckboxInput
  27. )
  28. t2 = fields.MultipleChoiceField(
  29. choices=[(1, '篮球'), (2, '足球')],
  30. widget=widgets.CheckboxSelectMultiple
  31. )
  32. #radio
  33. t3 = fields.ChoiceField(
  34. choices=[(1, '篮球'), (2, '足球')],
  35. widget=widgets.RadioSelect
  36. )
  37. # file
  38. t4 = fields.FileField(
  39. widget=widgets.FileInput
  40. )

radio自定义样式

  1. {% for radio in form.is_menu %}
  2. <label for="{{ radio.id_for_label }}" class="radio-inline">
  3. <!-- radio.tag => input radio.choice_label = > 文字 -->
  4. {{ radio.tag }}{{ radio.choice_label }}
  5. </label>
  6. {% endfor %}

select、radio等设置默认选择

  1. # 1. 在定义form时设置固定的初始值
  2. #定义字段时添加initial属性
  3. # 2. 动态设置初始值
  4. form = XxxForm(initial={'key': 'value'})

Form数据无法动态显示的BUG

方法一(推荐)

  1. class TestForm(Form):
  2. xx = fields.MultipleChoiceField(
  3. # choices=models.Classes.objects.values_list('id', 'title'),
  4. widget=widgets.SelectMultiple()
  5. )
  6. def __init__(self, *args, **kwargs):
  7. super(TestForm, self).__init__(*args, **kwargs)
  8. self.fields['xx'].widget.choices = models.Classes.objects.values_list('id', 'title')

方法二

获取数据时只能是all()获取,value为id,内容为数据对象,所以需要在models中添加str方法

  1. from django.forms import models as form_model
  2. class TestForm(Form):
  3. xx = form_model.ModelMultipleChoiceField(
  4. # 只能是 .all()
  5. queryset=models.Classes.objects.all(),
  6. widget=widgets.SelectMultiple()
  7. )
  8. class Classes(Model):
  9. title = models.CharField()
  10. def __str__(self):
  11. return self.title

自定义正则

  1. from django.core.validators import RegexValidator
  2. a = fields.CharField(
  3. validators = [RegexValidator('\d+', '只能是数字')]
  4. )

钩子方法 clean和clean_字段

  1. from django.core.exceptions import ValidationError
  2. class TestForm(Form):
  3. user = fields.CharField()
  4. def clean_user(self):
  5. """
  6. user 正则表达式验证通过后会执行该方法
  7. 验证不通过则不执行该方法
  8. """
  9. # 得到user值
  10. v = self.cleaned_data['user']
  11. # 如果此处验证不通过可以抛出异常
  12. raise ValidationError('错误信息', code='invalid') # code默认为invalid,可以定义为其他require、max_length...
  13. # 必须有返回值,否则cleaned_data['user']值为None
  14. return v
  15. def clean(self):
  16. """
  17. 适合做整体验证
  18. 必须正则和clean_xx方法都验证通过,才执行该方法
  19. 有返回值则cleaned_data的值为返回值
  20. 没有返回值则cleaned_data数据不变
  21. """
  22. # 在clean中抛出的错误都放在__all__中
  23. # 后台获取错误信息form.errors['__all__'] 或 form.errors[NON_FIELD_ERRORS]
  24. # 在前端中获取错误信息使用{{ form.non_field_errors }}
  25. raise ValidationError('错误信息')
  26. # 给某个字段加错误信息
  27. self.add_error('字段名', ValidationError('错误信息'))

文件上传

ajax文件上传查看Django学习(Ajax).md

  1. class TestForm(Form):
  2. title = fields.CharField()
  3. f = fields.FileField()
  4. class test(request):
  5. if request.method == 'GET':
  6. # ...
  7. else:
  8. obj = TestForm(data=request.POST, files=request.FILES)
  9. if obj.is_valid():
  10. # f是一个文件对象
  11. f = obj.cleaned.data.get('f')
  12. fielanem = f.name # 文件名
  13. f.size # 文件大小
  14. # 保存文件
  15. with open(filename, 'wb') as fs:
  16. # 循环获取数据写入文件
  17. for chunk in f.chunks():
  18. fs.write(chunk)

from组件中使用request

  1. # 重写from 中的 __init__方法
  2. def __init__(self, request, *args, **kwargs):
  3. super(xxxForm, self).__init__(*args, **kwargs)
  4. self.request = request

ModelForm

  1. from django.forms import ModelForm
  2. from django.forms import widgets as dj_widgets
  3. from django.forms import fields as dj_fields
  4. class UserModelForm(ModelForm):
  5. # 如果想增加字段 在此处写字段
  6. status = dj_fields.CharField()
  7. class Meta:
  8. model = models.User # 指定model
  9. fields = "__all__" # or ['id', 'username'] # 指定字段, __all__表示所有字段
  10. exclude = None # 排除的字段
  11. labels = None # 提示信息
  12. help_text = None # 帮助信息
  13. widgets = { # 自定义插件
  14. 'name': dj_widgets.Textarea(attrs={'class': 'c1'}) # 自定义属性
  15. }
  16. error_mesages = { # 错误提示信息
  17. 'name': {'required': '用户名不能为空'},
  18. }