Python全栈之路-Django(十四)

1 Form表单验证内部原理

def login(request):
if request.method == 'GET':
    return render(request,'login.html')
else:
    obj = LoginForm(request.POST)
    # is_valid
    """
    1. LoginForm实例化时,
        self.fields={
            'user': 正则表达式
            'pwd': 正则表达式
        }
    2. 循环self.fields
            flag = True
            errors
            cleaned_data
            for k,v in self.fields.items():
            # 1. user,正则表达式
            input_value = request.POST.get(k)
            正则表达式和input_value
            flag = False
            return flag
    """
    if obj.is_valid():
        print(obj.cleaned_data)
    else:
        print(obj.errors)
    return render(request,'login.html')

2 Form组件 Ajax提交

urls.py

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login/', views.login),
    url(r'^ajax_login/', views.ajax_login),
    url(r'^test/', views.test),
]

views.py

def ajax_login(request):
    ret = {'status': True, 'msg': None}
    obj = LoginForm(request.POST)
    if obj.is_valid():
        print(obj.cleaned_data)
        return HttpResponse(json.dumps(ret))
    else:
        print(obj.errors)
        ret['status'] = False
        ret['msg'] = obj.errors
        return HttpResponse(json.dumps(ret))

templates.login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>用户登录</h1>
    <form id="f1" action="/login/" method="post">
        {% csrf_token %}
        <p><input type="text" name="user">{{ obj.errors.user.0 }}</p>
        <p><input type="password" name="pwd">{{ obj.errors.pwd.0 }}</p>
        <p><input type="submit" value="提交"></p>
        <p><input type="button" value="Ajax提交" onclick="ajaxSubmit();"></p>
    </form>
    <script src="/static/jquery-3.2.1.min.js"></script>
    <script>
        function ajaxSubmit() {
            $('.c1').remove();
            $.ajax({
            url: '/ajax_login/',
            type: 'POST',
            data: $('#f1').serialize(),
            dataType: "JSON",
            success:function (arg) {
                console.log(arg);
                if (arg.status){

                }else{
                    console.log(arg.msg);
                    $.each(arg.msg, function (index,value) {
                        var tag = document.createElement('span');
                        tag.innerText = value[0];
                        tag.className = 'c1';
                        $('#f1').find('input[name="'+index+'"]').after(tag);
                    })

                }
            }
        })
        }

    </script>
</body>
</html>

3 Form组件常用字段和参数

3.1 Form组件常用字段

class TestForm(Form):
    t1 = fields.CharField(
        required=True,
        max_length=8,
        min_length=2,
        error_messages={
            'required': 't1不能为空',
            'max_length': 't1太长',
            'min_length': 't1太短',
        }
    )
    t2 = fields.IntegerField(
        max_value=10,
        min_value=1000,
        error_messages={
            'min_value': '必须大于10',
            'max_value': '必须小于1000',
            'required': 't2不能为空',
            'invalid': 't2必须是数字'
        }
    )
    t3 = fields.EmailField(
        error_messages={
            'required': 't3不能为空',
            'invalid': 't3必须是邮箱'
        }
    )
    t4 = fields.URLField()
    t5 = fields.SlugField()  # 字符串只能包含数字、字母、下划线等字符
    t6 = fields.GenericIPAddressField()
    t7 = fields.DateField()
    t8 = fields.DateTimeField()
    t9 = fields.RegexField(
        '139d+',
        error_messages={
            'invalid': '输入一个有效的值'
        }
    )  # 自定义正则表达式 包含:1 是否为空 2 最长 3 最短 4 自定义规则

3.1 Form组件常用参数

class TestForm(Form):
    t1 = fields.CharField(
        required=True,

        # 用于生成HTML标签并保留用户上次输入的数据  只推荐使用widget
        widget=widgets.Textarea,                      # 自动生成HTML标签
        label='用户名',                # 前端可以通过obj.t1.label访问
        initial='root',            # 在input框中显示默认值
        help_text='请输入用户名...',       # 提供帮助信息
        label_suffix=':',   # Label内容后缀
        # validators=[],                    # 自定义正则表达式
        disabled=True,                    # 是否可编辑

        max_length=8,
        min_length=2,
        error_messages={
            'required': 't1不能为空',
            'max_length': 't1太长',
            'min_length': 't1太短',
        }
    )

