django-form验证

文件上传

上传文件前端

<h2>文件上传</h2>
<form action="/f1/" method="post" enctype="multipart/form-data">
	{% csrf_token %}
	<input type="file" name="fafafa">
	<input type="submit" value="上传">
</form>

上传文件后端

import os
def f1(request):
    if request.method=="GET":
        return render(request, "f1.html")
    else:
        file_obj = request.FILES.get("fafafa")
        print(file_obj.name)
        print(file_obj.size)
        f = open(os.path.join("static", file_obj.name), "wb")
        for chunk in file_obj.chunks():
            f.write(chunk)
        f.close()
        return render(request, "f1.html")
# 访问127.0.0.1:8000/static/filename 可预览该文件

上传文件前端

	<h2>文件上传f2</h2>
	<form action="/f2/" method="post" enctype="multipart/form-data">
		{% csrf_token %}
		<p>{{ obj.user }}</p>
		<p>{{ obj.fafafa }}</p>
		<input type="submit" value="上传">		
	</form>

上传文件后端

class F2Form(Form):
    user = fields.CharField()
    fafafa = fields.FileField()


def f2(request):
    if request.method=="GET":
        obj = F2Form()
        return render(request, "f2.html",{"obj":obj})
    else:
        obj = F2Form(data=request.POST, files=request.FILES)
        if obj.is_valid():
            print(obj.cleaned_data.get("fafafa").name) # insomnia.png
            print(obj.cleaned_data.get("fafafa").size) # 321676
        return render(request, "f2.html",{"obj":obj})

form表单验证

django自带的form验证组件
定义规则

# 定制错误信息
error_dic = {
    "required":"用户名不能为空",
    "min_length":"用户名太短",
    "max_length":"用户名太长",
}
pwd_error = {
    "required": "密码不能为空",
    "min_length": "密码至少大于6位",
}

class LoginForm(Form):
    
    # 字段名必须和html标签的name属性一致
    username = fields.CharField(
        required=True,   # 输入不能为空
        max_length=16,   # 输入最长为16
        min_length=6,    # 输入最短为6
        error_messages=error_dic  # 定制错误信息
    )
    password = fields.CharField(
        required=True,
        min_length=6,
        error_messages=pwd_error,
    )

登陆验证实例

def login(request):
    if request.method == "GET":
        return render(request, "login.html", )
    else:
        obj = LoginForm(request.POST)
        re = obj.is_valid() # 是否校验成功
        if re:  # 校验成功
            print(obj.cleaned_data)  # {'username': 'alex3712', 'password': 'qwerasd'}
            return HttpResponse("login successful")
        else:
            return render(request, "login.html", {"obj": obj})
            # 前端错误信息{{ obj.errors.username.0 }}

验证并生成html标签

1.创建form类

from django.forms import Form
from django.forms import widgets
from django.forms import fields
 
class MyForm(Form):
    user = fields.CharField(
        widget=widgets.TextInput(attrs={'id': 'i1', 'class': 'c1'})
    )
 
    gender = fields.ChoiceField(
        choices=((1, '男'), (2, '女'),),
        initial=2,
        widget=widgets.RadioSelect
    )
 
    city = fields.CharField(
        initial=2,
        widget=widgets.Select(choices=((1,'上海'),(2,'北京'),))
    )
 
    pwd = fields.CharField(
        widget=widgets.PasswordInput(attrs={'class': 'c1'}, render_value=True)
    )

2.View函数处理

from django.shortcuts import render, redirect
from .forms import MyForm
 
 
def index(request):
    if request.method == "GET":
        obj = MyForm()
        return render(request, 'index.html', {'form': obj})
    elif request.method == "POST":
        obj = MyForm(request.POST, request.FILES)
        if obj.is_valid():
            values = obj.clean()
            print(values)
        else:
            errors = obj.errors
            print(errors)
        return render(request, 'index.html', {'form': obj})
    else:
        return redirect('http://www.google.com')

3.生成HTML标签

<form action="/" method="POST" enctype="multipart/form-data">
    <p>{{ form.user }} {{ form.user.errors }}</p>
    <p>{{ form.gender }} {{ form.gender.errors }}</p>
    <p>{{ form.city }} {{ form.city.errors }}</p>
    <p>{{ form.pwd }} {{ form.pwd.errors }}</p>
    <input type="submit"/>
</form>

form生成select标签

	单选
	cls_id = fields.IntegerField(
		# widget=widgets.Select(choices=[(1,'上海'),(2,'北京')])
		widget=widgets.Select(choices=models.Classes.objects.values_list('id','title'),attrs={'class': 'form-control'})
	)

	cls_id = fields.ChoiceField(
		choices=models.Classes.objects.values_list('id','title'),
		widget=widgets.Select(attrs={'class': 'form-control'})
	)


	obj = FooForm({'cls_id':1})
	多选
	xx = fields.MultipleChoiceField(
		choices=models.Classes.objects.values_list('id','title'),
		widget=widgets.SelectMultiple
	)

