zoukankan      html  css  js  c++  java
  • Python学习---DjangoForm的学习

    DjangoForm之创建工程

    Form是什么东西:

          用于验证用户请求数据合法性的一个组件

    普通的Form提交的弊端:

        1.用户提交数据的验证

        2.前台需要进行错误信息的提示

        3.需要保留上次用户输入的信息

    # 此处是正常的Form的判断操作
    """
    def Login(request):
        if request.method == "GET":
            return render(request, 'login.html')
        elif request.method == "POST":
            # 如果用户输入了10条数据,则Form里需要写10个get来获取值
            user = request.POST.get("user")
            passwd = request.POST.get('passwd')
            email = request.POST.get('email')
            # 判断用户的输入[涉及用户的为空判断,输入格式内容校验以及数据库操作等判断]
            # 数据库校验: 传入参数校验  + 字典的传入校验  **kwargs
            #  filter(user=u, email=e,passwd=p)   ==> filter(**kwargs) 
            #  create(user=u, email=e,passwd=p)   ==> create(**kwargs)
            # 如果校验失败,页面需要给用户显示错误信息,不能redirect[form提交页面会刷新,上次数据无法保留,ajax不涉及]
            只能return render(request, 'login.html; 'args'arg),需要给前台HTML添加{{msg}}操作
    """

    查看Django为我们创建的正则:

    image

    DjangoForm的Form验证

    Django的Form验证
        - 控诉:
            a. 用户提交数据的验证
                1、创建模版                      class LoginForm(forms.Form):...
                2、将请求交给模版,创建一个对象  obj = LoginForm(request.POST)
                3、进行验证                       obj.is_valid()【必须执行,这里开始校验,否则clean获取不到值】
                4、获取正确信息                  obj.clean()          
                5、获取错误信息                  obj.errors
            b. 错误信息提示[传递Form对象给后台]
                Form提交,刷新页面的特性,DjangoForm模版对象内部值丰富,再显示时,值和错误信息都有           
            c. 保留上一次提交的数据
                1、自动生成html标签【实际上{{obj.user}} 就是内部生成了一个HTML的字符串】
                2、保留上一次提交的数据【input框的value值更改为上次提交的值即可】       
    注:
        obj对象里面有正确信息也有错误信息
        Form使用 a,b,c
        ajax使用 a,错误信息处理: as_json()    as_data()

    DjangoForm之前台参数校验实例

    settings.py

    INSTALLED_APPS = [
       ...
     'app01',   # 注册app
    ]
    STATICFILES_DIRS = (os.path.join(BASE_DIR, "statics"),)  # 现添加的配置,这里是元组,注意逗号
    TEMPLATES = [
       ...
       'DIRS': [os.path.join(BASE_DIR, 'templates')],
    ]

    urls.py

    from django.contrib import admin
    from django.urls import path
    from django.conf.urls import url, include
    from app01 import views
    urlpatterns = [
       path('admin/', admin.site.urls),
       url(r'login.html/', views.Login),
    ]

    views.py

    from django.shortcuts import render, redirect
    # 创建模板
    # 本质是从请求中获取数据后来进行校验
    from django import forms
    class LoginForm(forms.Form):
        # 前台Form表单里面的name属性的值必须跟这里的名称完全一致,这样数据提交后才能进行校验
        # 如果名称不一致,则默认数据未传递过来,不作处理
        # 如果传递多个参数,则模版默认只按照名称来进行匹配,有则匹配,无责不匹配
        user = forms.CharField(min_length=6)     # 模版元素
        passwd = forms.CharField(min_length=12)  # 模版元素
        email = forms.EmailField(error_messages={"required": "格式错误"})# 模版元素同时自定义格式
    """
        code:
            required:   如果输入为空的时候显示
            invalid:    输入的类型错误
            min_length: 最小长度
    """
    def Login(request):
        if request.method == "GET":
            return render(request, 'login.html')
        elif request.method == "POST":
            # 模版会自动从request里面取值并校验
            obj = LoginForm(request.POST)
            # 从模版里面开始验证,全部正确则显示结果正确,否则错误
            status = obj.is_valid()
            print('验证结果:', status)
            if status:
                # 获取校验过的值和验证的错误信息
                value_dict = obj.clean()
                print('验证通过的值:', value_dict)
                # 类.create(**value_dict)  --> 此时可以直接插入数据到数据库了
            else:
                error_dict = obj.errors  # 此时的返回结果是个ErrorDict对象,可以type看类型
         # <class 'django.forms.utils.ErrorDict'>该对象基础DICT这个里面有as_json和as_data方法
                print('错误的信息[默认UL显示]:', error_dict)
                error_dict_json = obj.errors.as_json()  # 此时的返回结果是个JSON集
                print('错误的信息[json显示]:', error_dict_json)
            return render(request, 'login.html',{'obj': obj})

    templates/login.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
    </head>
    <body>
        <h1>Form提交数据</h1>
        <form method="post" action="/login.html/">
                     <!-- 前台的属组操作只能用点.来获取列表的第一个元素 -->
            <p><input type="text" name="user" placeholder="用户名"><span>{{ obj.user.errors.0}}</span></p>
       <p><input type="password" name="passwd" placeholder="密码"><span>{{ obj.passwd.errors.0}}</span></p>
             <p><input type="text" name="email" placeholder="邮箱"><span>{{ obj.user.email.0}}</span></p>
            <input type="submit" value="Form提交">
            <input id='ajax_submit' type="button" value="Ajax提交">
        </form>
    </body>
    <script src="/static/jquery-2.1.4.min.js"></script>
    <script>
        $(function () {
            $('#ajax_submit').click(function () {
                $.ajax({
                    url:"/login.html",
                    data:{user:'omc', email:'omc@hhh.com', passwd:'lem600'},
                    type:'POST',
                    success:function (args) {
                        console.log(args)
                    }
                })
            })
        })
    </script>
    </html>

    页面显示:

    image

    image

    学习扩展:

    # 封装Django里面的所有错误信息

    error_dict = obj.errors  # 此时的返回结果是个ErrorDict对象
    print('错误的信息[UL显示]:', error_dict) # 这里返回的是一个对象
    print('错误信息类型:', type(error_dict))#因为返回了ErrorDict里面__str__方法:return self.as_ul();
    # 因为返回的是DICT对象,所以可以利用key获取
    print('错误信息类型:', type(error_dict)) # 错误信息类型: <class 'django.forms.utils.ErrorDict'>
    #print('获取错误信息[属性获取]:', error_dict.user)   # 错误,'ErrorDict' object has no attribute 'user'
    print('获取错误信息[key获取]:', error_dict['user']) # 正确
    print('获取错误信息[key获取]类型:', type(error_dict['user']))  # ErrorList类型,默认返回第一个list[0]
    print('获取错误信息[此时是字符串]:', error_dict['user'][0]) # 字符串 This field is required.

    image

    DjangoForm之提交数据后保留数据

       Django会自动生成HTML,并保留我们生成的数据

    settings.py

    INSTALLED_APPS = [
       ...
     'app01',   # 注册app
    ]
    STATICFILES_DIRS = (os.path.join(BASE_DIR, "statics"),)  # 现添加的配置,这里是元组,注意逗号
    TEMPLATES = [
       ...
       'DIRS': [os.path.join(BASE_DIR, 'templates')],
    ]

    urls.py

    from django.contrib import admin
    from django.urls import path
    from django.conf.urls import url, include
    from app01 import views
    urlpatterns = [
       path('admin/', admin.site.urls),
       url(r'login.html/', views.Login),
    ]

    views.py

    from django.shortcuts import render, redirect
    # 创建模板
    # 本质是从请求中获取数据后来进行校验
    from django import forms
    class LoginForm(forms.Form):
        # 前台Form表单里面的name属性的值必须跟这里的名称完全一致,这样数据提交后才能进行校验
        # 如果名称不一致,则默认数据未传递过来,不作处理
        # 如果传递多个参数,则模版默认只按照名称来进行匹配,有则匹配,无责不匹配
        user = forms.CharField(min_length=6)     # 模版元素
        passwd = forms.CharField(min_length=12)  # 模版元素
        email = forms.EmailField(error_messages={"required": "格式错误"})# 模版元素同时自定义格式
    """
        code:
            required:   如果输入为空的时候显示
            invalid:    输入的类型错误
            min_length: 最小长度
    """
    def Login(request):
        if request.method == "GET":
           obj = LoginForm()  # 这里生成的obj对象只有生成HTML的作用,但是名称必须跟后面POST对象一致
           return render(request, 'login.html', {'obj': obj})
        elif request.method == "POST":
            # 模版会自动从request里面取值并校验
            obj = LoginForm(request.POST)
            # 从模版里面开始验证,全部正确则显示结果正确,否则错误
            status = obj.is_valid()
            print('验证结果:', status)
            if status:
                # 获取校验过的值和验证的错误信息
                value_dict = obj.clean()
                print('验证通过的值:', value_dict)
                # 类.create(**value_dict)  --> 此时可以直接插入数据到数据库了
            else:
                error_dict = obj.errors  # 此时的返回结果是个ErrorDict对象,可以type看类型
         # <class 'django.forms.utils.ErrorDict'>该对象基础DICT这个里面有as_json和as_data方法
                print('错误的信息[默认UL显示]:', error_dict)
                error_dict_json = obj.errors.as_json()  # 此时的返回结果是个JSON集
                print('错误的信息[json显示]:', error_dict_json)
            return render(request, 'login.html',{'obj': obj})

    templates/login.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
    </head>
    <body>
        <h1>Form提交数据</h1>
        <form method="post" action="/login.html/">
                                                                  <!-- 前台的属组操作只能用点.来获取,这里的表单是Django帮我们做的 -->
            <p>{{ obj.user }}<span>{{ obj.user.errors.0}}</span></p>
            <p>{{ obj.passwd }}<span>{{ obj.passwd.errors.0}}</span></p>
            <p>{{ obj.email }}<span>{{ obj.user.email.0}}</span></p>
            <input type="submit" value="Form提交">
            <input id='ajax_submit' type="button" value="Ajax提交">
        </form>
    </body>
    <script src="/static/jquery-2.1.4.min.js"></script>
    <script>
        $(function () {
            $('#ajax_submit').click(function () {
                $.ajax({
                    url:"/login.html",
                    data:{user:'omc', email:'omc@hhh.com', passwd:'lem600'},
                    type:'POST',
                    success:function (args) {
                        console.log(args)
                    }
                })
            })
        })
    </script>
    </html>

    页面显示;

    image

    问题:为什么get的Form对象必须和Form的一致?

    答: get请求过来后我们实例化了一个不带参数的LoginForm的obj对象,此时的只能在前台生成HTML作用[前台obj.user]

       post请求提交数据后,我们实例化了一个带POST参数的LoginForm的obj对象,里面有我们前台请求的数据,此时obj对象具有1.生成前台HTML的作用 2.带了post参数可以直接前台显示 3.我们前台用来同一个模板{{  }}来接收数据【正确/错误信息】,所以obj对象的名称不能改

    如果我们更改POST对象名称为obj1,前台也更改为obj1,此时数据提交后就不再显示input框了,因为一个是obj,一个是obj1

    附:input标签的生成过程[源码分析]

    image

    DjangoForm的Ajax验证【代码有问题】

    settings.py

    INSTALLED_APPS = [
       ...
     'app01',   # 注册app
    ]
    STATICFILES_DIRS = (os.path.join(BASE_DIR, "statics"),)  # 现添加的配置,这里是元组,注意逗号
    TEMPLATES = [
       ...
       'DIRS': [os.path.join(BASE_DIR, 'templates')],
    ]

    urls.py

    from django.contrib import admin
    from django.urls import path
    from django.conf.urls import url, include
    from app01 import views
    urlpatterns = [
       path('admin/', admin.site.urls),
       url(r'login.html/', views.Login),
       url(r'^login_ajax.html', views.login_ajax),
    ]

    views.py

    from django.shortcuts import render
    from django.shortcuts import HttpResponse
    import json
    def login_ajax(request):
        if request.method == "GET":
            return render(request, 'login_ajax.html')
        elif request.method == "POST":
            ret = {'status': True, 'error':None, 'data': None}
            obj = LoginForm(request.POST)
            if obj.is_valid():
                print(obj.clean())
            else:
                # 方式一
                # res_str = obj.errors.as_json() # res_str是一个字符串
                # ret['status'] = False
                # ret['error'] = res_str
                # 两次反序列化
                # 方式二:将Django的ValidationError类型转换为JSON对象
                ret['status'] = False
                ret['error'] = obj.errors.as_data() #Djaongo的数据类型 {'user': [ValidationError(['用户名长度不能小6'])], 'email': [ValidationError(['邮箱格式错误'])]}
                # 一次反序列化
            return HttpResponse(json.dumps(ret, cls=JsonCustomEncoder))
    
    # 方式一不需要此类
    from django.core.validators import ValidationError
    class JsonCustomEncoder(json.JSONEncoder):
        def default(self, field):
            if isinstance(field, ValidationError):
                return {'code': field.code, 'message': field.message}
            else:
                return json.JSONEncoder.default(self, field)

    templates/login_ajax.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style>
            .error-msg{
                color: red;
                font-size: 12px;
            }
        </style>
    </head>
    <body>
        <h1>Form提交数据</h1>
        <form id="f1">
            <p>        <input id="u" type="text" name="user" placeholder="用户名" />    </p>
            <p>        <input id="e" type="text" name="email" placeholder="邮箱" />    </p>
            <p>        <input id="p" type="text" name="pwd" placeholder="密码" />    </p>
            <input id="ajax_submit" type="button" value="Ajax提交"  />
        </form>
        <script src="/static/jquery-2.1.4.min.js"></script>
        <script>
            $(function () {
                $('#ajax_submit').click(function () {
                    $.ajax({
                        url:"/login_ajax.html",
                        //data: {user: $('#u').val(), email: $('#e').val(), pwd: $('#p').val()},
                        data: $('#f1').serialize(),
                        type: 'POST',
                        success:function (arg) {
                            $('.error-msg').remove();
                            var v1 = JSON.parse(arg);  //解析JSON数据
                            console.log(v1);
                            if(!v1.status){
                                // var error_obj = JSON.parse(v1.error);
                                var error_obj = v1.error;
                                $.each(error_obj,function (k,v) {
                                    // k: user 或 email
                                    // v: [{}{}{},]
                                    var tag = document.createElement('span');
                                    tag.className = 'error-msg';
                                    tag.innerHTML = v[0].message;
                                    $("input[name='" + k +"']").after(tag);
                                })
                            }else{
                                location.href = "/inde.html"
                            }
                            // { 'stauts': true, 'error':xx, 'data':’‘}
                        }
                    })
                })
            })
        </script>
    </body>
    </html>

    页面显示;

    image

    DjangoForm更多用法之多选框

    settings.py

    INSTALLED_APPS = [
       ...
     'app01',   # 注册app
    ]
    STATICFILES_DIRS = (os.path.join(BASE_DIR, "statics"),)  # 现添加的配置,这里是元组,注意逗号
    TEMPLATES = [
       ...
       'DIRS': [os.path.join(BASE_DIR, 'templates')],
    ]

    urls.py

    from django.contrib import admin
    from django.urls import path
    from django.conf.urls import url, include
    from app01 import views
    urlpatterns = [
            path('admin/', admin.site.urls),
            url(r'^index.html', views.index),
            url(r'^edit_index.html', views.edit_index), 
    ]

    views.py

    from django.shortcuts import render
    from django.shortcuts import HttpResponse
    class IndexForm(forms.Form):
        # 模版中的元素
        user = forms.CharField(min_length=6,error_messages={"required": '用户名不能为空','min_length': '用户名长度不能小6'})
        email = forms.EmailField(error_messages={"required": '邮箱不能为空','invalid': '邮箱格式错误'})
       favor = forms.MultipleChoiceField( choices=[(1,'AAA'),(2,'BBB'),(3,'CCC')]    )
    def index(request):
        obj = IndexForm()
        return render(request,'index.html',{'obj': obj})
    def edit_index(request):
        obj = IndexForm({'user': 'root','email': 'hhh@666.com','favor': [2,3]})
        return render(request,'index.html',{'obj': obj})

    templates/index.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <p>{{ obj.user }}</p>
        <p>{{ obj.email }}</p>
        <p>{{ obj.favor }}</p>
    </body>
    </html>

    DjangoForm更多用法之widget插件基本使用

    settings.py

    INSTALLED_APPS = [
       ...
     'app01',   # 注册app
    ]
    STATICFILES_DIRS = (os.path.join(BASE_DIR, "statics"),)  # 现添加的配置,这里是元组,注意逗号
    TEMPLATES = [
       ...
       'DIRS': [os.path.join(BASE_DIR, 'templates')],
    ]

    urls.py

    from django.contrib import admin
    from django.urls import path
    from django.conf.urls import url, include
    from app01 import views
    urlpatterns = [
       # 带插件的Form
     url(r'^detail.html', views.Detail),
    ]

    views.py

    from django.shortcuts import render, redirect
    
    from django import forms          # forms里面引用了field,widget的内容
    from django.forms import fields   # 这里再次引用是为了更加明确而已
    from django.forms import widgets
    # 带插件的Form,这里是定义模板
    class DetailForm(forms.Form):
        # user = fields.CharField() 默认widget = TextInput;此时就是一个白框,里面输入的文字都是明文【字符串】
        # 自定义样式: attrs={'class': 'c1'} 此时就告诉Django,我要给生成的标签添加了样式class=c1
        user = fields.CharField(widget=widgets.PasswordInput(attrs={'class': 'c1', 'placeholder': '请输入密码'}))
        # choices接收的是列表,列表里面是元组,里面2个值[第一个参数是value值,第二个是]
        choice = fields.ChoiceField(choices=[(1, '北京'), (2, '南京'), (3, '天津')])
        # Django可以把前台的字符串转换为数字类型
        age = fields.IntegerField()  
        # 总结: 如果是个单值[字符串],直接获取用户输入的字符串,  ---> CharField()[获取字符串]
        # 如果是个单值[数  字],直接获取用户输入的数字,  ---> IntegerField(),Django帮我们字符串换Int类型
        #        如果是个多值[下拉框],直接获取用户选择的字符串,  ---> ChoiceField()[获取的是字符串]
        # 前台返回的只有3类:字符串,数字, 列表
    
    def Detail(request):
        obj = DetailForm()
        return render(request, 'detail.html', {'obj': obj})

    templates/detail.html、

    <!DOCTYPE html>
    <html lang="en">
    <head>    <meta charset="UTF-8">  </head>
    <body>
        {{ obj.user }}
        {{ obj.choice }}
    </body>
    </html>

    页面显示;

    image

    学习拓展:

    choice = fields.ChoiceField(choices=[(1, '北京'), (2, '南京'), (3, '天津')])
    new_choice = fields.CharField(widget=widgets.Select(choices=[(1, '北京'), (2, '南京'), (3, '天津')]))
    int_choice = fields.IntegerField(widget=widgets.Select(choices=[(1, '北京'), (2, '南京'), (3, '天津')]))
    radio_select = fields.CharField(widget=widgets.RadioSelect(choices=[(1, '北京'), (2, '南京'), (3, '天津')]))

    CharField也可以利用插件实现select的效果,所以ChoiceField实际上是new_choice一系列的简写

    Choice和new_choice的返回结果是字符串

    Int_choice的返回结果是整数类型

    最强大的还是CharField,虽然生成的text文本框,但是可以通过插件实现转换其他HTML样式

    DjangoForm更多用法之字段和插件更多使用

    settings.py

    INSTALLED_APPS = [
       ...
     'app01',   # 注册app
    ]
    STATICFILES_DIRS = (os.path.join(BASE_DIR, "statics"),)  # 现添加的配置,这里是元组,注意逗号
    TEMPLATES = [
       ...
       'DIRS': [os.path.join(BASE_DIR, 'templates')],
    ]

    urls.py

    from django.contrib import admin
    from django.urls import path
    from django.conf.urls import url, include
    from app01 import views
    urlpatterns = [
        # 带插件的Form
        url(r'^detail.html', views.Detail),
        url(r'^fieldForm.html', views.DetailField), 
    ]

    views.py

    from django.shortcuts import render, redirect
    
    from django import forms          # forms里面引用了field,widget的内容
    from django.forms import fields   # 这里再次引用是为了更加明确而已
    from django.forms import widgets
    from django.core.validators import RegexValidator
    # 字段的详细使用
    class FieldForm(forms.Form):
        f = fields.CharField(
            required=True,     # 是否必须填写, 默认是必填的,
            max_length=8,      # 最大长度限制
            min_length=6,      # 最小长度限制
            label='用户名',    # 用于前端显示用的标签 obj.f.label  自带属性; 也可用obj.f.label_tag实现自动写入
            initial='用户名',   # 文本框内的初始值; views里面注意区别GET和POST请求,initial默认是GET请求显示
            show_hidden_initial='初始隐藏的值',  # 显示一个隐藏的标签,可以判断输入的值和隐藏的值是否有区别,然后处理
            validators=[RegexValidator(r'^[0-9]+$', 'phoneNumber must be digital', code='phoneNumberError'), ],  # 自定义验证规则
            error_messages={'required': '不能为空', 'invalid': '格式错误', 'max_length': '格式太长了'},  # 不指定则显示默认的
            disabled=True,  # 默认disabled=False,表示文本框可以编辑
            label_suffix='--->',  # label的后缀,默认是冒号,这里更改为 --->
        )
        '''
            注意: error_messages里面通过code来进行错误信息的匹配
                   想覆盖原来英文的错误信息,在error_messages覆盖即可
                   error_messages的优先级别高于自定义的优先级,且根据code来进行匹配
                   error_messages可以根据前面有什么参数[eg,min_length],message的code就可以写什么[这里就是min_length]
                   最常用的2个: required, invalid   max_length   min_length 
        '''
        # 另一种方式实现自定义正则[第一种是上述的CharField里面的的validator]
        f2 = fields.RegexField(r'^[0-9]+$')
        '''
        文件上传:
            1.form表单需要使用enctype="multipart/form-data"
            2.后台需要request.Files来接收文件,  obj = FieldForm(request.POST, request.FILES)
            3.获取文件对象InMemoryUploadedFile[对象内有文件名称,文件大小,文件内容]
        '''
        f3 = fields.FileField(allow_empty_file=False) # 文件不允许为空
        # 设置下拉框,此时默认返回的是字符串类型
        f4 = fields.ChoiceField(
            initial=2,      # 设置默认值,单选的时候只能选择1个默认值哈
            choices=((1, 'AAA'), (2, 'BBB'), (3, 'CCC')),  # 设置下拉选项[可迭代的就行]此时返回的1,2,3是字符串'1','2','3'
        )
        # 自带类型转换的Choice
        f5 = fields.TypedChoiceField(
            coerce=lambda x: int(x),  # 传递的参数转换为int类型;  lambda的等号[=]2边不需要空格
            initial=2,  # 设置默认值,单选的时候只能选择1个默认值哈
            choices=((1, 'AAA'), (2, 'BBB'), (3, 'CCC')),  # 设置下拉选项[可迭代的就行]此时返回的1,2,3是字符串'1','2','3'
        )
        # 设置下拉框多选
        f6 = fields.MultipleChoiceField(
            initial=(2, 3),  # 设置默认值,必须是可迭代的就行
            choices=((1, 'AAA'), (2, 'BBB'), (3, 'CCC')),  # 设置下拉选项[可迭代的就行]此时返回的1,2,3是字符串'1','2','3'
        )
        # 实现多个验证[既满足A又满足B]
        f7 = fields.ComboField(fields=[fields.CharField(max_length=20), fields.EmailField(), ])  # 里面是个可迭代对象
    
        # 抽象类,子类中可以实现聚合多个字典去匹配一个值,要配合MultiWidget使用
        f8 = fields.MultiValueField(fields=[fields.ChoiceField(), ])  # 里面是可迭代对象
        # 生成2个框,因为继承了MultiValueField[这个类中有2个定制的CharField]
        f9 = fields.SplitDateTimeField()
        # 文件选项:此时会把当前app01路径下的所有文件以下拉框的形式显示[提交也是提交选中选项]
        f10 = fields.FilePathField(path='app01',
                                   match=None,           # 正则匹配
                                   recursive=False,      # 递归下面的文件夹
                                   allow_files=True,     # 是否允许文件
                                   allow_folders=False,  # 是否允许文件夹等其他属性)
                                   )
        # IP的验证
        f11 = fields.GenericIPAddressField()
        # 只允许数字,字母,下划线
        f12 = fields.SlugField()           # 数字,字母,下划线,减号(连字符)
        # UUID
        f13 = fields.UUIDField()
    
    def DetailField(request):
        if request.method == "GET":
            obj = FieldForm()
            return render(request, 'fieldForm.html', {'obj': obj})
        else:
            obj = FieldForm(request.POST, request.FILES)  # 注意别忘了参数,因为is_valid和clean都是POST请求的
            obj.is_valid()
            data = obj.clean()
            error_json = obj.errors.as_json()
            print("正确信息:", data)
            print("错误信息:", error_json)
            return render(request, 'fieldForm.html', {'obj': obj})

    templates/fieldForm.html、

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
    </head>
    <body>
        <form action="/fieldForm.html/" method="post" enctype="multipart/form-data">
            <h2>{{ obj.f.id_for_label }} 是个字符串,自动生成了一个id,这里自定制label效果</h2>
            <label for="{{ obj.f.id_for_label }}">{{ obj.f.label }}:</label>{{ obj.f }} <hr>
            <h2> {{ obj.f.label_tag }}可以自动帮我们生成label标签,等价上面的全部  </h2>
            {{ obj.f.label_tag }}{{ obj.f }}<hr>
            <h2>第二种自定义正则</h2>
            {{ obj.f2 }}<hr>
            <h2>文件上传</h2>
            {{ obj.f3 }}<hr>
            <h2>下拉框</h2>
            {{ obj.f4 }}<hr>
            <h2>多选下拉框</h2>
            {{ obj.f6 }}
            <input type="submit" value="提交">
        </form>
    </body>
    </html>

    页面显示[不全显示];

    image

      DjangoForm应用-- select数据从数据库取且实时刷新

    settings.py

    INSTALLED_APPS = [
       ...
     'app01',   # 注册app
    ]
    STATICFILES_DIRS = (os.path.join(BASE_DIR, "statics"),)  # 现添加的配置,这里是元组,注意逗号
    TEMPLATES = [
       ...
       'DIRS': [os.path.join(BASE_DIR, 'templates')],
    ]

    urls.py

    from django.contrib import admin
    from django.urls import path
    from django.conf.urls import url, include
    from app01 import views
    urlpatterns = [
         # select的数据从数据库来,且实时更新
      url(r'^db.html', views.db), 
    ]

    views.py

    from django.shortcuts import render, redirect
    
    from django import forms          # forms里面引用了field,widget的内容
    from django.forms import fields   # 这里再次引用是为了更加明确而已
    from django.forms import widgets
    from django.core.validators import RegexValidator
    
    from app01.models import DBModel
    class DBForm(forms.Form):
        d1 = fields.CharField()
        # 固定的option
        type1 = fields.ChoiceField(choices=[(1, 'AAA'), (2, 'BBB'), (3, 'CCC')])
        # 从数据库内获取option
        type2 = fields.ChoiceField(choices=DBModel.objects.all().values_list())  # 将数据转换为元组类型的list
        # 实时刷新数据库内容
        type3 = fields.ChoiceField(choices=[]) # 数据从数据库读取一次,每次生成对象都从内存获取,易产生脏数据
    
        def __init__(self, *args, **kwargs):   # 调用父级别的构造方式,每次创建对象的时候都会获取数据
            super(DBForm, self).__init__(*args, **kwargs)
            self.fields['type3'].choices = DBModel.objects.all().values_list() # 数据从此处获取
    
    def db(request):
        # 手动在数据库内创建数据库数据  --> 图形界面提交
        if request.method == "GET":
            obj = DBForm()
            return render(request, 'db.html', {'obj': obj})
        else:
            obj = DBForm(request.POST, request.FILES)  # 注意别忘了参数,因为is_valid和clean都是POST请求
            obj.is_valid()
            data = obj.clean()
            error_json = obj.errors.as_json()
            print("正确信息:", data)
            print("错误信息:", error_json)
            return render(request, 'db.html', {'obj': obj})

    app01/models.py

    from django.db import models
    # Create your models here.
    class DBModel(models.Model):
        type = models.CharField(max_length=22)  #  创建type字段且id是Django帮我们创建

    templates/db.html、

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
    </head>
    <body>
                用户名: {{ obj.d1 }}<br>
                固定的: {{ obj.type1 }}<br>
                数据库: {{ obj.type2 }}<br>
    实时刷新数据库内容:  {{ obj.type3 }}<br>
    </body>
    </html>

    初始化数据库:

    python manage.py makemigrations
    python manage.py migrate
    

    页面显示[不全显示]

    image

    数据库内容:

    image

    DjangoForm应用--新URL方式编辑时,默认内容选中

    settings.py

    INSTALLED_APPS = [
       ...
     'app01',   # 注册app
    ]
    STATICFILES_DIRS = (os.path.join(BASE_DIR, "statics"),)  # 现添加的配置,这里是元组,注意逗号
    TEMPLATES = [
       ...
       'DIRS': [os.path.join(BASE_DIR, 'templates')],
    ]

    urls.py

    from django.contrib import admin
    from django.urls import path
    from django.conf.urls import url, include
    from app01 import views
    urlpatterns = [
    # 新URL方式编辑时,且内容默认选中
    url(r'^dbEdit.html', views.dbEdit),
    ]

    views.py

    from django.shortcuts import render, redirect
    
    from django import forms          # forms里面引用了field,widget的内容
    from django.forms import fields   # 这里再次引用是为了更加明确而已
    from django.forms import widgets
    from django.core.validators import RegexValidator
    
    from app01 import models
    class DBEditForm(forms.Form):
        user = fields.CharField()
        user_type1 = fields.IntegerField(widget=widgets.Select(choices=[(1, 'AAA'), (2, 'BBB'), (3, 'CCC')]))
        user_type2 = fields.IntegerField(widget=widgets.Select(choices=[]))
        def __init__(self, *args, **kwargs):
            super(DBEditForm, self).__init__(*args, **kwargs)
            self.fields['user_type2'].widget.choices = DBModel.objects.all().values_list()
    # 新URL方式编辑时,默认选中
    def dbEdit(request):
        if request.method == "GET":
            nid = request.GET.get('nid')   # 前台定义的nid
            info = models.UserInfo.objects.filter(id=nid).first()
            print('用户姓名:', info.usename, '
    用户类型:', info.type_id)
            '''
                如果这里的字典dic跟DBEditForm里面的字段一致,则Django默认会帮我们填补数据的
                方案一: 自定义固定的内容:这里采用自定义,info我们转换为字典同理同效果
                    dic = {'user': 'root2020', 'user_type1': 3, 'user_type2': 5} 
                    obj = DBEditForm(dic)
                方案二: 将info对象转换为字典,根据前台的nid动态的获取内容
                    dic = {'user': 'root2020', 'user_type1': 3, 'user_type2': 5}
                注意: 如果是多选的话,则只需要返回一个列表即可
                    dic = {'user': 'root2020', 'user_type1': 3, 'user_type2': 5, 'favor':[1,2,3,4]}
            '''
              dic = {'user': info.usename, 'user_type1': 3, 'user_type2': info.type_id}  # 根据前台的反馈来进行数据匹配
            obj = DBEditForm(dic)
            return render(request, 'dbEdit.html', {'obj': obj})
        else:
        obj = DBEditForm(request.POST, request.FILES)  # 注意别忘了参数,因为is_valid和clean都是POST请求的
            obj.is_valid()
            data = obj.clean()
            error_json = obj.errors.as_json()
            print("正确信息:", data)
            print("错误信息:", error_json)
            return render(request, 'dbEdit.html', {'obj': obj})

    app01/models.py

    from django.db import models
    # Create your models here.
    class DBModel(models.Model):
        type = models.CharField(max_length=22)  #  创建type字段且id是Django帮我们创建
    
    class UserInfo(models.Model):
        usename = models.CharField(max_length=22)
        # type在数据库内显示的值为: type_id
        type = models.ForeignKey("DBModel", on_delete=True)   # 设置外键,一对多,这里是多的一方

    templates/ dbEdit.html

    <!DOCTYPE html>
    <html lang="en">
    <head>    <meta charset="UTF-8">  </head>
    <body>
        {{ obj.user }}<br>
        {{ obj.user_type1 }}<br>
        {{ obj.user_type2 }}<br>
    </body>
    </html>

    初始化数据库:

    python manage.py makemigrations
    python manage.py migrate
    
    

    页面显示

    image

    数据库内容

    image

     

    【更多参考】http://www.cnblogs.com/wupeiqi/articles/6144178.html

  • 相关阅读:
    selenium2基本控件介绍及其代码
    selenium2元素定位Xpath和cssSelector
    Selenium2启动浏览器且加载插件
    bash之条件测试if/else
    bash脚本编写基础
    Android后台的linux一直保持唤醒状态,不进入睡眠
    Linux任务计划、周期性任务执行
    C#进阶系列——WebApi 跨域问题解决方案:CORS(转载)
    linq group by
    echart 分组属性
  • 原文地址:https://www.cnblogs.com/ftl1012/p/9405014.html
Copyright © 2011-2022 走看看