Django基础笔记3(form组件)
阅读原文时间:2023年07月09日阅读:1

From组件

from django.forms import Form, fields

class loginForm(Form):  # 设置规则
    username = fields.CharField(max_length=16, required=True, error_messages={
        'required': '要填用户名',
        'max_length': '太长了'
    })
    passwd = fields.CharField(max_length=10, min_length=6, required=True)

使用form组件

def test(request):
    if request.method == 'GET':
        return render(request, 'App7/login.html')
    else:
        obj = loginForm(request.POST)
        ret = obj.is_valid()  # 自动校验,返回bool
        if ret:
            print(obj.cleaned_data) #返回字典类型
        return HttpResponse('123')


form组件返回错误信息

def test(request):
    if request.method == 'GET':
        return render(request, 'App7/login.html')
    else:
        obj = loginForm(request.POST)
        #obj=loginForm({'name':'xxx'})            #与上面一样
        ret = obj.is_valid()  # 自动校验,返回bool
        if ret:
            print(obj.cleaned_data) #返回字典类型
        else:
            print(obj.errors)
            print(obj.errors['username'][0])#索引的方式查找相应字段的错误信息
        return HttpResponse('123')

前端显示错误信息

    name:<input type="text" name="username">{{ obj.errors.username.0 }}<br>
    password:<input type="password" name="passwd">{{ obj.errors.passwd.0 }}<br>


利用Ajax传表单

def adjax_login(request):
    ret = {'status': True, 'msg': ''}
    if request.method == 'POST':
        obj = loginForm(request.POST)
        if obj.is_valid():
            print(obj.cleaned_data)
        else:
            # print(obj.errors)  # 对象类型,不能直接传
            ret['status'] = False
            ret['msg'] = json.dumps(obj.errors, ensure_ascii=False)  # 第二个参数防止中文乱码
    v = json.dumps(ret, ensure_ascii=False)
    return HttpResponse(v)


<form id="form1" method="post" action="./login.html">
    {% csrf_token %}
    name:<input type="text" name="username">
 <br>
    password:<input type="password" name="passwd">
<br>
    <button type="submit">登录</button>

    <a onclick="subForm();">提交</a>
</form>


function subForm() {
    $('.error').remove()//先清除之前的错误信息
    $.ajax({
            url: './ajaxLogin.html',//此处也可使用别名({% url 'name' %})
            type: 'POST',
            data: $('#form1').serialize(),   //ajax自带的处理form表单数据
            dataType: 'JSON',
            success: function (arg) {
                if (arg.status) {
                            //表单格式无误
                } else {                                  //字典的key(字段名,出错的input的name)  //字典的value(错误信息)
                    $.each(JSON.parse(arg.msg), function (index, value) {
                        console.log(index)
                        var tag = document.createElement('span')
                        tag.innerHTML = value[0]
                        tag.className = 'error'
                        $('#form1').find('input[name="' + index + '"]').after(tag)
                    })
                }
            }
        }
    )
}
效果


使用Ajax提交,页面不会刷新,用户的填写会被保留

form表单的其他字段类型限制

class testForm(Form):
    email = fields.EmailField(required=True, error_messages={
        'invalid': '格式错误,必须是邮箱格式'  # 所有的格式错误,都是invalid
    })
    num = fields.IntegerField(required=True, max_value=10, min_value=10000)  # int类型的field可以设置最大最小值
    t1 = fields.URLField()
    t2 = fields.SlugField()  # 数字字母下划线
    t3 = fields.DateField()  # 日期
    t4 = fields.RegexField()  # 可自定制正则表达式

常用的正则表达式:脚本之家在线工具


Form组件生成HTML标签

class cr(Form):  # #                     初始值            提示信息        字段标签
    f1 = fields.CharField(required=True, initial='adf', help_text='请输入用户名', label='用户名',
                          # 是否可编辑       #label标签的后缀
                          disabled=False, label_suffix='->')
def cForm(request):
    if request.method == 'GET':
         obj = cr()
      return render(request, 'App7/cForm.html', {'obj': obj})

自动添加样式

class RegModelForm(Form):
    nickname = forms.CharField(label='昵称', max_length=8)
    username = forms.CharField(label='用户名', max_length=16)
    password = forms.CharField(label='密码', min_length=8, max_length=32, widget=forms.PasswordInput(
    ))
    confirm_password = forms.CharField(label='重复密码', widget=forms.PasswordInput(
    ))

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for name, field in self.fields.items():  # item就是此类的字段,name为名字,field为对象
            field.widget.attrs['class'] = 'form-control'
            field.widget.attrs['placeholder'] = '请输入%s' % (field.label)


{{ obj.f1 }}{{ obj.f1.help_text }}<br>
{{ obj.as_p }}
利用Form组件生成标签并保留上一次写的值
class Reg(Form):
    username = fields.CharField(min_length=12,
                widget=widgets.TextInput(attrs={'class': 'c1'}))

    passwd = fields.CharField(min_length=8, max_length=16)

def reg(request):
    if request.method == 'GET':
        obj = Reg()
        return render(request, 'App7/reg.html', {'obj': obj})
    else:
        obj = Reg(request.POST)
        if obj.is_valid():
            print(obj.cleaned_data)
        else:
            print(obj.errors)
        return render(request, 'App7/reg.html', {'obj': obj})

novalidate:去除浏览器给我们做的验证

<form action="./reg.jsp" method="post" novalidate>
    {% csrf_token %}
    <p>
        {{ obj.username }}{{ obj.errors.username.0 }}
    </p>
    <p>
        {{ obj.passwd }}{{ obj.errors.passwd.0 }}
    </p>
    <p>
        <input type="submit" value="提交">
    </p>
</form>

novalidate:效果

From组件之modelForm

from django.forms import widgets, ModelForm
class Question( ModelForm):
    class Meta:
        fields = '__all__'
        model = Problem  # 设置数据库中对应的model

        #将这些字段排除在外,即生成Form的时候不会生成这些东西

        exclude = ['project', 'creator', 'last_update_time']

        widgets = {
            'type': widgets.Select(),
            'module': widgets.Select(),
            'assign': widgets.Select(attrs={'class': 'selectpicker'}),
            'priority': widgets.Select(),
            'status': widgets.Select(),
            'mode': widgets.Select(),
            'creator': widgets.Select(),
            'attention': widgets.SelectMultiple(attrs={'class': 'selectpicker'}),
            'subject': widgets.Input(),
            'end_time': widgets.Input(),
            'start_time': widgets.Input(),
            'desc': widgets.Textarea(),

        }

'''使用modelForm'''
forms = Question(data=request.POST)
if forms.is_valid():
    '''排除的字段需要逐个添加上'''
   forms.instance.project = request.project
   forms.instance.creator = request.user
   forms.save()

利用modelForm初始化表单的值

obj = models.Problem.objects.filter(id=problem_id, project_id=project_id).first()  # 当前编辑的对象
form = Question(request, instance=obj)

通过modelForm实现对manytomany字段的更新

forms = Question(request, data=request.POST)
        if forms.is_valid():
            objs = models.Problem.objects.filter(id=problem_id, project_id=project_id)
            # manytomany字段不可以直接通过update对象来更新
            objs.first().attention.set(forms.cleaned_data['attention'])
            del forms.cleaned_data['attention']
            objs.update(**forms.cleaned_data)