Python学习---Form拾遗180322

image

Form操作之错误信息操作

1. 用户发送请求过来

2. for 循环对字段进行正则表达式的验证  fields.clean(value)

3. 自定义clean_字段() 进行名字段值正确性的校验

4. 自定义clean()的内容校验,会进行异常信息的捕捉

5. post_clean()方法的校验,不允许抛出异常,self.add_error(进行校验)

注意  self.add_error(None, ValidatorError(‘’))   这里虽然写的是None,但实际上会转换为__all__

        Django内部会进行转换的:self.add_error(‘__all__’, ValidatorError(‘’))

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('fm/', views.fm),
]

views.py

from django.shortcuts import render, redirect, HttpResponse
from app01 import models,fields
class Fm(forms.Form):
    username = fields.CharField(max_length=32, label='用户名')
    email = fields.EmailField(label='邮箱')

    # 这里是对username字段的内容进行验证的
    def _clean_username(self):
        data = self.cleaned_data['username']
        if (data == 'root'):
            return data    # 验证通过,返回一个结果给forms.py中full_clean()方法的调用处
        else:
            from django.core.exceptions import  ValidationError
            # 这里的异常也是forms.py中full_clean()的异常捕获
            raise ValidationError("请使用root用户登录...")

    # 这里实际上是调用 _clean_form(self)里的clean()进行错误拓展
    def clean(self):
        data = self.cleaned_data['username']
        email = self.cleaned_data['email']
        if (data == 'root' and email == 'root@live.com'):
            pass  # 因为父级别的_post_clean也是什么都不操作
        else:
            from django.core.exceptions import ValidationError
            # 这里的异常是forms._clean_form()的异常捕获
            raise ValidationError("用户名或email错误...")
        return self.cleaned_data

    # _post_clean和_clean_form里面的clean()效果同,所以这里隐去
    # 这里是个_post_clean里面的Hook,里面的方法体为空
    # def _post_clean(self):
    #     data = self.cleaned_data['username']
    #     email = self.cleaned_data['email']
    #     if (data == 'root' and email == 'root@live.com'):
    #         pass    # 因为父级别的_post_clean也是什么都不操作
    #     else:
    #         from django.core.exceptions import ValidationError
    #         # 这里的异常是forms._clean_form()的异常捕获
    #         raise ValidationError("用户名或email错误...")

def fm(request):
    if request.method == "GET":
        obj = Fm()
        return render(request, 'fm.html', {"obj": obj})
    else:
        obj = Fm(request.POST)
        obj.is_valid()
        # data = obj.clean()   因为Fm()里面覆写了该方法,所以直接调用cleaned_data获取值即可
        data = obj.cleaned_data
        error = obj.errors
        print('错误信息',error)
        print('正确信息:',data)
        return render(request, 'fm.html', {"obj": obj})

templates/fm.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
</head>
<body>
    {#    模版语言一: 逐个输出内容#}
        <h5>模版语言,逐个输出</h5>
        {{ obj.username }}
        {{ obj.email }}
<hr>
    {# 模版语言二: 一次性输出全部内容,如果是as_p,则是在P标签内,as_ul是ul标签 #}
        <h5>模版语言,一次性配合lable标签输出全部字段</h5>
        {{ obj.as_p }}
        {{ obj.as_ul }}
        <table>{{ obj.as_table }}</table>
<hr>
        <form action="/fm/" method="post">
            {{ obj.as_p }}
            <input type="submit" value="提交"/>
        </form>
</body>
</html>

页面显示;

image

初始化数据库

python manage.py makemigrations
python manage.py migrate

Form操作之is_valid()源码解析

进入full_clean()方法

image

full_clean()方法:

image

_clean_fields()

image

image

add_error(name,e)

image

image

_clean_form():

image

_post_form()

image

Form操作之前台下拉框实时显示数据库内容

问题现象:无法获取数据库内最新的数据

imageimage

解决一: 调用父类的构造方法,每次调用函数之前重新获取数据

class Fm(forms.Form):
    username = fields.CharField(max_length=32, label='用户名')
    email = fields.EmailField(label='邮箱')
    user_type=fields.ChoiceField(choices=models.UT.objects.values_list('id', 'caption'))

    def __init__(self, *args, **kwargs):
        super(Fm, self).__init__(*args, **kwargs)
        self.fields['user_type'].widget.choices = models.UT.objects.all().values_list('id', 'caption')

image

image

最终显示内容:

image

 

附完整源码:

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('fm/', views.fm),
]

views.py

from django.shortcuts import render, redirect, HttpResponse
from app01 import models
class Fm(forms.Form):
    username = fields.CharField(max_length=32, label='用户名')
    email = fields.EmailField(label='邮箱')
    user_type=fields.ChoiceField(choices=models.UT.objects.values_list('id', 'caption'))
    # 方案一:
    def __init__(self, *args, **kwargs):
        super(Fm, self).__init__(*args, **kwargs)
        self.fields['user_type'].widget.choices = models.UT.objects.all().values_list('id', 'caption')
    # 方案二:
    from django.forms import models as filed_models
    # 这里的all()返回的是一个对象,前台页面显示的始终是object,但是看源码又有value值
    # 同时这里的limit_choices_to并无明显效果显示,在ModelForm里面效果显著    
user_type2 = filed_models.ModelChoiceField(queryset=models.UT.objects.all(),
                                               to_field_name='caption',
                                               limit_choices_to={'id':'(1,3)'},)
    # 多选框
    user_type3 = filed_models.ModelMultipleChoiceField(queryset=models.UT.objects.all(),
                                               to_field_name='caption',
                                               limit_choices_to={'id': '(1,3)'}, )

def fm(request):
    if request.method == "GET":
        obj = Fm()
        return render(request, 'fm.html', {"obj": obj})

models.py

from django.db import models
class U(models.Model):
    id = models.AutoField(primary_key=True)  # AutoField必须是主键,才能自定义该列
    name = models.CharField(max_length=32)
    email = models.CharField(max_length=32)
    userType = models.ForeignKey("UT", on_delete=True)  # 1对多[无法用自定义,有约束关系]

class UT(models.Model):
    caption = models.CharField(max_length=32)
    def __str__(self):
        return self.caption

templates/fm.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
</head>
<body>
    {#    模版语言一: 逐个输出内容#}
        <h5>模版语言,逐个输出</h5>
        {{ obj.username }}
        {{ obj.email }}
<hr>
    {# 模版语言二: 一次性输出全部内容,如果是as_p,则是在P标签内,as_ul是ul标签 #}
        <h5>模版语言,一次性配合lable标签输出全部字段</h5>
        {{ obj.as_p }}
        {{ obj.as_ul }}
        <table>{{ obj.as_table }}</table>
<hr>
        <form action="/fm/" method="post">
            {{ obj.as_p }}
            <input type="submit" value="提交"/>
        </form>
</body>
</html>

页面显示;

image

初始化数据库

python manage.py makemigrations
python manage.py migrate

 

Form操作更多参考 :http://www.cnblogs.com/wupeiqi/articles/6144178.html

posted @ 2018-08-04 11:52  小a玖拾柒  阅读(311)  评论(0编辑  收藏  举报