欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

在Django同1個頁面中的多表單處理詳解

 更新時間:2017年01月25日 11:17:22   投稿:daisy  
這篇文章主要給大家介紹了在Django同1個頁面中的多表單處理的相關(guān)資料,文章先給大家介紹了如何快速上手Django實現(xiàn)項目的方法,方便讓大家理解和學習,需要的朋友可以參考借鑒,下面來一起看看吧。

快速上手Django實現(xiàn)項目

近期公司在做1個海淘的項目,APP為pylot。由于時間比較趕,加上隔壁那哥們不在,只能自己挑大梁了。結(jié)果,當項目做出來之后,被領(lǐng)導狠狠的批了一頓,說怎么用django寫,你能解決Django的內(nèi)存問題嗎,你能解決并發(fā)的問題嗎?Django那么重。

然后我只好回答說,正是因為它重,所以人家拿來寫大型項目。雖然這里不是為了上面這2個問題的,而是來說下如何快速開發(fā)原型的問題。

對于Django這樣基于模型的Web框架,實話說真的解決了很多繁瑣的工作。由于它1個模型對應(yīng)1張表,因此只要很短暫的時間就把原型給弄完了。實際上,我用Django主要是不用被頁面浪費我的時間,這樣我就可以專心寫API那方面了。

結(jié)果,公司這個項目除了自己可以看到外,還要實現(xiàn)1個B端的需求,而我此時的后臺功能已經(jīng)完成了,這可以如何是好。而區(qū)別在于只能讓注冊的用戶只能看到屬于它自己的訂單,而其他不變。

于是上官方文檔看了下表單的教程,看到1個ModelForm的玩意,通過它可以將后臺的表單直接渲染出來,而后在ModelForm類中通過instance關(guān)鍵字可以將對應(yīng)模型直接渲染出來,這樣花了1個星期的時間就把API、B端和公司的后臺完成了,效率還算比較高。

下面說下如何通過Django快速實現(xiàn)項目:

  1. 實際上分解問題很關(guān)鍵,把問題按等級劃分有助于加快開發(fā)速度
  2. 把不怎么會寫的代碼先跳過,使用繁瑣的方式先寫上去,后面再用其內(nèi)建的方式來替換
  3. 不要緊張,一定要保持淡定,不然你會發(fā)現(xiàn)你完全寫不出代碼
  4. 不要看官方文檔,因為寫的啰嗦又難找到重點
  5. 帶著問題在網(wǎng)上搜索答案,如果某個方式不行就換種思路去做,比如要實現(xiàn)1個多對多的關(guān)系的HTML組件,直接找第3方插件而不是看文檔實現(xiàn)

相信如何能做到以上幾點,才能把django的效率發(fā)揮出來。下面來看看本文的詳細介紹吧。

Django同1個頁面中的多表單處理

關(guān)于在同1個頁面多個表單提交的問題,實際上是項目中遇到的1個小問題。關(guān)于這個問題,主要有2個需要解決的問題:

  1. 多個表單的渲染問題
  2. 多個表單提交時外鍵的處理問題

下面我們分別進行說明。

當時在建模的時候使用了類似如下的方式:

from django.db import models 

class Store(models.Model): 
 name = models.CharField('名稱', max_length=20) 
 first = models.FloatField('首重') 
 additional = models.FloatField('次重') 
 img = models.ImageField('圖片', upload_to='store/1') 

class Depot(models.Model): 
 s_name = models.ForeignKey(Store, verbose_name='倉庫') 
 src = models.CharField('始發(fā)地', max_length=20) 
 dest = models.CharField('目的地', max_length=20) 
 days = models.PositiveSmallIntegerField('需要的天數(shù)') 

class Address(models.Model): 
 s_name = models.ForeignKey(Store, verbose_name='倉庫') 
 country = models.CharField('國家', max_length=20) 
 state = models.CharField('省份', max_length=10) 
 city = models.CharField('城市', max_length=10) 
 description = models.TextField('描述', blank=True)

在這里,1個倉庫的數(shù)據(jù)主要由3個表組成,分別為它的一些基礎(chǔ)信息,可以配送的范圍、天數(shù)及其他一些附加信息組成。然后其頁面如下所示:

多表單渲染

