Django----表单

HTML表单

单纯从前端的html来说,表单是用来提交数据给服务器的,不管后台的服务器用的是Django还是PHP语言还是其他语言。只要input标签放在form标签中,然后再添加一个提交按钮,那么以后点击提交按钮,就可以将input标签对于的值提交给服务器了。

Django中的表单

Django中的表单丰富了传统的HTML语言中的表单。在Django中的表单,主要做以下两件事:

  1. 渲染表单模板
  2. 表单验证数据是否合法

Django中的表单使用流程

在讲解Django表单的具体每部分的细节之前。我们首先先来看下整体的使用流程。首先我们在后台服务器定义一个表单类,继承于from django import froms

表单渲染格式

前面我们通过{{ from }}模板语言,简单地将表单渲染到HTML页面中了,实际上,有更多的方式

  • {{ form.as_tabel}} : 将表单渲染一个表格元素,每个输入框作为一个<tr>标签
  • {{ form.as_p }} : 将表单的每个输入框包裹在一个<p>标签内tags
  • {{ form.as_ul }} : 将表单渲染成一个列表元素,每个输入框作为一个<li>标签

froms

# @Time : 2020/7/15 13:01 
# @Author : Small-J 

# 继承Django的表单验证
from django import forms


class MessageBoardForm(forms.Form):
    # 最大长度限制和最小长度限制
    title = forms.CharField(max_length=100, min_length=2, label='标题')

    content = forms.CharField(widget=forms.Textarea)
    # 渲染表单的中文显示
    email = forms.EmailField(label='邮箱')
    # required
    reply = forms.BooleanField(required=False)

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h2>Form表单提交</h2>
{# 对应的form标签 #}
<form action="" method="post">
    <table>
        {{ form.as_table }}

    </table>
    <input type="submit" value="提交">
</form>
</body>
</html>

在这里插入图片描述

常用的Field

使用Field可以是对数据验证的第一步。你期待这个提交上来的数据是什么类型,那么就使用什么类型的Field

CharField

用来接收文本。

参数:

  • max_length : 这个字段值的最大长度。
  • min_length : 这个字段值的最小长度。
  • required : 这个字段是否必须的。默认是必须的。
  • error_messages : 在某个条件验证失败的时候,给出错误信息。

EmailField

  • 用来接收邮箱,会自动验证邮箱是否合法
  • 错误信息的key : requiredinvalid

IntegerField

用来接收整形,并且验证通过后,会将这个字段的值转换为整形

  • max_value: 最大的值
  • min_value : 最小的值
  • 错误信息的key:required 、invalid、max_value、min_value

IntegerField

用来接收整形,并且验证通过后,会将这个字段的值转换为整形

  • max_value : 最大的值
  • min_value : 最小的值
  • 错误信息的key : requiredinvalidmax_valuemin_value

URLField

  • 用来接收url格式的字符串
  • 错误信息的key : requiredinvalid

forms.py

# @Time : 2020/7/19 14:21 
# @Author : Small-J

from django import forms


class MyForm(forms.Form):
    # 当我们输入一个错误的邮箱的时候,显示错误的信息
    # {'email': [{'message': 'Enter a valid email address.', 'code': 'invalid'}]}
    # 当显示错误的信息的时候会提示'Enter a vaild email address'
    # 当我们想自定义错误信息的时候,可以在对应字段中写上参数error_messages
    email = forms.EmailField(error_messages={'invalid': '请输入正确的邮箱地址'})
    price = forms.FloatField(error_messages={'invalid': '请输入正确的浮点型数据'})
    URL = forms.URLField(error_messages={'invalid': '请输入正确的邮箱地址', 'required': '请输入填写网站'})

views.py

from django.shortcuts import render
# 导入类视图
from django.views.generic import View
from .forms import MyForm
from django.http import HttpResponse


class IndexView(View):
    def get(self, request):
        return render(request, 'index.html')

    def post(self, request):
        form = MyForm(request.POST)
        # 表示如果验证通过的话
        if form.is_valid():
            return HttpResponse('success')
        else:
            print(form.errors.get_json_data())
            return HttpResponse('fail')

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="" method="post">
    邮箱:<input type="text" name="email"><br>
    价格:<input type="text" name="price"><br>
    URL:<input type="text" name="URL"><br>
    <input type="submit" name="提交" >
</form>
</body>
</html>

在这里插入图片描述

常用的验证器

在验证某个字段的时候,可以传递一个validators参数用来指定验证器,进一步对数据进行过滤。验证器有很多,但是很多验证器我们其实已经通过这个Field或者一些参数就可以指定了。比如EmailValidator,我们可以通过EmailFidle来指定,比如MaxValueValidator,我们可以通过max_value参数来指定。

  • MaxValueValidator : 验证最大值
  • MinValueValidator : 验证最小值
  • MinLengthVaidator :验证最小长度
  • ManLengthVaidator : 验证最大长度
  • EmailValidator : 验证是否是邮箱格式
  • URLVaidator : 验证是否为URL格式
  • RegexValidator : 如果还需要更加复杂的验证,那么我们可以通过正则表达式验证
# 验证手机号码是否合法
# RegexValidator:代表着为正则表达式说法
# message :自定义错误信息显示
phone_number = forms.CharField(validators=[validators.RegexValidator(r'1[345678]\d{9}', message='请输入正确的手机号码')])

自定义的验证器

有时候对一个字段验证,不是一个长度,一个正则表达式能够写清楚的,还需要一些其他复杂的逻辑,那么我们可以对某个字段,进行自定义的验证。比如在注册的表单验证中,我们想要验证手机号码是否已经被注册过,那么这是就需要在数据库中进行判断才知道。对某个字段进行自定义的验证方式是,定义一个方法,这个方法的名字定义规则是:clean_fieldname。如果验证失败,那么就抛出一个验证错误。比如要验证用户表中手机号码之前是否在数据库中存在,那么可以通过以下代码实现

models.py

from django.db import models


# 模型
class MyForm(models.Model):
    username = models.CharField(max_length=15)
    telephone = models.CharField(max_length=11)
    pwd1 = models.CharField(max_length=10, null=True)
    pwd2 = models.CharField(max_length=10, null=True)

views.py

from django.shortcuts import render
# 导入类视图
from django.views.generic import View
from .forms import MyForm, RegisterForm
from django.http import HttpResponse
from .models import MyForm


class IndexView(View):
    def get(self, request):
        return render(request, 'index.html')

    def post(self, request):
        form = MyForm(request.POST)
        # 表示如果验证通过的话
        if form.is_valid():
            return HttpResponse('success')
        else:
            print(form.errors.get_json_data())
            return HttpResponse('fail')


class RegisterView(View):
    def get(self, request):
        return render(request, 'regist.html')

    def post(self, request):
        form = RegisterForm(request.POST)
        # 验证表单数据是否存在
        if form.is_valid():
            # cleaned_data中的值类型与字段定义的Field类型一致
            username = form.cleaned_data.get('username')
            telephone = form.cleaned_data.get('telephone')
            MyForm.objects.create(username=username, telephone=telephone)
            return HttpResponse('success')
        else:
            print(form.errors.get_json_data())
            return HttpResponse('fail')

regist.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="" method="post">
    <table>
        <tr>
            <td>用户名:</td>
            <td><input type="text" name="username"></td>
        </tr>
        <tr>
            <td>手机号码:</td>
            <td><input type="text" name="telephone"></td>
        </tr>
        <tr>
            <td>密码:</td>
            <td><input type="password" name="pwd1"></td>
        </tr>
        <tr>
            <td>再次输入密码:</td>
            <td><input type="password" name="pwd2"></td>
        </tr>
        <tr>
            <td></td>
            <td><input type="submit" value="提交"></td>
        </tr>
    </table>
</form>
</body>
</html>

当针对某个字段的情况下

class RegisterForm(forms.Form):
    username = forms.CharField(max_length=100)
    # RegexValidator:正则表达式
    telephone = forms.CharField(validators=[validators.RegexValidator(r'1[345678]\d{9}', message='请输入正确的手机号码')])

    # clean+对应的字段名字  -针对某字段进行
    # 该自定义的字段要返回数据
    #
    def clean_telephone(self):
        telephone = self.cleaned_data.get('telephone')
        # 进行数据库判断过滤
        exists = MyForm.objects.filter(telephone=telephone).exists()
        if exists:
            # 判断数据是否存在,如果存在将主动抛出个异常
            # ValidationError:验证失败的一个异常
            raise forms.ValidationError(message='手机号码已存在')
        return telephone

当针对多个字段的情况下

class RegisterForm(forms.Form):
    username = forms.CharField(max_length=100)
    # RegexValidator:正则表达式
    telephone = forms.CharField(validators=[validators.RegexValidator(r'1[345678]\d{9}', message='请输入正确的手机号码')])
    pwd1 = forms.CharField(max_length=16, min_length=6)
    pwd2 = forms.CharField(max_length=16, min_length=6)

    # clean+对应的字段名字  -针对某字段进行
    # 该自定义的字段要返回数据


    # 当针对多个字段的时候
    def clean(self):
        cleaned_data = super().clean()
        pwd1 = cleaned_data.get('pwd1')
        pwd2 = cleaned_data.get('pwd2')
        if pwd1 != pwd2:
            raise forms.ValidationError(message='两次输入的密码不一样')
        return cleaned_data

提取错误信息

如果验证失败了,那么有一些错误信息是我们需要传给前端的。这时候我们可以通过以下属性来获取:

  • form.errors : 这个属性获取的错误信息是一个包含了html标签的信息

  • form.errors.get_json_data() : 这个方法获取的是一个字典类型的错误信息。将某个字段的名字作为key,错误信息作为值的一个字典。

  • form.as_json() : 这个方法是将form.get_json_data()返回的字典dump成json格式的字符串,方便进行传输。

  • 上述方法获取的字段的错误值,都是一个比较复杂的数据。比如以下:

    {'username': [{'message': 'Enter a valid URL.', 'code': 'invalid'}, {'message': 'Ensure this value has at most 4 characters (it has 22).', 'code': 'max_length'}]}

class MyForm(forms.Form):
    username = forms.URLField(max_length=4)

    def get_errors(self):
        errors = self.errors.get_json_data()
        new_errors = {}
        for key,message_dicts in errors.items():
            messages = []
            for message in message_dicts:
                messages.append(message['message'])
            new_errors[key] = messages
        return new_errors

猜你喜欢

转载自blog.csdn.net/qq_37662827/article/details/107452616