django之form组件

一、验证功能

html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form id="fm" action="/f1.html/" method="POST">
        <p><input type="text" name="user">{{ obj.errors.user.0 }}</p>
        <p><input type="text" name="pwd">{{ obj.errors.pwd.0 }}</p>
        <p><input type="text" name="age">{{ obj.errors.age.0 }}</p>
        <p><input type="text" name="email">{{ obj.errors.email.0 }}</p>
        <input type="submit" value="提交" />
    </form>
    <script src="/static/jquery-3.1.1.js"></script>

</body>
</html>

views

from django.shortcuts import render
from django.shortcuts import HttpResponse,redirect

from django import forms
from django.forms import fields

class F1Form(forms.Form):
    user = fields.CharField(
        max_length=20,
        min_length=2,
        required=True,
        error_messages={'required':'用户名不能为空','max_length':'不能超过20个字','min_length':'不能小于2个字'}

    )
    pwd = fields.CharField(required=True,min_length=8)
    age = fields.IntegerField(
        required=True,
        error_messages={
            'required':'不能为空',
            'invalid':'格式错误'
        }
                              )
    email = fields.EmailField(
        required=True,
        min_length=8,
        error_messages={
            'invalid':'格式错误'
        }
    )

def f1(request):
    if request.method == 'GET':
        obj = F1Form()
        return  render(request,'f1.html',{'obj':obj})
    else:
        obj = F1Form(request.POST)
        if obj.is_valid():
            print('验证成功',obj.cleaned_data)
            return HttpResponse('ok')
        else:
            print('验证失败',obj.errors)
            return render(request,'f1.html',{'obj':obj})

 

二、生成html

 

html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form id="fm" action="/f1.html/" method="POST">
        <p>{{ obj.user }}{{ obj.errors.user.0 }}</p>
        <p>{{ obj.pwd }}{{ obj.errors.pwd.0 }}</p>
        <p>{{ obj.age }}{{ obj.errors.age.0 }}</p>
        <p>{{ obj.email }}{{ obj.errors.email.0 }}</p>
        <input type="submit" value="提交" />
    </form>
    <script src="/static/jquery-3.1.1.js"></script>

</body>
</html>

views

from django.shortcuts import render
from django.shortcuts import HttpResponse,redirect

from django import forms
from django.forms import fields

class F1Form(forms.Form):
    user = fields.CharField(
        max_length=20,
        min_length=2,
        required=True,
        error_messages={'required':'用户名不能为空','max_length':'不能超过20个字','min_length':'不能小于2个字'}

    )
    pwd = fields.CharField(required=True,min_length=8)
    age = fields.IntegerField(
        required=True,
        error_messages={
            'required':'不能为空',
            'invalid':'格式错误'
        }
                              )
    email = fields.EmailField(
        required=True,
        min_length=8,
        error_messages={
            'invalid':'格式错误'
        }
    )

def f1(request):
    if request.method == 'GET':
        obj = F1Form()   #自动生成html
        return  render(request,'f1.html',{'obj':obj})
    else:
        obj = F1Form(request.POST)
        if obj.is_valid():
            print('验证成功',obj.cleaned_data)
            return HttpResponse('ok')
        else:
            print('验证失败',obj.errors)
            return render(request,'f1.html',{'obj':obj})

 

三、简单应用

models

from django.db import models


class UserInfo (models.Model):
    username = models.CharField (max_length=30)
    email = models.EmailField (max_length=50)

url

from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^users/', views.users),
    url(r'^add_user/', views.add_user),
    url(r'^edit_user-(\d+)/', views.edit_user),
]

 

users.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<a href="/add_user/">添加</a>
    <ul>
        {% for row in data %}
            <li>{{ row.id }}--{{ row.username }}--{{ row.email }}<a href="/edit_user_{{ row.id }}">编辑</a></li>
        {% endfor %}
    </ul>

</body>
</html>

 

add_user.html

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

edit.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/edit_user_{{ nid }}/" method="post" novalidate>
    {% csrf_token %}
    <p>{{ obj.username }}{{ obj.errors.username.0 }}</p>
    <p>{{ obj.email }}{{ obj.errors.email.0 }}</p>
    <input type="submit">
</form>

</body>
</html>

df

from django import forms
from django.forms import fields

class UserForm(forms.Form):
    username = fields.CharField()
    email = fields.EmailField()

 

views

 

from django.shortcuts import render,redirect
from app01 import models
from app01.df import UserForm

def users(request):
    data = models.UserInfo.objects.all()

    return render(request,'users.html',{'data':data})

