第24天卿捎,Django之ModelForm

一. 創(chuàng)建一個(gè)ModelForm

1.1 使用之前需要導(dǎo)入對(duì)應(yīng)app中的models和Django提交的ModelForm類

from django.forms import ModelForm
from app01.models import Host
from django.forms import widgets           #插件,接下來會(huì)用到
from django.core.exceptions import ValidationError         

1.2 創(chuàng)建一個(gè)類径密,并繼承ModelForm

class HostModelForm(ModelForm):             #新建1個(gè)類午阵,繼承ModelForm
    class Meta:                             #在內(nèi)部定義一個(gè)Meta類,注意這個(gè)類名是固定不變的
        model = Host                        #對(duì)應(yīng)models.py中哪個(gè)類(哪個(gè)表)
        fields = '__all__'                  #表示使用models.Host類中所有字段
        # fields = ('hostname','ip','port','dep')    #也可以這樣選擇指定字段

ModelForm常用的class Meta配置

class Meta:
        model = models.UserInfo            #結(jié)尾不用加逗號(hào)
        fields = '__all__'
        # fields =  ['username','email']
        # exclude = ['username']            # 除了 XX字段享扔,其他都使用
        labels = {                          # label 名稱
            'username': '用戶名',
            'email': '郵箱',
        }
        help_texts = {                     # 幫助信息
            'username': '...'
        }
        widgets = {
            'username': Fwidgets.Textarea(attrs={'class': 'c1'})
        }
        error_messages = {                       # 自定義錯(cuò)誤
            '__all__':{

            },
            'email': {
                'required': '郵箱不能為空',
                'invalid': '郵箱格式錯(cuò)誤..',
            }
        }
        field_classes = {                         #字段類型底桂,可以強(qiáng)制修改成其他類型
            # 'email': Ffields.URLField
        }

        # localized_fields=('ctime',)

二. ModelForm生成Html和數(shù)據(jù)驗(yàn)證

2.1 生成空表單

forms = HostModelForm()     # 生成空的表單

2.2 在表單中顯示初始數(shù)據(jù)

hostobj =models.Host.objects.get(id=1)
forms = HostModelForm(instance = hostobj)          # instance  對(duì)應(yīng)模型實(shí)例 

2.3 驗(yàn)證表單數(shù)據(jù)并保存

forms = HostModelForm(request.POST)
if forms.is_valid():              # 驗(yàn)證成功則保存modelsform
    forms.save()                  # 這一步會(huì)直接將數(shù)據(jù)保存至數(shù)據(jù)庫

注意:此時(shí),forms.save()不僅保存當(dāng)前對(duì)象實(shí)例伪很,還保存實(shí)例對(duì)應(yīng)跨表關(guān)系(外鍵戚啥、多對(duì)多等)

三. 前端頁面展示form表

在模版中展示指定字段

<form method="post" novalidate>
    {% csrf_token %}
    <p>{{ forms.hostname.label }}:&nbsp;{{ forms.hostname }}{{ forms.hostname.errors.0 }}</p>
    <p>{{ forms.ip.label }}:&nbsp;{{ forms.ip }}{{ forms.ip.errors.0 }}</p>
    <p>{{ forms.port.label }}:&nbsp;{{ forms.port }}{{ forms.port.errors.0 }}</p>
    <input type="submit" value="提交">
</form>

如果嫌上面這種方法麻煩,還可以在模版中循環(huán)forms實(shí)例锉试,以列出每個(gè)字段

<form method="post" novalidate>
    {% csrf_token %}
    {% for form in forms %}
       <p>{{ form.label }}:&nbsp;{{ form }}{{ form.errors.0 }}</p>
    {% endfor %}
    <input type="submit" value="提交">
</form>

四. 示例

4.1 在app中創(chuàng)建一個(gè)forms.py

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author : Cai Guangyin

from django.forms import ModelForm
from app01.models import Host
from django.forms import widgets
from django.core.exceptions import ValidationError


