Django学习11

Form组件

功能:
1.生成页面可用的HTML标签
2.对用户提交的数据进行校验
3.保留上次输入内容

生成标签

views.py写法

views.py:
from django import forms

class MyForm(forms.Form):
    # 普通输入框
    name = forms.CharField(
        label = 'xxx',		 					# 标识
        requires = True,	  					# 默认为True,内容不为空
        min_length = 6,	   						# 最小长度为6
        initial = '默认值',						# 默认值
        validators=[RegexValidator(r'^aaa','不以aaa开头不给通过'),],	# 自定义校验规则 RegexValidator(正则,错误信息); RegexValidator(校验函数,)
        help_text = '这里是帮助文本',					# 帮助文本
        error_messages={'min_length':'太短了,要六位!',},		        # 自定义错误信息,字典
        widget=forms.widgets.TextInput(),   				# 插件,改变生成的标签的样式
    )

    # 密文输入框
    password = forms.CharField(
        label='密码',
        min_length=8,
        max_length=12,
        widget=forms.widgets.PasswordInput(),
    )
    # 单选
    sex = forms.ChoiceField(
        label='性别',
        initial=3,
        choices=((1,'男'),(2,'女'),(3,'保密')),  # 元组
        widget=forms.widgets.RadioSelect(),
    )
    # 单选的下拉框
    city = forms.ChoiceField(
        label='城市',
        initial=3,
        choices=((1, '北京'), (2, '上海'), (3, '广州')),  # 元组
        widget=forms.widgets.Select(),
    )
    # 多选的下拉框
    rapper = forms.MultipleChoiceField(
        label='说唱歌手',
        choices=((1, '光光'), (2, '法老'), (3, '弹壳')),  # 元组
        widget=forms.widgets.SelectMultiple(),
    )
    # 多选的checkbox
    hobby = forms.MultipleChoiceField(
        label='爱好',
        choices=((1, '说唱'), (2, '街舞'), (3, '篮球')),  # 元组
        widget=forms.widgets.CheckboxSelectMultiple(),
    )
    # 单选的checkbox(我已阅读/记住我/下次自动登录...)
    tip = forms.MultipleChoiceField(
        label='我已阅读',
        choices=(('True', '已选'), ('False', '不选')),
        widget=forms.widgets.CheckboxInput(),
    )
    # date日期类型
    birthday = forms.CharField(
        label='生日',
        widget=forms.widgets.TextInput(attrs={'type':'date',}),		# attrs={} 给标签加属性
    )

html写法

<form action="" method="post" novalidate>
    {% csrf_token %}

    <div>
        <label for="">{{ form_obj.name.label }}</label>
        {{ form_obj.name }}
        {{ form_obj.name.help_text }}
        <span style="color: red;font-size: 14px">{{ form_obj.name.errors.0 }}</span>    <!-- 把索引为0的li的文本信息提取出来 -->
    </div>
    <div>
        <label for="">{{ form_obj.password.label }}</label>
        {{ form_obj.password }}
        <span style="color: red;font-size: 14px">{{ form_obj.password.errors.0 }}</span>
    </div>
    <div>
        <label for="">{{ form_obj.sex.label }}</label>
        {{ form_obj.sex }}
    </div>
    <div>
        <label for="">{{ form_obj.city.label }}</label>
        {{ form_obj.city }}
    </div>
    <div>
        <label for="">{{ form_obj.hobby.label }}</label>
        {{ form_obj.hobby }}
    </div>
    <div>
        <label for="">{{ form_obj.rapper.label }}</label>
        {{ form_obj.rapper }}
    </div>
    <div>
        <label for="">{{ form_obj.tip.label }}</label>
        {{ form_obj.tip }}
    </div>
    <div>
        <label for="">{{ form_obj.birthday.label }}</label>
        {{ form_obj.birthday }}
    </div>

    <input type="submit">
</form>

校验内容

def register(request):
    form_obj = RegisterForm()
    if request.method == 'GET':
        return render(request,'register.html',{'form_obj':form_obj})  # html文件渲染form_obj来生成标签(见上面)
    else:
        form_obj = RegisterForm(request.POST)   # 放入用户输入的数据并创建对象
        if form_obj.is_valid():     		# 校验 返回 true/false
            print(form_obj.cleaned_data)    # 打印符合规则的内容
            return HttpResponse('注册成功')
        else:
            print(form_obj.errors)      # 打印不符合规则的内容(字段和错误信息)
            return render(request,'register.html',{'form_obj':form_obj})

局部钩子和全局钩子

字段中的校验规则满足不了需求,就可以考虑使用钩子,在定义的form类中写如下方法
# 局部钩子(clean_字段名):
	def clean_name(self):
		value = self.cleaned_data['name']
		if 'xx' in value:
			raise ValidationError('含有敏感词汇:xx')
		else:
			return value

# 全局钩子(clean):
	def clean(self):
        value = self.cleaned_data
        
        p1 = value['password']
        p2 = value['r_password']
        if p1 == p2:
            return value
        else:
            self.add_error('r_password','两次输入的密码不一致!')	# 给某个字段单独添加错误信息
            raise ValidationError('两次输入的密码不一致!')

校验执行顺序

for循环逐个校验字段(name,password...),其中每个字段先校验字段内的规则,再校验局部钩子.等全部字段都校验完毕后,才校验全局钩子.

ModelForm组件

通过model的属性自动翻译成form的属性, 来进行form组件的工作

创建类

from django import forms
from django.core.exceptions import ValidationError

class BookModelForm(forms.ModelForm):
    # title = forms.CharField(max_length=15,min_length=6)	对自动生成的属性不满意的也可以用form的方式生成覆盖
    class Meta:
        model = models.Book
        field = '__all__'
        # field = ['title','price']		可以指定属性生成,不一定要全部生成
        # exclude = ['title']		也可以排除,让指定属性不生成
        
        labels = {				# 定制label
            'title':'书名',
            'price':'价格',
        }
        
        widgets = {				# 定制样式
            'publishDate':forms.widgets.TextInput(attr={'type':'date'}).
        }
        
        error_messages = {		# 定制错误信息
            'title':{'required':'不能为空!'},
        }
    # 局部钩子
	def clean_title(self):
        value = self.cleaned_data.get('title')
        if 'xx' in value:
            raise ValidationError('含有敏感词汇:xx')
        else:
            return value
    # 全局钩子
    def clean(self):
        pass
    
    def __init__(self,*args,**kwargs):		# 给每个属性添加统一的bootstrap样式
        super().__init__(*args,**kwargs)
        for field in self.fields.values():
            field.widget.attrs.update({'class':'form-control'})

使用

1.modelform对象生成标签:
	先实例化 -- 将实例化对象传入html -- html页面循环该对象来生成标签

2.modelform对象保存数据
	传入request.POST实例化 -- is_valid校验 -- 校验通过,对象.save()直接保存

3.modelform对象编辑数据
	呈现原有数据:
	把原来的数据先找到 -- .first()转为model对象 -- 实例化(instance=model对象) -- 再将实例化对象传给html页面 -- html页面循环该对象来生成标签
	修改原有数据:
	实例化(request.POST,instance=model对象)  -- is_valid校验 -- 校验通过,对象.save()直接修改

posted @ 2020-08-11 07:45  straightup  阅读(250)  评论(0)    收藏  举报