def add_user(request):
    if request.method == 'GET':
        obj = UserForm()
        return render(request,'add_user.html',{'obj':obj})
    else:
        obj = UserForm(request.POST)
        if obj.is_valid():
            models.UserInfo.objects.create(**obj.cleaned_data)
            return redirect('/users/')
        else:
            return render(request,'add_user.html',{'obj':obj})

def edit_user(request,nid):
    if request.method =='GET':
        data = models.UserInfo.objects.filter(id=nid).first()
        obj =UserForm({'username':data.username,'email':data.email})
        return render(request,'edit_user.html',{'obj':obj,'nid':nid})
    else:
        obj =UserForm(request.POST)
        if obj.is_valid():
            models.UserInfo.objects.filter(id=nid).update(**obj.cleaned_data)
            return redirect('/users/')
        else:
            return render(request,'edit_user.html',{'obj':obj,'nid':nid})

四、组件字段

字段主要由正则匹配和插件构成

Field参数

required=True, widget=None, label=None, initial=None,help_text='', error_messages=None, show_hidden_initial=False,validators=(), localize=False, disabled=False, label_suffix=None

 

(1)CharField参数

具备Field参数

max_length=None, min_length=None, strip=True, empty_value=''
from django.shortcuts import render
from django import forms
from django.forms import fields,widgets
class TestForm(forms.Form):
    user = fields.CharField(
        required=True,   #是否必填
        max_length=12,    #最大长度
        min_length=3,     #最小长度
        error_messages={}, #错误提示
        # widgets = widgets.Select() ,#定制HTML插件
        label='用户名',
        initial='请输入用户名',   #初始化
        help_text='无用参数',
        show_hidden_initial=False,  #输入框不可修改
        disabled=True,
        label_suffix='-->'
    )
    age = fields.IntegerField()
    email = fields.EmailField()

def test(request):
    if request.method == 'GET':
        obj = TestForm()
        return render(request,'test.html',{'obj':obj})
    else:
        obj = TestForm (request.POST, request.FILES)
        obj.is_valid ()
        print (obj.cleaned_data)
        return render (request, 'test.html', {'obj': obj})

html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<table>
    {{ obj.as_table }}

</table>
<ul>
    {{ obj.as_ul }}
</ul>
{{ obj.as_p }}
</body>
</html>

显示

(2)IntegerField

具备Field参数

max_value=None, min_value=None

(3)其他

Field
    required=True,               是否允许为空
    widget=None,                 HTML插件
    label=None,                  用于生成Label标签或显示内容
    initial=None,                初始值
    help_text='',                帮助信息(在标签旁边显示)
    error_messages=None,         错误信息 {'required': '不能为空', 'invalid': '格式错误'}
    show_hidden_initial=False,   是否在当前插件后面再加一个隐藏的且具有默认值的插件(可用于检验两次输入是否一直)
    validators=[],               自定义验证规则
    localize=False,              是否支持本地化
    disabled=False,              是否可以编辑
    label_suffix=None            Label内容后缀
 
 
CharField(Field)
    max_length=None,             最大长度
    min_length=None,             最小长度
    strip=True                   是否移除用户输入空白
 
IntegerField(Field)
    max_value=None,              最大值
    min_value=None,              最小值
 
FloatField(IntegerField)
    ...
 
DecimalField(IntegerField)
    max_value=None,              最大值
    min_value=None,              最小值
    max_digits=None,             总长度
    decimal_places=None,         小数位长度
 
BaseTemporalField(Field)
    input_formats=None          时间格式化   
 
DateField(BaseTemporalField)    格式:2015-09-01
TimeField(BaseTemporalField)    格式:11:12
DateTimeField(BaseTemporalField)格式:2015-09-01 11:12
 
DurationField(Field)            时间间隔:%d %H:%M:%S.%f
    ...
 
RegexField(CharField)
    regex,                      自定制正则表达式
    max_length=None,            最大长度
    min_length=None,            最小长度
    error_message=None,         忽略,错误信息使用 error_messages={'invalid': '...'}
 
EmailField(CharField)      
    ...
 
FileField(Field)
    allow_empty_file=False     是否允许空文件
 
ImageField(FileField)      
    ...
    注:需要PIL模块,pip3 install Pillow
    以上两个字典使用时,需要注意两点:
        - form表单中 enctype="multipart/form-data"
        - view函数中 obj = MyForm(request.POST, request.FILES)
 
URLField(Field)
    ...
 
 
BooleanField(Field)  
    ...
 
