Django(七)表单与模型

    表单的作用是实现网页上的数据交互,用户在网站输入数据信息,提交到网站服务器进行处理。用户表单是web开发的一项基本操作,Django的表单功能有Form类实现,主要分为两种:django.forms.Form和django.forms.ModelForm。前者是一个基础的表单。后者是在前者的基础结果模型所生成的数据表单。


基础表单

    传统表单生成方式是在模板文件中编写HTML代码实现,在HTML语言中,表单由<form>标签实现。表单生成方式如下:

<!DOCTYPE html>

<html>

<body>

    <form action="" method="post">

        First name:<br>

        <input type="text" name="firstname" value="Mickey"><br>

        Last name:<br>

        <input type="text" name="lastname" value="Mouse">

        <input type="submit" value="Submit">

    </form>

</body>

</html>

一个完整的表单有4个主要组成部分:提交地址、请求方式、元素控件、提交按钮。说明如下:

1.提交地址用于设置用户提交的表单数据应由那个URL来接受和处理,控件<form>的属性action决定。当用户想服务器提交数据时,若属性action为空,则调教的数据应由当前的URL来接受和处理。否则网页会跳转到属性action所指向的URL地址。

2.请求方式用于设置表单的提交方式,通常是get请求或post请求,由控件<form>的属性method决定。

3.元素控件是提供用户输入数据信息的输入框。由HTML的<input>控件实现,其控件属性type用于设置输入框的类型,常用的输入框类型有文本框、下拉框、复选框

4.提交按钮提供用户提交数据到服务器,按钮也由HTML的<input>控件实现,但该按钮具有一定的特殊性,因此不归纳到元素空间的 范围内。


    在模板文件中,直接编写表单是一种较为简单的实现方式,如果过表单元素较多,会在无形之中增加模板的代码量,这样对日后的维护和更新带来不便。为了简化表单的实现过程和提高表单的灵活性,Django提供了完善的表单功能。

    在项目的index中添加空白文件form.py,改文件主要用于编写表单的实现功能。文件夹可自行命名:同事在文件夹templates中添加模板文件data_form.html,改文件用于将表单的数据显示到网页上。最后在文件form.py, views.py, data_form.html添加一下代码:

# form.py代码,定义ProductForm表单对象

from django import forms

from .models import *

class ProductForm(forms.Form):

    name = forms.CharField(max_length=20, label='名字',)

    weight = forms.CharField(max_length=50, label='重量')

    size = forms.CharField(max_length=50, label='尺寸')

    choices_list = [(i+1, v['type_name']) for i,v in enumerate(Type.objects.values('type_name'))]

    type = forms.ChoiceField(choices=choices_list, label='产品类型')

# views.py 代码 将表单 ProductForm实例化并将其传递到末班中生成网页内容

from django.shortcuts import render

from .form import *

def index(request):

    product = ProductForm()

    return render(request, 'data_form.html',locals())

# data_form.html代码, 将表单对象的内容显示在网页上

<!DOCTYPE html>

<html lang="en">

<head>

    <meta charset="UTF-8">

    <title>Title</title>

</head>

<body>

{% if product.errors %}

    <p> 数据出错啦,错误信息:{{ product.errors }}. </p>

    {% else %}

    <form action="" method="post">

        {% csrf_token %}

        <table> {{ product.as_table }} </table>

        <input type="submit" value="提交">

        {{ product.type.type }}

        </form>

        {% endif %}

</body>

</html>

    上述代码演示了Django内置表单功能的使用方法,主要由form.py,views.py,data_form.html共同实现,说明如下:

    1.在form.py中定义表单ProductForm,表单以类的形式表示,在表单中定义了不同类型的雷属性,这些属性在表单中称为表单字段,每个表单字段代表HTML里面的一个控件,这是表单的基本组成单位。

    2.在views.py中导入form.py所定义的ProductForm类,在视图函数index中对ProductForm实例化生成对象product,再讲对象product传递给模板data_form.html

    3.模板data_form.html将对象product以HTML的<table>的形式展示在网页上。


表单定义

    Django的表单功能主要是通过定义表单类,再由类的实例化生成HTML的表单元素控件,这样可以在模板中减少HTML的硬编码每个HTML的表单元素控件由表单字段来决定,代码如下:

# 表单类ProductForm的表单字段name

name = forms.CharField(max_leng=20, label='名称',)

# 表单字段name所生成的HTML元素控件

<tr>

<th><label for="id_name"> 名称:</label><th>