class HostModelForm(ModelForm):             #新建1個(gè)類猫十,繼承ModelForm
    class Meta:
        model = Host                        #對(duì)應(yīng)models.py中哪個(gè)類(哪個(gè)表)
        fields = '__all__'                  #表示使用models.Host類中所有字段
        # fields = ('hostname','ip','port','dep')    #也可以這樣選擇指定字段
        error_messages = {                  #自定義錯(cuò)誤提示信息
            'hostname':{
                'required':'用戶名不能為空'
            },
            'ip':{
                'required':'IP不能為空',
                'invalid':'IP地址格式錯(cuò)誤'
            },
            'port':{
                'required':'端口不能為空'
            },
            'dep': {
                'required': '部門不能為空'
            },
            'userinfo': {
                'required': '所屬用戶不能為空'
            },
        }
        labels = {                      #自定義label標(biāo)簽顯示的內(nèi)容
            'hostname':'主機(jī)名',
            'ip':'IP',
            'port':'端口',
            'dep':'部門',
            'userinfo':'所屬用戶'
        }
        widgets = {       # 自定義插件,注意必須加s,因?yàn)槭菑?fù)數(shù)呆盖,寫widget不起作用
            'hostname': widgets.TextInput(attrs={'class':'form-control'}),
            'ip': widgets.TextInput(attrs={'class':'form-control'}),
            'port': widgets.TextInput(attrs={'class':'form-control'}),
            'dep': widgets.Select(attrs={'class':'form-control'}),
            'userinfo': widgets.SelectMultiple(attrs={'class':'form-control'}),
        }

    def clean_port(self):      #也可以自定義鉤子函數(shù)對(duì)字段進(jìn)行驗(yàn)證
        value = self.cleaned_data['port']
        if int(value) > 65535:
            raise ValidationError('端口號(hào)不能大于65535')
        return value

4.2 views.py

from django.shortcuts import render
from .models import *
from .forms import HostModelForm
# Create your views here.

def index(request):
    forms = HostModelForm()            #創(chuàng)建空表單
    if request.method == 'POST':
        forms = HostModelForm(request.POST)     #提交數(shù)據(jù)
        if forms.is_valid():                    #驗(yàn)證數(shù)據(jù) 
            forms.save()
    return render(request,'index.html',locals())

def edit_host(request):
    host_obj = Host.objects.filter(pk=1).first()
    forms = HostModelForm(instance=host_obj)   #編輯時(shí)顯示默認(rèn)數(shù)據(jù)
    if request.method == 'POST':
        # host_obj = Host.objects.filter(pk=1).first()
        # forms = HostModelForm(request.POST)    #向modelform中傳遞數(shù)據(jù)
        forms = HostModelForm(data=request.POST,instance=host_obj)  #編輯保存時(shí)拖云,需要將data和instance都傳入
        if forms.is_valid():
            forms.save()
    return render(request,'edithost.html',locals())

注意:在修改表單(表單中有初始值),提交驗(yàn)證時(shí)应又,需要傳入datainstance兩個(gè)參數(shù)宙项,如:forms = HostModelForm(data=request.POST,instance=host_obj)

4.3 模版文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<form method="post" novalidate>
    {% csrf_token %}
    {% for form in forms %}
       <p>{{ form.label }}:&nbsp;{{ form }}{{ form.errors.0 }}</p>
    {% endfor %}
    <input type="submit" value="提交">
</form>

</body>
</html>
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市株扛,隨后出現(xiàn)的幾起案子尤筐,更是在濱河造成了極大的恐慌,老刑警劉巖洞就,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件盆繁,死亡現(xiàn)場離奇詭異,居然都是意外死亡旬蟋,警方通過查閱死者的電腦和手機(jī)油昂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人冕碟,你說我怎么就攤上這事拦惋。” “怎么了安寺?”我有些...
    開封第一講書人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵厕妖,是天一觀的道長。 經(jīng)常有香客問我我衬,道長叹放,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任挠羔,我火速辦了婚禮井仰,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘破加。我一直安慰自己俱恶,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開白布范舀。 她就那樣靜靜地躺著合是,像睡著了一般。 火紅的嫁衣襯著肌膚如雪锭环。 梳的紋絲不亂的頭發(fā)上聪全,一...
    開封第一講書人閱讀 51,365評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音辅辩,去河邊找鬼难礼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛玫锋,可吹牛的內(nèi)容都是我干的蛾茉。 我是一名探鬼主播,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼撩鹿,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼谦炬!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起节沦,我...
    開封第一講書人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤键思,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后甫贯,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體吼鳞,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年获搏,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡常熙,死狀恐怖纬乍,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情裸卫,我是刑警寧澤仿贬,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站墓贿,受9級(jí)特大地震影響茧泪,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜聋袋,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一队伟、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧幽勒,春花似錦嗜侮、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至咪惠,卻和暖如春击吱,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背遥昧。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來泰國打工覆醇, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人渠鸽。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓叫乌,卻偏偏與公主長得像,于是被迫代替她去往敵國和親徽缚。 傳聞我的和親對(duì)象是個(gè)殘疾皇子憨奸,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容