NullBooleanField(BooleanField)
    ...
 
ChoiceField(Field)
    ...
    choices=(),                选项,如:choices = ((0,'上海'),(1,'北京'),)
    required=True,             是否必填
    widget=None,               插件,默认select插件
    label=None,                Label内容
    initial=None,              初始值
    help_text='',              帮助提示
 
 
ModelChoiceField(ChoiceField)
    ...                        django.forms.models.ModelChoiceField
    queryset,                  # 查询数据库中的数据
    empty_label="---------",   # 默认空显示内容
    to_field_name=None,        # HTML中value的值对应的字段
    limit_choices_to=None      # ModelForm中对queryset二次筛选
     
ModelMultipleChoiceField(ModelChoiceField)
    ...                        django.forms.models.ModelMultipleChoiceField
 
 
     
TypedChoiceField(ChoiceField)
    coerce = lambda val: val   对选中的值进行一次转换
    empty_value= ''            空值的默认值
 
MultipleChoiceField(ChoiceField)
    ...
 
TypedMultipleChoiceField(MultipleChoiceField)
    coerce = lambda val: val   对选中的每一个值进行一次转换
    empty_value= ''            空值的默认值
 
ComboField(Field)
    fields=()                  使用多个验证,如下:即验证最大长度20,又验证邮箱格式
                               fields.ComboField(fields=[fields.CharField(max_length=20), fields.EmailField(),])
 
MultiValueField(Field)
    PS: 抽象类,子类中可以实现聚合多个字典去匹配一个值,要配合MultiWidget使用
 
SplitDateTimeField(MultiValueField)
    input_date_formats=None,   格式列表:['%Y--%m--%d', '%m%d/%Y', '%m/%d/%y']
    input_time_formats=None    格式列表:['%H:%M:%S', '%H:%M:%S.%f', '%H:%M']
 
FilePathField(ChoiceField)     文件选项,目录下文件显示在页面中
    path,                      文件夹路径
    match=None,                正则匹配
    recursive=False,           递归下面的文件夹
    allow_files=True,          允许文件
    allow_folders=False,       允许文件夹
    required=True,
    widget=None,
    label=None,
    initial=None,
    help_text=''
 
GenericIPAddressField
    protocol='both',           both,ipv4,ipv6支持的IP格式
    unpack_ipv4=False          解析ipv4地址,如果是::ffff:192.0.2.1时候,可解析为192.0.2.1, PS:protocol必须为both才能启用
 
SlugField(CharField)           数字,字母,下划线,减号(连字符)
    ...
 
UUIDField(CharField)           uuid类型

 

比较常用:

        ChoiceField 
        MultipleChoiceField
        CharField
        IntegerField
        DecimalField
        DateField
        DateTimeField
        EmailField
        GenericIPAddressField
        FileField
        
        RegexField

五、字段插件

TextInput(Input)
NumberInput(TextInput)
EmailInput(TextInput)
URLInput(TextInput)
PasswordInput(TextInput)
HiddenInput(TextInput)
Textarea(Widget)
DateInput(DateTimeBaseInput)
DateTimeInput(DateTimeBaseInput)
TimeInput(DateTimeBaseInput)
CheckboxInput
Select
NullBooleanSelect
SelectMultiple
RadioSelect
CheckboxSelectMultiple
FileInput
ClearableFileInput
MultipleHiddenInput
SplitDateTimeWidget
SplitHiddenDateTimeWidget
SelectDateWidget

常用插件

# 单radio,值为字符串
# user = fields.CharField(
#     initial=2,
#     widget=widgets.RadioSelect(choices=((1,'上海'),(2,'北京'),))
# )
 
# 单radio,值为字符串
# user = fields.ChoiceField(
#     choices=((1, '上海'), (2, '北京'),),
#     initial=2,
#     widget=widgets.RadioSelect
# )
 
# 单select,值为字符串
# user = fields.CharField(
#     initial=2,
#     widget=widgets.Select(choices=((1,'上海'),(2,'北京'),))
# )
 
# 单select,值为字符串
# user = fields.ChoiceField(
#     choices=((1, '上海'), (2, '北京'),),
#     initial=2,
#     widget=widgets.Select
# )
 
# 多选select,值为列表
# user = fields.MultipleChoiceField(
#     choices=((1,'上海'),(2,'北京'),),
#     initial=[1,],
#     widget=widgets.SelectMultiple
# )
 
 
# 单checkbox
# user = fields.CharField(
#     widget=widgets.CheckboxInput()
# )
 
 
# 多选checkbox,值为列表
# user = fields.MultipleChoiceField(
#     initial=[2, ],
#     choices=((1, '上海'), (2, '北京'),),
#     widget=widgets.CheckboxSelectMultiple
# )

 

 choices选项从数据库中自动更新