select标签实时取值

生成select标签时,chocies选项可以写死,也可以从数据库中实时获取,我们定义xxForm类时,xx-choices是类的静态方法,整个程序运行阶段都不会被更改,所以我们需要自定义构造方法动态传入choices

class TeacherForm(Form):
    tname = fields.CharField(min_length=2)
    xx = fields.MultipleChoiceField(
        # choices=models.Classes.objects.values_list("id", "caption"),
        widget=widgets.SelectMultiple
    )
    # 解决方法一
    # from django.forms import models as form_model
    # xx = form_model.ModelMultipleChoiceField(queryset=models.Classes.objects.all())
    # xx = form_model.ModelChoiceField(queryset=models.Classes.objects.all())

    # 解决方法二
    # xx是静态字段 ***获取的值无法实时更新***,
    # 那么需要自定义构造方法动态传入choices从而达到此目的
    def __init__(self, *args, **kwargs):
        super(TeacherForm, self).__init__(*args, **kwargs)
        self.fields["xx"].choices = models.Classes.objects.values_list("id", "caption")

自定义form验证

validators参数

from django.forms import Form
from django.forms import widgets
from django.forms import fields
from django.core.validators import RegexValidator
 
class MyForm(Form):
    user = fields.CharField(
        validators=[RegexValidator(r'^[0-9]+$', '请输入数字'), RegexValidator(r'^159[0-9]+$', '数字必须以159开头')],
    )

重写clean_field

from django import forms
    from django.forms import fields
    from django.forms import widgets
    from django.core.exceptions import ValidationError
    from django.core.validators import RegexValidator
 
    class FInfo(forms.Form):
        username = fields.CharField(max_length=5,
                                    validators=[RegexValidator(r'^[0-9]+$', 'Enter a valid extension.', 'invalid')], )
        email = fields.EmailField()
 
        def clean_username(self):
            """
            Form中字段中定义的格式匹配完之后,执行此方法进行验证
            :return:
            """
            value = self.cleaned_data['username']
            if "666" in value:
                raise ValidationError('666已经被玩烂了...', 'invalid')
            return value

重写clean()方法
参见官方文档。重点就下面一句,我们需要同时验证多个字段的合法性,就需要重写clean方法,见示例,
Suppose we add another requirement to our contact form: if the cc_myself field is True, the subject must contain the word "help". We are performing validation on more than one field at a time, so the form’s clean() method is a good spot to do this. Notice that we are talking about the clean() method on the form here, whereas earlier we were writing a clean() method on a field. It’s important to keep the field and form difference clear when working out where to validate things. Fields are single data points, forms are a collection of fields.

By the time the form’s clean() method is called, all the individual field clean methods will have been run (the previous two sections), so self.cleaned_data will be populated with any data that has survived so far. So you also need to remember to allow for the fact that the fields you are wanting to validate might not have survived the initial individual field checks.

There are two ways to report any errors from this step. Probably the most common method is to display the error at the top of the form. To create such an error, you can raise a ValidationError from the clean() method. For example:

from django import forms

class ContactForm(forms.Form):
    # Everything as before.
    ...

    def clean(self):
        cleaned_data = super(ContactForm, self).clean()
        cc_myself = cleaned_data.get("cc_myself")
        subject = cleaned_data.get("subject")

        if cc_myself and subject:
            # Only do something if both fields are valid so far.
            if "help" not in subject:
                raise forms.ValidationError(
                    "Did not send for 'help' in the subject despite "
                    "CC'ing yourself."
                )

validators方法

import re
from django.forms import Form
from django.forms import widgets
from django.forms import fields
from django.core.exceptions import ValidationError
 
 
# 自定义验证规则
def mobile_validate(value):
    mobile_re = re.compile(r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$')
    if not mobile_re.match(value):
        raise ValidationError('手机号码格式错误')
 
 
class PublishForm(Form):
 
 
    title = fields.CharField(max_length=20,
                            min_length=5,
                            error_messages={'required': '标题不能为空',
                                            'min_length': '标题最少为5个字符',
                                            'max_length': '标题最多为20个字符'},
                            widget=widgets.TextInput(attrs={'class': "form-control",
                                                          'placeholder': '标题5-20个字符'}))
 
 
    # 使用自定义验证规则
    phone = fields.CharField(validators=[mobile_validate, ],
                            error_messages={'required': '手机不能为空'},
                            widget=widgets.TextInput(attrs={'class': "form-control",
                                                          'placeholder': u'手机号码'}))
 
    email = fields.EmailField(required=False,
                            error_messages={'required': u'邮箱不能为空','invalid': u'邮箱格式错误'},
                            widget=widgets.TextInput(attrs={'class': "form-control", 'placeholder': u'邮箱'}))
posted @ 2017-07-05 19:26  pirate邹霉  阅读(611)  评论(0编辑  收藏  举报