4 Form组件保留上次输入数据示例

app01.views.py

class RegisterForm(Form):
    user = fields.CharField(min_length=8)
    email = fields.EmailField()
    password = fields.CharField(min_length=8, max_length=16)
    phone = fields.RegexField('139d+')

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

templates.register.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/register/" method="post" novalidate>
    {% csrf_token %}
    <p>{{ obj.user }}{{ obj.errors.user.0 }}</p>
    <p>{{ obj.email }}{{ obj.errors.email.0 }}</p>
    <p>{{ obj.password }}{{ obj.errors.password.0 }}</p>
    <p>{{ obj.phone }}{{ obj.errors.phone.0 }}</p>
    <input type="submit" value="提交">
</form>
</body>
</html>

5 利用Form组件实现班级管理和学生管理

urls.py

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^classes/', views.classes),

    url(r'^add_class/', views.add_class),
    url(r'^edit_class/(d+)/', views.edit_class),
    url(r'^students/', views.students),
    url(r'^add_student/', views.add_student),
    url(r'^edit_student/(d+)/', views.edit_student),
]

app01.models.py

from django.db import models

# Create your models here.


class Classes(models.Model):
    title = models.CharField(max_length=32)


class Student(models.Model):
    name = models.CharField(max_length=32)
    email = models.CharField(max_length=32)
    age = models.IntegerField()
    cls_id = models.ForeignKey('Classes')


class Teacher(models.Model):
    tname = models.CharField(max_length=32)
    c2t = models.ManyToManyField('Classes')

app01.views.py

from django.shortcuts import render, redirect
from app01 import models
# Create your views here.
from django.forms import Form, fields
from django.forms import widgets


class ClassForm(Form):
    title = fields.RegexField(
        '全栈d+期',
        error_messages={
            'required': '不能为空',
            'invalid': '格式错误'
        }
    )

def classes(request):
    if request.method == 'GET':
        class_list = models.Classes.objects.all()
        return render(request, 'classes.html', {'class_list': class_list, })


def add_class(request):
    if request.method == 'GET':
        obj = ClassForm()
        return render(request, 'add_class.html', {'obj': obj})
    else:
        obj = ClassForm(request.POST)
        if obj.is_valid():
            models.Classes.objects.create(**obj.cleaned_data)
            return redirect('/classes/')
        else:
            print(obj.errors)
            return render(request, 'add_class.html', {'obj': obj})


def edit_class(request, nid):
    if request.method == 'GET':
        row = models.Classes.objects.filter(id=nid).first()
        # 下面是两种让页面显示初始值的方法
        # obj = ClassForm(data={'title': row.title})  # 会对默认值进行校验
        obj = ClassForm(initial={'title': row.title})  # 不会对默认值进行校验

        return render(request, 'edit_class.html', {'nid': nid, 'obj': obj})
    else:
        obj = ClassForm(request.POST)
        if obj.is_valid():
            print(obj.cleaned_data)
            models.Classes.objects.filter(id=nid).update(**obj.cleaned_data)
            return redirect('/classes/')
        print(obj.errors)
        return render(request, 'edit_class.html', {'nid':nid, 'obj': obj})


class StudentForm(Form):
    name = fields.CharField(
        max_length=10,
        min_length=2,
        widget=widgets.TextInput(attrs={'class': 'form-control'})
    )
    email = fields.EmailField(
        widget=widgets.TextInput(attrs={'class': 'form-control'}),
    )
    age = fields.IntegerField(
        min_value=20,
        max_value=30,
        widget=widgets.TextInput(attrs={'class': 'form-control'})
    )
    cls_id_id = fields.IntegerField(
        # widget=widgets.Select(choices=[(1,'上海'), (2,'北京')]),
        widget=widgets.Select(
            choices=models.Classes.objects.all().values_list('id', 'title'),
            attrs={'class': 'form-control'}
        )
    )