方式一

from django.forms import Form
from django.forms import widgets
from django.forms import fields


class MyForm(Form):

    user = fields.ChoiceField(
        # choices=((1, '上海'), (2, '北京'),),
        initial=2,
        widget=widgets.Select
    )

    def __init__(self, *args, **kwargs):
        # 拷贝所有的静态字段,复制给self.fields
        super(MyForm,self).__init__(*args, **kwargs)
        # self.fields['user'].widget.choices = ((1, '上海'), (2, '北京'),)
        # 或
        self.fields['user'].widget.choices = models.Classes.objects.all().value_list('id','caption')

 

方式二

rom django import forms
from django.forms import fields
from django.forms import widgets
from django.forms import models as form_model
from django.core.exceptions import ValidationError
from django.core.validators import RegexValidator
 
class FInfo(forms.Form):
    authors = form_model.ModelMultipleChoiceField(queryset=models.NNewType.objects.all())
    # authors = form_model.ModelChoiceField(queryset=models.NNewType.objects.all())

 

ajax提交后只能接受后端字符串,不会接受后端的跳转,也就只能在前端设置跳转。所以ajax提交错误信息要自己展示,跳转要自己跳转。

views

def ajax(request):
    if request.method == 'GET':
        obj = AjaxForm()
        return render(request,'ajax.html',{'obj':obj})
    else:
        ret = {'status':'no','message':None}
        import json
        obj = AjaxForm(request.POST)
        if obj.is_valid():
            

            ret['status'] = 'yes'
            return HttpResponse(json.dumps(ret))
        else:
            # print(type(obj.errors))
            # print(obj.errors)
            from django.forms.utils import ErrorDict
            # print(obj.errors.as_ul())
            # print(obj.errors.as_json())
            # print(obj.errors.as_data())



            ret['message'] = obj.errors
            # 错误信息显示在页面上
            return HttpResponse(json.dumps(ret))

html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form id="fm" method="POST" action="/ajax/">
        {% csrf_token %}
        {{ obj.as_p }}
        <input type="button" value="Ajax提交" id="btn" />
    </form>
    <script src="/static/jquery-3.1.1.js"></script>
    <script>
        $(function () {
            $('#btn').click(function () {
                $.ajax({
                    url: '/ajax/',
                    type: 'POST',
                    data: $('#fm').serialize(),
                    dataType: 'JSON',
                    success:function (arg) {

                        // arg: 状态,错误信息
                        if (arg.status == 'yes'){
                            window.location.href = "http://www.baidu.com"
                        }
                        console.log(arg);
                    }
                })


            })


        })
    </script>
</body>
</html>

六、简单扩展

1,插件扩展

自定制验证规则

利用Form组件自带的正则扩展:
            a. 方式一
                from django.forms import Form
                from django.forms import widgets
                from django.forms import fields
                from django.core.validators import RegexValidator
                 
                class MyForm(Form):
                        user = fields.CharField(
                        error_messages={'invalid': '...'},
                        validators=[RegexValidator(r'^[0-9]+$', '请输入数字'), RegexValidator(r'^159[0-9]+$', '数字必须以159开头')],
                    )
            b. 方式二
                from django.forms import Form
                from django.forms import widgets
                from django.forms import fields
                from django.core.validators import RegexValidator
                 
                class MyForm(Form):
                user = fields.RegexField(r'^[0-9]+$',error_messages={'invalid': '...'})

 2.基于源码流程

