快速入门
from django.forms import Form, fieldsclass LoginForm(Form):# 不能为空 长度6~18# error_messages 定义错误信息# username 和表单中字段名匹配username = fields.CharField(max_length=18, min_length=6, required=True, error_messages={'required': '用户名不能为空','min_length': '用户名不能少于6个字符',})password = fields.CharField(min_length=16, required=True)def login(request):obj = LobinForm(request.POST)if obj.is_valid(): # 判断是否校验成功obj.cleaned_data # dict 效验成功后的数据else:obj.errors # 对象 所有的错误信息obj.errors['username'] # 获取针对username的所有错误信息obj.errors['username'][0] # 获取针对username的第一条错误信息obj.non_field_errors # 获取clean() 函数抛出的错误信息
字段和参数
字段
CharField # 字符串验证IntegerField # 数字EmailField # emailURLField # URLSlugField #GenericIPAddressField # IP地址DateField # 日期DateTimeField # 时间RegexField # 自定制表达式
参数
'''Field'''required # 不能为空 默认 =Trueerror_messages # 错误信息定义# 所有格式错误的key为 invalid# 如:IntegerField必须为数字show_hidden_initial# 是否在当前插件后面再加一个隐藏的且具有默认值的插件(可用于检验两次输入是否一致)= Falsevalidators # 自定义验证规则lacalize # 是否支持本地化(时间) =False# 以下自动生成HTML标签widget # html插件 指定html标签是哪种label # 用于生产Label标签或显示内容initial # 初始值help_text # 帮助信息(在标签旁边显示)disabled # 是否可以编辑() =Falselabel_suffix # Label内容后缀'''CharField'''max_length # 最大长度min_length # 最小长度strip # 是否移除用户输入空白 = True'''IntegerField'''max_value # 最大值min_value # 最小值
自动生成HTML
保留上次输入的内容
from django.forms import Form, fields, widgetsclass TestForm(Form):username = fields.CharField(min_length=6, max_length=16,label='用户名',help_text='请输入6~16位的用户名', label_suffix=':'# 不设置widget默认为input text框)password = fields.CharField(min_length=6, max_length=16, widget=widgets.PasswordInput, # 指定为input密码框label='密码', help_text='请输入6~16位的密码', label_suffix=':')def register(request):if request.method == 'GET':# 将obj传入模板中可以生成没有值的inputobj = TestForm()return render(request, 'register.html', {'obj': obj})else:# 将obj传入模板中可以生成带值的inputobj = TestForm(request.POST)if obj.is_valid():return HttpResponse('ok')else:return render(request, 'register.html', {'obj': obj})
<form action="/register" method="post">{{ obj.username }} {# 只是生成单个input框 #}{{ obj.password }}<button >注册</button></form>显示如下图
<form action="/register" method="post">{# 会生成所有input框,并生成label和帮助信息 #}{{ obj.as_p }}{# 其他 生成ul 和 table #}<ul>{{ obj.as_ul }}</ul><table>{{ obj.as_table }}</table><button >注册</button></form>显示如下图
widgets
# 自定义样式 attrs属性# 每个widget插件都有attrs属性widget=widgets.TextInput(attrs={'class': 'form-control','placeholder': '请输入...'})widgets.PasswordInput# select 单选s_id = fields.IntegerField(initial=1, # 设置默认选项widget=widgets.Select(choices=[(1, '上海'), (2, '杭州')]))s_id = fields.ChoiceField(choices=[(1, '上海'), (2, '杭州')],widget=widgets.Select())# 多选xx = fields.MultipleChoiceField(choices=[(1, '上海'), (2, '杭州')],widget=widgets.SelectMultiple())# CheckBoxt = fields.CharField(widget=widgets.CheckboxInput)t2 = fields.MultipleChoiceField(choices=[(1, '篮球'), (2, '足球')],widget=widgets.CheckboxSelectMultiple)#radiot3 = fields.ChoiceField(choices=[(1, '篮球'), (2, '足球')],widget=widgets.RadioSelect)# filet4 = fields.FileField(widget=widgets.FileInput)
radio自定义样式
{% for radio in form.is_menu %}<label for="{{ radio.id_for_label }}" class="radio-inline"><!-- radio.tag => input radio.choice_label = > 文字 -->{{ radio.tag }}{{ radio.choice_label }}</label>{% endfor %}
select、radio等设置默认选择
# 1. 在定义form时设置固定的初始值#定义字段时添加initial属性# 2. 动态设置初始值form = XxxForm(initial={'key': 'value'})
Form数据无法动态显示的BUG
方法一(推荐)
class TestForm(Form):xx = fields.MultipleChoiceField(# choices=models.Classes.objects.values_list('id', 'title'),widget=widgets.SelectMultiple())def __init__(self, *args, **kwargs):super(TestForm, self).__init__(*args, **kwargs)self.fields['xx'].widget.choices = models.Classes.objects.values_list('id', 'title')
方法二
获取数据时只能是all()获取,value为id,内容为数据对象,所以需要在models中添加str方法
from django.forms import models as form_modelclass TestForm(Form):xx = form_model.ModelMultipleChoiceField(# 只能是 .all()queryset=models.Classes.objects.all(),widget=widgets.SelectMultiple())class Classes(Model):title = models.CharField()def __str__(self):return self.title
自定义正则
from django.core.validators import RegexValidatora = fields.CharField(validators = [RegexValidator('\d+', '只能是数字')])
钩子方法 clean和clean_字段
from django.core.exceptions import ValidationErrorclass TestForm(Form):user = fields.CharField()def clean_user(self):"""user 正则表达式验证通过后会执行该方法验证不通过则不执行该方法"""# 得到user值v = self.cleaned_data['user']# 如果此处验证不通过可以抛出异常raise ValidationError('错误信息', code='invalid') # code默认为invalid,可以定义为其他require、max_length...# 必须有返回值,否则cleaned_data['user']值为Nonereturn vdef clean(self):"""适合做整体验证必须正则和clean_xx方法都验证通过,才执行该方法有返回值则cleaned_data的值为返回值没有返回值则cleaned_data数据不变"""# 在clean中抛出的错误都放在__all__中# 后台获取错误信息form.errors['__all__'] 或 form.errors[NON_FIELD_ERRORS]# 在前端中获取错误信息使用{{ form.non_field_errors }}raise ValidationError('错误信息')# 给某个字段加错误信息self.add_error('字段名', ValidationError('错误信息'))
文件上传
ajax文件上传查看Django学习(Ajax).md
class TestForm(Form):title = fields.CharField()f = fields.FileField()class test(request):if request.method == 'GET':# ...else:obj = TestForm(data=request.POST, files=request.FILES)if obj.is_valid():# f是一个文件对象f = obj.cleaned.data.get('f')fielanem = f.name # 文件名f.size # 文件大小# 保存文件with open(filename, 'wb') as fs:# 循环获取数据写入文件for chunk in f.chunks():fs.write(chunk)
from组件中使用request
# 重写from 中的 __init__方法def __init__(self, request, *args, **kwargs):super(xxxForm, self).__init__(*args, **kwargs)self.request = request
ModelForm
from django.forms import ModelFormfrom django.forms import widgets as dj_widgetsfrom django.forms import fields as dj_fieldsclass UserModelForm(ModelForm):# 如果想增加字段 在此处写字段status = dj_fields.CharField()class Meta:model = models.User # 指定modelfields = "__all__" # or ['id', 'username'] # 指定字段, __all__表示所有字段exclude = None # 排除的字段labels = None # 提示信息help_text = None # 帮助信息widgets = { # 自定义插件'name': dj_widgets.Textarea(attrs={'class': 'c1'}) # 自定义属性}error_mesages = { # 错误提示信息'name': {'required': '用户名不能为空'},}
