Python之路【第二十一篇】:Django之Form组件

Django之Form组件

Django的Form主要具有一下几大功能:

  • 生成HTML标签
  • 验证用户数据(显示错误信息)
  • HTML Form提交保留上次提交数据
  • 初始化页面显示内容

小试牛刀

1、创建Form类


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

from django.forms import Form

from django.forms import widgets

from django.forms import fields

class MyForm(Form):

    user = fields.CharField(

        widget=widgets.TextInput(attrs={‘id‘‘i1‘‘class‘‘c1‘})

    )

    gender = fields.ChoiceField(

        choices=((1‘男‘), (2‘女‘),),

        initial=2,

        widget=widgets.RadioSelect

    )

    city = fields.CharField(

        initial=2,

        widget=widgets.Select(choices=((1,‘上海‘),(2,‘北京‘),))

    )

    pwd = fields.CharField(

        widget=widgets.PasswordInput(attrs={‘class‘‘c1‘}, render_value=True)

    )

2、View函数处理


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

from django.shortcuts import render, redirect

from .forms import MyForm

def index(request):

    if request.method == "GET":

        obj = MyForm()

        return render(request, ‘index.html‘, {‘form‘: obj})

    elif request.method == "POST":

        obj = MyForm(request.POST, request.FILES)

        if obj.is_valid():

            values = obj.clean()

            print(values)

        else:

            errors = obj.errors

            print(errors)

        return render(request, ‘index.html‘, {‘form‘: obj})

    else:

        return redirect(‘http://www.google.com‘)

3、生成HTML


1

2

3

4

5

6

7

<form action="/" method="POST" enctype="multipart/form-data">

    <p>{{ form.user }} {{ form.user.errors }}</p>

    <p>{{ form.gender }} {{ form.gender.errors }}</p>

    <p>{{ form.city }} {{ form.city.errors }}</p>

    <p>{{ form.pwd }} {{ form.pwd.errors }}</p>

    <input type="submit"/>

</form>

    <form method="POST" enctype="multipart/form-data">
        {% csrf_token %}

            {{ form.xxoo.label }}
            {{ form.xxoo.id_for_label }}
            {{ form.xxoo.label_tag }}
            {{ form.xxoo.errors }}
            <p>{{ form.user }} {{ form.user.errors }}</p>
            <input type="submit" />
    </form>

Form类

创建Form类时,主要涉及到 【字段】 和 【插件】,字段用于对用户请求数据的验证,插件用于自动生成HTML;

1、Django内置字段如下:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

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)            时间间隔:%%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=‘‘,              帮助提示

        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类型

            ...

注:UUID是根据MAC以及当前时间等创建的不重复的随机字符串

   >>> import uuid

    # make a UUID based on the host ID and current time
    >>> uuid.uuid1()    # doctest: +SKIP
    UUID(‘a8098c1a-f86e-11da-bd1a-00112444be1e‘)

    # make a UUID using an MD5 hash of a namespace UUID and a name
    >>> uuid.uuid3(uuid.NAMESPACE_DNS, ‘python.org‘)
    UUID(‘6fa459ea-ee8a-3ca4-894e-db77e160355e‘)

    # make a random UUID
    >>> uuid.uuid4()    # doctest: +SKIP
    UUID(‘16fd2706-8baf-433b-82eb-8c7fada847da‘)

    # make a UUID using a SHA-1 hash of a namespace UUID and a name
    >>> uuid.uuid5(uuid.NAMESPACE_DNS, ‘python.org‘)
    UUID(‘886313e1-3b8a-5372-9b90-0c9aee199e5d‘)

    # make a UUID from a string of hex digits (braces and hyphens ignored)
    >>> x = uuid.UUID(‘{00010203-0405-0607-0809-0a0b0c0d0e0f}‘)

    # convert a UUID to a string of hex digits in standard form
    >>> str(x)
    ‘00010203-0405-0607-0809-0a0b0c0d0e0f‘

    # get the raw 16 bytes of the UUID
    >>> x.bytes
    b‘\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f‘

    # make a UUID from a 16-byte string
    >>> uuid.UUID(bytes=x.bytes)
    UUID(‘00010203-0405-0607-0809-0a0b0c0d0e0f‘)

2、Django内置插件:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

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

常用选择插件


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

# 单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的选项可以从数据库中获取,但是由于是静态字段 ***获取的值无法实时更新***,那么需要自定义构造方法从而达到此目的。

方式一:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

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.ChoiceField(

        # choices=((1, ‘上海‘), (2, ‘北京‘),),

        initial=2,

        widget=widgets.Select

    )

    def __init__(self*args, **kwargs):

        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‘)

方式二:

使用django提供的ModelChoiceField和ModelMultipleChoiceField字段来实现


1

2

3

4

5

6

7

8

9

10

from 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())