def students(request):
    stu_list = models.Student.objects.all().values('id', 'name', 'age', 'email', 'cls_id__title')
    return render(request, 'students.html', {'stu_list': stu_list})

def add_student(request):
    if request.method == 'GET':
        obj = StudentForm()
        return render(request, 'add_student.html', {'obj': obj})
    else:
        obj = StudentForm(request.POST)
        if obj.is_valid():
            print(obj.cleaned_data)
            models.Student.objects.create(**obj.cleaned_data)
            return redirect('/students/')
        else:
            print(obj.errors)
            return render(request, 'add_student.html', {'obj': obj})

def edit_student(request, nid):
    if request.method == 'GET':
        row = models.Student.objects.filter(id=nid).values().first()
        obj = StudentForm(row)
        return render(request, 'edit_student.html', {'nid': nid, 'obj': obj})
    else:
        obj = StudentForm(request.POST)
        if obj.is_valid():
            models.Student.objects.filter(id=nid).update(**obj.cleaned_data)
            return redirect('/students/')
        else:
            print(obj.errors)
            return render(request, 'edit_student.html', {'nid': nid, 'obj': obj})

templates.classes.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>班级列表</h1>
    <div>
        <a href="/add_class/">添加</a>
    </div>
<ul>
    {% for row in class_list %}
        <li>{{ row.id }} {{ row.title }} <a href="/edit_class/{{ row.id }}/">编辑</a></li>
    {% endfor %}

</ul>
</body>
</html>

templates.add_class.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>添加班级</h1>
    <form action="/add_class/" method="post" novalidate>
        {% csrf_token %}
        <p>{{ obj.title }}{{ obj.errors.title.0 }}</p>
        <input type="submit" value="提交">
    </form>
</body>
</html>

templates.edit_class.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>编辑班级</h1>
    <form action="/edit_class/{{ nid }}/" method="post">
        {% csrf_token %}
        <p>{{ obj.title }}{{ obj.errors.title.0 }}</p>
        <input type="submit" value="提交">
    </form>
</body>
</html>

templates.students.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>学生列表</h1>
    <a href="/add_student/">添加</a>
    <ul>
        {% for stu in stu_list %}
            <li>{{ stu.id }}-{{ stu.name }}-{{ stu.age }}-{{ stu.email }}-{{ stu.cls_id__title }} <a href="/edit_student/{{ stu.id }}/">编辑</a></li>
        {% endfor %}

    </ul>

</body>
</html>

templates.add_student.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>添加学生</h1>
    <form action="/add_student/" method="post" novalidate>
        {% csrf_token %}
        <p>{{ obj.name }}</p>
        <p>{{ obj.email }}</p>
        <p>{{ obj.age }}</p>
        <p>{{ obj.cls_id_id }}</p>
        <input type="submit" value="提交">
    </form>
</body>
</html>

templates.edit_student.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="/static/plugins/bootstrap-3.3.7-dist/css/bootstrap.css"></link>
</head>
<body>


    <div style=" 500px;margin: 10px auto;">
        <form class="form-horizontal" action="/edit_student/{{ nid }}/" method="post" novalidate>
            {% csrf_token %}
          <div class="form-group">
            <label class="col-sm-2 control-label">姓名</label>
            <div class="col-sm-10">
                {{ obj.name }}
            </div>
          </div>
          <div class="form-group">
            <label class="col-sm-2 control-label">邮箱</label>
            <div class="col-sm-10">
                {{ obj.email }}
            </div>
          </div>
            <div class="form-group">
            <label class="col-sm-2 control-label">年龄</label>
            <div class="col-sm-10">
                {{ obj.age }}
            </div>
          </div>
            <div class="form-group">
            <label class="col-sm-2 control-label">班级</label>
            <div class="col-sm-10">
                {{ obj.cls_id_id }}
            </div>
          </div>
          <div class="form-group">
            <div class="col-sm-offset-2 col-sm-10">
              <button type="submit" class="btn btn-default">Submit</button>
            </div>
          </div>
        </form>
    </div>
</body>
</html>
原文地址:https://www.cnblogs.com/wanyuetian/p/7138768.html