下面咱們繼續實現depot購物車的web應用。本節要實現提交訂單功能。如今買方已經能夠挑選須要的產品放入購物車,可是還不能進行購買。咱們但願實現這樣的功能:html
買方點擊」結算「按鈕,而後輸入姓名、地址和email信息,就向賣方發出了一張訂單,該訂單包含上述買方信息和其選購的全部條目。首先仍是實現Model類。咱們要增長一個訂單類(Order),並修改原來的條目類(LineItem),增長到Order的外鍵(即LineItem到Order的many-to-one關聯)。以下:git
class Order(models.Model):web
name = models.CharField(max_length=50)數據庫
address = models.TextField()django
email = models.EmailField()session
class LineItem(models.Model):app
product = models.ForeignKey(Product)ide
order = models.ForeignKey(Order)函數
unit_price = models.DecimalField(max_digits=8,decimal_places=2)工具
quantity = models.IntegerField()
要注意,由於LineItem引用了Order,因此在定義模型類的順序上要將Order放在前面。
前面介紹過修改模型類以後應該如何處理,這裏就再也不重複了。
而後祭出scaffold,快速生成一系列」醜陋「的界面。該工具還不夠成熟,在生成以前,必定要備份depotapp/urls.py 、views.py 和 forms.py,以後手工合併,切記!
以後將產品目錄界面(depot/templates/depotapp/store.html)中的」結算「標籤的連接改成映射到生成的create_order視圖函數:
<aclass="btn success"href="{% url depotapp.views.create_order %}">結算</a>
兩 個界面就連接起來了。可是自動生成的訂單界面並無將session中的條目保存到數據庫,也沒有清空購物車,而且提交訂單後沒有返回到產品目錄界面,所 以還要對其進行修改。主要的修改在create_order視圖函數中進行。爲了方便對比,將生成的原始視圖函數列出以下:
def create_order(request):
form = OrderForm(request.POST orNone)
if form.is_valid():
form.save()
form = OrderForm()
t = get_template('depotapp/create_order.html')
c = RequestContext(request,locals())
return HttpResponse(t.render(c))
關於事務處理
」保存訂單「和」保存訂單條目「應該造成一個事務。Django的事務處理能夠經過middleware自動添加,也能夠手工添加。手工添加的方式更加靈活,經過在view函數前增長修飾符(decorator)來實現,有三種修飾符能夠選擇:
@transaction.autocommit 在 save() 或 delete() 時自動提交事務。
@transaction.commit_on_success 當整個view成功後提交事務,不然回滾( TransactionMiddleware採用的就是這種機制)
@transaction.commit_manually 須要手動調用commit或rollback。
咱們暫時不想使用middleware的方式,因此用@transaction.commit_on_success來實現事務管理。這須要引用transaction模塊:from django.db import transaction
最終修改的create_order視圖函數以下:
@transaction.commit_on_success
def create_order(request):
form = OrderForm(request.POST orNone)
if form.is_valid():
order = form.save()
for item in request.session['cart'].items:
item.order = order
item.save()
clean_cart(request)
return store_view(request)
t = get_template('depotapp/create_order.html')
c = RequestContext(request,locals())
return HttpResponse(t.render(c))