zoukankan      html  css  js  c++  java
  • django中的forms组件(权限信息校验,增删改查)

    1.用处

      1、用户请求数据验证

      2、自动生成错误信息    

      3、打包用户提交的正确信息

      4、如果其中有一个错误了,其他的正确,则保留上次输入的内容

      5、自动创建input标签并可以设置样式

      6.基于forms实现增删改查

    2.使用方法

     对于注册信息进行校验

    在应用下创建一个forms.py文件(起什么名无所谓,后面在视图函数中直接导入进来使用)

    from django import forms
    from django.forms import widgets
    from django.core.exceptions import NON_FIELD_ERRORS, ValidationError
    
    class UserInfo(forms.Form):
        username = forms.CharField(
            required=True,   # 标明是必填字段,不能为空
            min_length=4, max_length=12,
            label="姓名",     # 给定字段名称,直接把username换成了姓名
            error_messages={"required": "用户名不能为空!!"},
            widget=widgets.TextInput(attrs={"placeholder": "用户名", "class": "form-control"}) # 自动生成input框
        )
    
        password = forms.CharField(
            widget=widgets.PasswordInput(attrs={"placeholder":"密码","class":"form-control"}),
            label="密码",
        )
    
        sec_pwd = forms.CharField(
            required=True,
            label="二次密码",
            widget=widgets.PasswordInput(attrs={"placeholder":"二次密码","class":"form-control"})
        )
    
        age = forms.IntegerField(
            label="年龄",
            widget = widgets.NumberInput(attrs={"placeholder":"年龄","class":"form-control"}),
            error_messages={"required": "输入不对!!"},
        )
    
        email = forms.EmailField(
            widget=widgets.EmailInput(attrs={"placeholder":"邮箱","class":"form-control"}),
            label="邮箱",
            error_messages={"invalid": "格式错误"}
        )
    
    
        # 定制化二次错误信息
    
        # 局部钩子
        # 注意这里必须是以clean_  开头,可以查看源码,下面得到的val都是字符串类型
        def clean_username(self):
            val = self.cleaned_data.get("username")
            if not val.isdigit():
                return val
            else:
                raise ValidationError("用户名非纯数字")
    
        def clean_password(self):
            val = self.cleaned_data.get("password")
            if len(val) > 3:
                return val
            else:
                raise ValidationError("密码太短")
    
        def clean_age(self):
            val = self.cleaned_data.get("age")
            if int(val) > 18:
                return val
            else:
                raise ValidationError("岁数太小")
    
    
        # 全局钩子
        # 对于两次输入的密码进行校验是否一致
        def clean(self):
            password = self.cleaned_data.get("password")
            sec_pwd = self.cleaned_data.get("sec_pwd")
            if password == sec_pwd:
                return self.cleaned_data
            else:
                raise ValidationError("两次密码不一致")

      这个类到底干了什么事呢??你在解释器中打印就会发现,第一件事就是将自己显示成HTML。form对象做的第二件事就是来校验信息

      调用任何绑定form的is_valid()方法,就可以知道它的数据是否合法

      Django的form系统自动寻找匹配的函数方法,该方法名称以 clean_ 开头,并以字段名称结束。 如果有这样的方法,它将在校验时被调用。这属于一次额外校验

      如果存在异常,我们抛出一个 forms.ValidationError 型异常,这个异常的描述会被作为错误列表中的一项显示给用户

    views.py

    from django.shortcuts import render,HttpResponse
    # Create your views here.
    from app01.form import UserInfo
    
    
    def index(request):
        # 定制化提示信息,
        if request.method=="POST":
            form = UserInfo(request.POST)
            # 如果全部输入信息有效
            if form.is_valid():
                return HttpResponse("添加成功")
            else:
                # 打印输入的信息
                print("---",form.cleaned_data)      # 得到一个字典
                print("???",form.errors)             # ErrorDict : {"校验错误的字段":["错误信息",]}
                print("!!!",form.errors.get("email"))   # ErrorList ["错误信息",]
    
    
                g_error = form.errors.get("__all__")
                print("+++",g_error)     # <ul class="errorlist nonfield"><li>两次密码不一致</li></ul>
                if g_error:
                    g_error = g_error[0]   # 直接获取你自己的错误提示,即两次密码不一致
                
                return render(request, "index.html", locals())
    
        else:
            form = UserInfo()
            return render(request, "index.html", locals())

     这里form.py和创建的视图函数衔接关键点就在于 form = UserInfo(request.POST)

    模板渲染:

    方式一:

    以p标签的样式展现出来,当然也能以能table标签展示

    index.html

    <!doctype html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport"
              content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Document</title>
        <style>
            .error {
                color: red;
            }
        </style>
        <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.css">
    </head>
    <body>
    <h3>注册用户</h3>
    <div class="container">
        <div class="row">
            <div class="col-md-8 col-md-offset-2">
                {# 这个novalidate很重要啊,没有这个后面自己定制的错误提示无法渲染出来 #}
                {# 自己编写表单验证插件的时候,使用它可以避免和默认的表单验证冲突 #}
                <form action="" method="post" novalidate>
                    {% csrf_token %}
                    {{ form.as_p }}
                    <input type="submit">
               </form>
            </div>
        </div>
    </div>
    
    </body>
    </html>

    # 要注意这里form表单中添加的属性novalidate,它能够避免和默认的表单验证发生冲突

    方式二:

    书写相对麻烦

    <form action="" method="post" novalidate>
          {% csrf_token %}
                    <div>
                        <p>姓名</p>
                        {{ form.username }}
                    </div>
                    <div>
                        <p>密码</p>
                        {{ form.password }}
                    </div>
                    <div>
                        <p>二次密码</p>
                        {{ form.sec_pwd }}
                    </div>
                    <div>
                        <p>年龄</p>
                        {{ form.age }}
                    </div>
                    <div>
                        <p>年龄</p>
                        {{ form.email }}
                    </div>
                    <input type="submit">
        
     </form>

    方式三(常用):

    <form action="" method="post" novalidate>
            {% csrf_token %}
                    {% for foo in form %}
                        <div class="form-group">
                            {# 渲染出lable标签,标签后面是输入框 #}
                            <lable>{{ foo.label }}</lable>{{ foo }}
                            {# 专门定制报错信息 #}
                            <span class="error pull-right">{{ foo.errors.0 }}</span>
                            {# 对于二次输入报错信息进行设置 #}
                            {% if foo.label == "二次密码" %}
                                <span class="error pull-right">{{ g_error|default_if_none:"" }}</span>
                            {% endif %}
                        </div>
                    {% endfor %}
                    <input type="submit" class="btn btn-default btn-sm">
                </form>

     3.基于forms组件的ModelForm实现的增删改查

    models.py

    from django.db import models
    
    class Depart(models.Model):
        caption = models.CharField(max_length=32)
    
        def __str__(self):
            return self.caption
    class Role(models.Model):
        title = models.CharField(max_length=32)
    
        def __str__(self):
            return self.title
    
    class User(models.Model):
    
        name = models.CharField(verbose_name='姓名',max_length=32)
        depart = models.ForeignKey(verbose_name='部门',to='Depart',on_delete=models.CASCADE)
    
        gender_choices = (
            (1,''),
            (2,''),
        )
        gender = models.IntegerField(verbose_name='性别',choices=gender_choices,default=1)
    
        roles = models.ManyToManyField(verbose_name='角色',to='Role')

    urls.py

    from django.contrib import admin
    from django.urls import path,re_path
    from app01 import views
    urlpatterns = [
        path('admin/', admin.site.urls),
        re_path('user/list/$', views.user_list),
        re_path('user/add/$', views.user_add),
        re_path('user/edit/(?P<uid>d+)/$', views.user_edit),
        re_path('user/del/(?P<uid>d+)/$', views.user_del),
    ]

    views.py

    from django.shortcuts import render,redirect
    from app01 import models
    
    def user_list(request):
        user_queryset = models.User.objects.all()
        return render(request,'user_list.html',{'user_queryset':user_queryset})
    
    
    from django import forms
    class UserForm(forms.ModelForm):
        class Meta:
            model = models.User
            fields = '__all__'
            # fields = ['name','depart']
            widgets = {
                'name':forms.TextInput(attrs={'class':'form-control'}),
                'depart':forms.Select(attrs={'class':'form-control'}),
                'gender':forms.Select(attrs={'class':'form-control'}),
                'roles':forms.SelectMultiple(attrs={'class':'form-control'}),
            }
            error_messages = {
                'name':{
                    'required':'用户名不能为空'
                }
            }
    
    def user_add(request):
        if request.method == "GET":
            form = UserForm()
        else:
            form = UserForm(request.POST)
            if form.is_valid():
                print('通过验证')
                form.save()
                return redirect('/user/list/')
        return render(request,'user_add.html',{'form':form})
    
    
    def user_edit(request,uid):
        obj = models.User.objects.filter(id=uid).first()
        if request.method =='GET':
            form = UserForm(instance=obj)
            return render(request,'user_edit.html',{'form':form})
        else:
            form = UserForm(data=request.POST,instance=obj)
            if form.is_valid():
                form.save()
                return redirect('/user/list/')
            else:
                return render(request, 'user_edit.html', {'form': form})
    
    
    def user_del(request,uid):
        models.User.objects.filter(id=uid).delete()
        return redirect('/user/list/')

     user_list.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    </head>
    <body>
        <div class="container">
            <a href="/user/add/" class="btn btn-primary">添加</a>
            <table class="table table-bordered">
                <thead>
                    <tr>
                        <th>名称</th>
                        <th>性别</th>
                        <th>部门</th>
                        <th>角色</th>
                        <th>操作</th>
                    </tr>
                </thead>
                <tbody>
                    {% for row in user_queryset %}
                        <tr>
                            <td>{{ row.name }}</td>
                            <td>{{ row.get_gender_display }}</td>
                            <td>{{ row.depart.caption }}</td>
                            <td>
                                {% for node in row.roles.all %}
                                    <span>{{ node.title }}</span>
                                {% endfor %}
                            </td>
                            <td>
                                <a href="/user/edit/{{ row.id }}/">编辑</a>
                                <a href="/user/del/{{ row.id }}/">删除</a>
                            </td>
                        </tr>
                    {% endfor %}
                </tbody>
            </table>
        </div>
    </body>
    </html>

     user_edit.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
         <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    </head>
    <body>
        <h1>编辑用户</h1>
        <form method="post" novalidate>
            {% csrf_token %}
            {% for field in form %}
                <div>{{ field.label }}{{ field }} {{ field.errors.0 }}</div>
            {% endfor %}
            <input type="submit" value="提交">
        </form>
    </body>
    </html>

    user_add.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
         <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    </head>
    <body>
        <div class="container">
            <h1>添加用户</h1>
            <form method="post" class="form-horizontal" novalidate>
                {% csrf_token %}
                {% for field in form %}
                    <div class="form-group">
                        <label class="col-sm-2 control-label">{{ field.label }} </label>
                        <div class="col-sm-10">
                          {{ field }} {{ field.errors.0 }}
                        </div>
                      </div>
                {% endfor %}
                <input type="submit" value="提交">
            </form>
        </div>
    </body>
    </html>

     效果:

    这里其他效果:

  • 相关阅读:
    remove white space from read
    optimize the access speed of django website
    dowload image from requests
    run jupyter from command
    crawl wechat page
    python version 2.7 required which was not found in the registry windows 7
    health
    alternate rows shading using conditional formatting
    word
    【JAVA基础】static 关键字
  • 原文地址:https://www.cnblogs.com/LearningOnline/p/9278447.html
Copyright © 2011-2022 走看看