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>

     效果:

    这里其他效果:

  • 相关阅读:
    AFHTTPRequestOperationManager的那些事
    iOS缩放图片
    iOS截图
    网络服务
    Six
    正文处理命令及tar命令
    用户,群组和权限 四
    用户,群组和权限 三
    用户,群组和权限 二
    用户,群组和权限 一
  • 原文地址:https://www.cnblogs.com/LearningOnline/p/9278447.html
Copyright © 2011-2022 走看看