而公司的需求就是我們要在商戶端上讓客戶在創(chuàng)建倉庫時填寫上述的內(nèi)容,由于我比較懶,而公司給出的時間也不是很充裕,于是直接使用ModelForm來實現(xiàn),而不需要一一的創(chuàng)建表單了。換句話說,我們要將多個模型表在同1個頁面中渲染出來,對于這樣的問題,主要有4種解決的方案:

  1. 在1個form組件中使用多個模型表單類
  2. 使用django提供的modelform_factory來解決
  3. 使用第3方插件django-betterforms或django-multipleformwizard這樣的插件
  4. 使用元類,然后繼承BaseForm進行表單的重寫。

這里我們使用第1種解決方案來實現(xiàn)多個表單渲染的問題。

這里我們在forms模塊下新建3個模型表單類:

from django.forms import ModelForm 
from models import Store, Address, Depot 

class StoreForm(ModelForm): 
 class Meta: 
 model = Store 
 fields = '__all__' 

class AddressForm(ModelForm): 
 class Meta: 
 model = Address 
 exclude = ['s_name'] 

class DepotForm(ModelForm): 
 class Meta: 
 model = Depot 
 exclude = ['s_name']

然后在視圖中引入這3個表單:

from django.shortcuts import render_to_response, HttpResponseRedirect 
from django.template import RequestContext 
from forms import StoreForm, AddressForm, DepotForm 

def store_add(req): 
 if req.method == 'POST': 
 ... 
 else: 
 sf = StoreForm() 
 af = AddressForm() 
 df = DepotForm() 
 return render_to_response('store_add.html', { 
 'sf': sf, 'af': af, 'df': df, 
 }, context_instance=RequestContext(req))

默認情況下,我們先將對應(yīng)的表單渲染出來先。在這里我們往模板中輸出了多個變量,然后在模板中手動進行如下的處理:

<form action="" method='post' enctype='multipart/form-data'> 
 {% csrf_token %} 
 {{ sf.as_p }} 
 {{ df.as_p }} 
 {{ af.as_p }} 
 <input type="submit" value = "添加" /> 
</form>

在這里,我們在1個表單中輸出多個表單,其頁面如下所示:

可以看到其效果與后臺的頁面相差不是很大,只是沒有對應(yīng)的樣式而已。

多表單提交外鍵處理

接著我們需要處理多個表單提交時的處理問題。

def store_add(req): 
 if req.method == 'POST': 
 sf = StoreForm(req.POST, req.FILES) 
 af = AddressForm(req.POST) 
 df = DepotForm(req.POST) 
 if sf.is_valid() and af.is_valid() and df.is_valid(): 
 sf.save() 
 df.save() 
 af.save() 
 return HttpResponseRedirect('store') 
 ...

在這里我們直接對這3個表單進行保存,結(jié)果出現(xiàn)了這樣1個錯誤。

NOT NULL constraint failed: app_depot.s_name_id 

由于我們使用了1個外鍵進行了約束,而使用上述的方式會導致數(shù)據(jù)表中的s_name_id的字段數(shù)值為NULL,從而導致了錯誤。而上述的方式時直接就提交給數(shù)據(jù)庫了,導致后面的外鍵無法被滿足。

為了解決這個問題,我們采用延遲提交給數(shù)據(jù)庫的方式:

def store_add(req): 
 if req.method == 'POST': 
 ... 
 if sf.is_valid() and af.is_valid() and df.is_valid(): 
 form = sf.save(commit=False) 
 sf.save() 
 dform = df.save(commit=False) 
 dform.s_name = form 
 dform.save() 
 aform = af.save(commit=False) 
 aform.s_name = form 
 aform.save() 
 return HttpResponseRedirect('store') 
 else: 
 ...

在這里,我們先讓第1張表先不提交,將其保存為1個變量form中。而第2個張表也先不提交,我們將其實例的s_name修改為之前的第1張表返回的結(jié)果,然后再進行保存。這樣我們就實現(xiàn)了多張表的依賴導致的問題了。最后我們使用重定向的方式將成功添加后的頁面跳轉(zhuǎn)到該商戶的倉庫列表中。

其跳轉(zhuǎn)后的頁面如下所示:

這樣我們就解決了在1個頁面提交多個表單的問題。實際關(guān)于Django在1個頁面提交多個表單的問題,實際上問題不是很多,只要解決了渲染和提交時處理的問題,實際這個問題就迎刃而解了。重要的是如何拆分問題和解決問題的思路。

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學習或者工作能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。

相關(guān)文章

最新評論