<td><input type="text" name="name" id="id_name" required maxlength="20"></td>

</tr>

    从表单字段转换HTML元素控件可以发现:

    1.字段那么的参数label将转化成HTML的标签<label>

    2.字段name的forms.CharField 类型转换成HTML的<input type="text"> 控件,标签<input>是一个输入框控件,type="text"代表当前输入框为文本输入框,参数type用于设置输入框的类型。

    3.字段那么的命名转换成<input>控件的参数name, 表单字段的参数max_length将转换成<input>控件的参数required maxlength.

除了上述表单字段外,Django还提供多种内置的表单字段,如需要了解可去官网查询相关资料。


模型与表单

    数据表单是将模型的字段转换成表单的字段,再从表单的字段生成HTML的元素控件,这是日常开发中常用的表单之一。接下来重点说明ModelForm实现表单数据与模型数据之间的交互开发。

    首先在文件form.py中定义表单ProductModelForm,该表单继承自父类forms.ModelForm。代码如下:

from django import forms

from .models import *

from django.core.exceptions import ValidationError

class ProductModelForm(forms.ModelForm):

    # 添加模型外的表单字段

    productId = forms.CharField(max_length=20, label='产品序号', initial='NO1')

    # 模型与表单设置

    class Meta:

        # 绑定模型

        model = Product

        # fields 属性是设置转换字段,'__all__'是将全部模型字段转换成表单字段

        # fields = '__all__'

        fields = ['name','weight','size','type']

        # exclude是禁止模型字段转换表单字段

        exclude = []

        # labels设置HTML元素控件的label标签

        abels = { 'name': '产品名称', 'weight': '重量', 'size': '尺寸', 'type': '产品类型' }

        # 定义widgets,设置表单字段的CSS样式

        widgets = { 'name': forms.widgets.TextInput(attrs={'class': 'c1'}), }

        # 定义字段的类型,一般情况下模型的字段会自动转换成表单字段

        field_classes = { 'name': forms.CharField }

        # 帮助提示信息 help_texts = { 'name': '' }

        # 自定义错误信息

        error_messages = {

                                        # __all__设置全部错误信息

                                        '__all__':{'required': '请输入内容', 'invalid': '请检查输入内容'},

                                        # 设置某个字段错误信息

                                        'weight': {'required': '请输入重量数值', 'invalid': '请检查数值是否正确'} }

# 自定义表单字段weight的数据清洗

def clean_weight(self):

    # 获取字段weight的值

    data = self.cleaned_data['weight']

    return data+'g'

    上述代码中,表单类ProdectModelForm可分为三大部分:添加模型外的表单字段、模型与表单设置和自定义表单字段weight的数据清洗函数,说明如下:

    1.添加模型外的表单字段是在模型已有的字段下添加额外的表单字段。

    2.模型与表单设置是将模型的字段转换成表单字段,由类meta的属性实现两者的字段转换。

    3.自定义表单字段weight的数据清洗函数只适用于字段weight的数据清洗。


类Meta的属性及说明

    模型字段转换成表单字段主要在类Meta中实现。

model:  必需属性,用于绑定Model对象。

fields:   必需属性,设置模型内那些字段转换成表单字段。属性值为'__all__'代表整个模型的字段,若设置一个或多个,使用列表或元组的数 据格式表示,列表或元组里的元素是模型的字段名。

exclude:  可选属性,与fields相反。

labels:  可选属性,设置表单字段里的参数label。属性值以字典表示,字典里ID键是模型的字段。

widgets:可选属性,设置表单字段的参数widget

field_classes:  可选属性,将模型的字段重新定义为表单字段类型,默认情况下,模型字段类型会自动转换为表单字段类型。

help_texts:  可选属性,设置表单字段里的参数help_text.

error_messages:  可选属性,设置表单字段里的参数error_messages.


重写初始化函数__init__()

class ProductModelForm(forms.ModelForm):

# 重写ProductModelForm类的初始函数__init__

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

        super(ProductModelForm, self).__init__(*args, **kwargs)

        # 设置下拉框的数据

        type_obj = Type.objects.values('type_name')

        choices_list = [(i + 1, v['type_name']) for i, v in enumerate(type_obj)]

        self.fields['type'].choices = choices_list

        # 初始化字段name

        self.fields['name'].initial = '我的手机'

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,591评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,448评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,823评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,204评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,228评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,190评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,078评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,923评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,334评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,550评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,727评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,428评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,022评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,672评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,826评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,734评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,619评论 2 354

推荐阅读更多精彩内容