自定义验证规则

方式一:


1

2

3

4

5

6

7

8

9

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(

        validators=[RegexValidator(r‘^[0-9]+$‘‘请输入数字‘), RegexValidator(r‘^159[0-9]+$‘‘数字必须以159开头‘)],

    )

方式二:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

import re

from django.forms import Form

from django.forms import widgets

from django.forms import fields

from django.core.exceptions import ValidationError

# 自定义验证规则

def mobile_validate(value):

    mobile_re = re.compile(r‘^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$‘)

    if not mobile_re.match(value):

        raise ValidationError(‘手机号码格式错误‘)

class PublishForm(Form):

    title = fields.CharField(max_length=20,

                            min_length=5,

                            error_messages={‘required‘‘标题不能为空‘,

                                            ‘min_length‘‘标题最少为5个字符‘,

                                            ‘max_length‘‘标题最多为20个字符‘},

                            widget=widgets.TextInput(attrs={‘class‘"form-control",

                                                          ‘placeholder‘‘标题5-20个字符‘}))

    # 使用自定义验证规则

    phone = fields.CharField(validators=[mobile_validate, ],

                            error_messages={‘required‘‘手机不能为空‘},

                            widget=widgets.TextInput(attrs={‘class‘"form-control",

                                                          ‘placeholder‘: u‘手机号码‘}))

    email = fields.EmailField(required=False,

                            error_messages={‘required‘: u‘邮箱不能为空‘,‘invalid‘: u‘邮箱格式错误‘},

                            widget=widgets.TextInput(attrs={‘class‘"form-control"‘placeholder‘: u‘邮箱‘}))

方法三:自定义方法


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

from django import forms

    from django.forms import fields

    from django.forms import widgets

    from django.core.exceptions import ValidationError

    from django.core.validators import RegexValidator

    class FInfo(forms.Form):

        username = fields.CharField(max_length=5,

                                    validators=[RegexValidator(r‘^[0-9]+$‘‘Enter a valid extension.‘‘invalid‘)], )

        email = fields.EmailField()

        def clean_username(self):

            """

            Form中字段中定义的格式匹配完之后,执行此方法进行验证

            :return:

            """

            value = self.cleaned_data[‘username‘]

            if "666" in value:

                raise ValidationError(‘666已经被玩烂了...‘‘invalid‘)

            return value

方式四:同时生成多个标签进行验证


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

from django.forms import Form

from django.forms import widgets

from django.forms import fields

from django.core.validators import RegexValidator

############## 自定义字段 ##############

class PhoneField(fields.MultiValueField):

    def __init__(self*args, **kwargs):

        # Define one message for all fields.

        error_messages = {

            ‘incomplete‘‘Enter a country calling code and a phone number.‘,

        }

        # Or define a different message for each field.

        = (

            fields.CharField(

                error_messages={‘incomplete‘‘Enter a country calling code.‘},

                validators=[

                    RegexValidator(r‘^[0-9]+$‘‘Enter a valid country calling code.‘),

                ],

            ),

            fields.CharField(

                error_messages={‘incomplete‘‘Enter a phone number.‘},

                validators=[RegexValidator(r‘^[0-9]+$‘‘Enter a valid phone number.‘)],

            ),

            fields.CharField(

                validators=[RegexValidator(r‘^[0-9]+$‘‘Enter a valid extension.‘)],

                required=False,

            ),

        )

        super(PhoneField, self).__init__(error_messages=error_messages, fields=f, require_all_fields=False*args,

                                         **kwargs)

    def compress(self, data_list):

        """

        当用户验证都通过后,该值返回给用户

        :param data_list:

        :return:

        """

        return data_list

############## 自定义插件 ##############

class SplitPhoneWidget(widgets.MultiWidget):

    def __init__(self):

        ws = (

            widgets.TextInput(),

            widgets.TextInput(),

            widgets.TextInput(),

        )

        super(SplitPhoneWidget, self).__init__(ws)

    def decompress(self, value):

        """

        处理初始值,当初始值initial不是列表时,调用该方法

        :param value:

        :return:

        """

        if value:

            return value.split(‘,‘)

        return [NoneNoneNone]

初始化数据

在Web应用程序中开发编写功能时,时常用到获取数据库中的数据并将值初始化在HTML中的标签上。

1、Form


1

2

3

4

5

6

7

8

9

10

11

12

13

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()

    city = fields.ChoiceField(

        choices=((1‘上海‘), (2‘北京‘),),

        widget=widgets.Select

    )

2、Views


1

2

3

4

5

6

7

8

9

10

11

12

13

14

from django.shortcuts import render, redirect

from .forms import MyForm