验证数据库中是否存在同名用户

 
        a. 单字段
            from django.core.exceptions import NON_FIELD_ERRORS, ValidationError
            class AjaxForm(forms.Form):
                username = fields.CharField()
                user_id = fields.IntegerField(
                    widget=widgets.Select(choices=[(0,'alex'),(1,'BOB'),(2,'ALICE'),])
                )
            # 自定义方法 clean_字段名
            # 必须返回值self.cleaned_data['username']
            # 如果出错:raise ValidationError('用户名已存在')
            def clean_username(self):
                v = self.cleaned_data['username']
                if models.UserInfo.objects.filter(username=v).count():
                    # 整体错了
                    # 自己详细错误信息
                    raise ValidationError('用户名已存在')
                return v
            def clean_user_id(self):
                return self.cleaned_data['user_id']

        b. 整体错误验证
            class AjaxForm(forms.Form):
                username = fields.CharField()
                user_id = fields.IntegerField(
                    widget=widgets.Select(choices=[(0,'alex'),(1,'BOB'),(2,'ALICE'),])
                )
                # 自定义方法 clean_字段名
                # 必须返回值self.cleaned_data['username']
                # 如果出错:raise ValidationError('用户名已存在')
                def clean_username(self):
                    v = self.cleaned_data['username']
                    if models.UserInfo.objects.filter(username=v).count():
                        # 整体错了
                        # 自己详细错误信息
                        raise ValidationError('用户名已存在')
                    return v
                def clean_user_id(self):
                    return self.cleaned_data['user_id']

                def clean(self):
                    value_dict = self.cleaned_data
                    v1 = value_dict.get('username')
                    v2 = value_dict.get('user_id')
                    if v1 == 'root' and v2==1:
                        raise ValidationError('整体错误信息')
                    return self.cleaned_data
                    
                    
        PS: _post_clean
                

 

七、序列化

from django.shortcuts import render
from django.shortcuts import HttpResponse
from app01 import models
import json
def xuliehua(request):

    return render(request,'xuliehua.html')

"""
def get_data(request):
    user_list = models.UserInfo.objects.all()
    return render(request,'get_data.html',{'user_list':user_list})
"""
def get_data(request):
    from django.core import serializers

    ret = {'status':True,'data':None}
    try:
        # user_list = models.UserInfo.objects.all()
        # QuerySet【obj,obj,obj】
        # ret['data'] = serializers.serialize("json",user_list)
        # // var
        # v = JSON.parse(arg.data);
        # // console.log(v);

        # user_list = models.UserInfo.objects.all().values('id','username')
        # ret['data'] = list(user_list)
        # console.log(arg.data);

        # user_list = models.UserInfo.objects.all().values_list('id', 'username')
        # ret['data'] = list(user_list)
        # console.log(arg.data);
        pass
    except Exception as e:
        ret['status'] = False
    result = json.dumps(ret)
    return HttpResponse(result)

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>用户列表</h1>
    <table id="tb">

    </table>
    <script src="/static/jquery-3.1.1.js"></script>
    <script>
        $(function () {
            initData();
        });
        function initData() {
            $.ajax({
                url :'/get_data/',
                type:'GET',
                dataType:'JSON',
                success:function (arg) {
                    //$('#tb').append(arg);
                    if(arg.status){
                        console.log(arg.data);
                        //var v = JSON.parse(arg.data);
                        //console.log(v);
                    }
                }
            })
        }
    </script>
</body>
</html>

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用Bootstrap样式来美化Django Form组件。 首先,在Django项目中安装Bootstrap,可以通过pip命令安装: ``` pip install django-bootstrap4 ``` 然后,在Django项目的settings.py文件中添加以下内容: ``` INSTALLED_APPS = [ # ... 'bootstrap4', # ... ] # 设置Bootstrap版本 BOOTSTRAP4 = { 'include_jquery': True, 'jquery_url': '//cdn.bootcss.com/jquery/3.3.1/jquery.min.js', 'base_url': '//cdn.bootcss.com/bootstrap/4.1.3/', } ``` 接着,在Django Form组件中使用Bootstrap样式: ```python from django import forms from django.utils.translation import gettext_lazy as _ class ContactForm(forms.Form): name = forms.CharField( label=_("Your Name"), max_length=100, widget=forms.TextInput(attrs={'class': 'form-control'}), ) email = forms.EmailField( label=_("Your Email"), widget=forms.EmailInput(attrs={'class': 'form-control'}), ) message = forms.CharField( label=_("Message"), widget=forms.Textarea(attrs={'class': 'form-control'}), ) ``` 在这个例子中,我们在每个字段的widget参数中添加了class属性,这个class属性的值为form-control,这样就可以使用Bootstrap样式来美化表单组件。 最后,在HTML模板中使用Bootstrap样式: ```html {% extends "base.html" %} {% block content %} <div class="container"> <form method="post"> {% csrf_token %} {{ form.as_p }} <button type="submit" class="btn btn-primary">Submit</button> </form> </div> {% endblock %} ``` 在这个例子中,我们使用了Bootstrap的container类和btn类来美化HTML模板。然后使用form.as_p来渲染表单组件,这个方法会把每个表单组件渲染成一个p标签,每个p标签中包含一个label标签和一个input标签,这样我们就可以使用Bootstrap样式来美化整个表单了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值