def index(request):

    if request.method == "GET":

        values = {‘user‘‘root‘‘city‘2}

        obj = MyForm(values)

        return render(request, ‘index.html‘, {‘form‘: obj})

    elif request.method == "POST":

        return redirect(‘http://www.google.com‘)

    else:

        return redirect(‘http://www.google.com‘)

3、HTML


1

2

3

4

5

6

7

<form method="POST" enctype="multipart/form-data">

    {% csrf_token %}

    <p>{{ form.user }} {{ form.user.errors }}</p>

    <p>{{ form.city }} {{ form.city.errors }}</p>

    <input type="submit"/>

</form>

时间: 2024-08-05 11:15:02

Python之路【第二十一篇】:Django之Form组件的相关文章

Python开发【第二十一篇】:Web框架之Django【基础】

Python开发[第二十一篇]:Web框架之Django[基础] 猛击这里:http://www.cnblogs.com/wupeiqi/articles/5237704.html Python之路[第十六篇]:Django[基础篇] Python的WEB框架有Django.Tornado.Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了ORM.模型绑定.模板引擎.缓存.Session等诸多功能. 基本配置 一.创建django程序 终端命令:django-a

六十一、Django之form组件

一.form组件 1.校验数据 # 第一步需要一个form类 from django import forms class MyForm(forms.Form): name = forms.CharField(max_length=6) password = forms.CharField(max_length=8,min_length=3) email = forms.EmailField(required=True) #第二步实例化form对象 form_obj = MyForm({'nam

Python之路(第二十篇) subprocess模块

一.subprocess模块 subprocess英文意思:子进程 那什么是进程呢? (一)关于进程的相关理论基础知识 进程是对正在运行程序的一个抽象,进程的概念起源于操作系统,是操作系统最核心的概念,操作系统的其他所有内容都是围绕进程的概念展开的. 所以想要真正了解进程,必须事先了解操作系统. 程序员无法把所有的硬件操作细节都了解到,管理这些硬件并且加以优化使用是非常繁琐的工作,这个繁琐的工作就是操作系统来干的,有了他,程序员就从这些繁琐的工作中解脱了出来,只需要考虑自己的应用软件的编写就可以

Python之路(第二十七篇) 面向对象进阶:内置方法、描述符

一.__call__ 对象后面加括号,触发执行类下面的__call__方法. 创建对象时,对象 = 类名() :而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()() class Foo: ? def __call__(self, *args, **kwargs): print("我执行啦") ? f = Foo() f() #对象加括号调用执行类下的__call__方法 #输出结果 我执行啦 二.__next__和__iter__实现迭代器协议 迭

Python之路【第九篇】:Python操作 RabbitMQ、Redis、Memcache、SQLAlchemy

Python之路[第九篇]:Python操作 RabbitMQ.Redis.Memcache.SQLAlchemy Memcached Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态.数据库驱动网站的速度.Memcached基于一个存储键/值对的hashmap.其守护进程(daemon )是用C写的,但是客户端可以用任何语言来编写,并通过memcached协议与守护进程通信. Memc

Python开发【第二十篇】:缓存

Python开发[第二十篇]:缓存redis&Memcache 点击这里 Python之路[第九篇]:Python操作 RabbitMQ.Redis.Memcache.SQLAlchemy Memcached Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态.数据库驱动网站的速度.Memcached基于一个存储键/值对的hashmap.其守护进程(daemon )是用C写的,但是客户端可

七日Python之路--第十一天

(一)关于模板,Template 可以在项目根目录下的settings.py 配置文件中,声明 import os BASE_DIR = os.path.dirname(os.path.dirname(__file__)) TEMPLATE_DIRS = os.path.join(BASE_DIR, 'templates') 这样模板的默认搜索就是在根目录的'templates'文件下进行寻找. 但是,感觉还是不声明,直接使用默认的搜索路径比较好.当不进行声明时,默认搜索路径是相应的app应用目

七日Python之路--第十二天(Django Web 开发指南)

<Django Web 开发指南>.貌似使用Django1.0版本,基本内容差不多,细读无妨.地址:http://www.jb51.net/books/76079.html (一)第一部分 入门 (1)内置数字工厂函数 int(12.34)会创建一个新的值为12的整数对象,而float(12)则会返回12.0. (2)其他序列操作符 连接(+),复制(*),以及检查是否是成员(in, not in) '**'.join('**')   或  '***%s***%d' % (str, int)

Python之路【第九篇】:Python基础(26)——socket server

socketserver Python之路[第九篇]:Python基础(25)socket模块是单进程的,只能接受一个客户端的连接和请求,只有当该客户端断开的之后才能再接受来自其他客户端的连接和请求.当然我 们也可以通过python的多线程等模块自己写一个可以同时接收多个客户端连接和请求的socket.但是这完全没有必要,因为python标准库已经为 我们内置了一个多线程的socket模块socketserver,我们直接调用就可以了,完全没有必要重复造轮子. 我们只需简单改造一下之前的sock