2016-08-27 47 views
4

我被困在設計問題中。Django在視圖中添加窗體到formset

想象的訂單模型和材料模型,

class Material(models.Model): 
    material_code = models.CharField(max_length=40) 
    standard_price = models.DecimalField() 

class Order(models.Model): 
    customer = models.ForeignKey(Customer) 


class OrderItems(models.Model): 
    order = models.ForeignKey(Order) 
    material = models.ForeignKey(Material) 
    price = models.DecimalField() 

在我的訂單詳細信息視圖,我填充使用inlineformset_factory的OrderItems(訂單,的OrderItems)

我想要的行爲是下面:

如果用戶想要添加更多的訂單項,我想將用戶重定向到物料清單頁面,用戶選擇一個或多個物料並確認,然後我重定向他以使用新添加的物品再次訂購詳細視圖。

我正在考慮這些工作,像Django管理員操作與中間頁面。

在添加新訂購訂單之前,我還希望從材料standard_price中設置訂單價格,這意味着我想在將其添加到訂購商品之前修改表單集合值。


我想在這裏問的問題,有更簡單的方式實現這一目標,現在看來,表單集數據存儲到會話和重新建新項目表單集不會很容易。我會考慮解決這個問題的另一種方法。

我不想要JS的解決方案,想象一下我的訂單模型,grandtotal,我可能會計算總項目金額,與js解決方案我可能必須做計算邏輯與js,用戶添加項目和改變價格,然後我用js進行總計算。這是我想要避免的。

+0

總計問題很容易避免。永遠不要接受客戶,要控制什麼。所以「加入購物車」js只會提交物品ID和數量。它接收新的購物車總數(在服務器上計算)並呈現更新後的迷你購物車。問題解決了。 – Melvyn

回答

5

從您提供的描述中,我找不到用於的套件

您只需要一個材料目錄頁面,其中列出了材料。每種材料都可以添加到當前購物車,這是通過Ajax調用通過材質PK傳遞的url完成的,因此該Ajax調用的視圖可以創建購物車並將該材料添加到購物車。

最後,你需要一個的OrderDetail,你需要一個for循環上的所有材料,目前在用戶的購物車。

您可以第一個完全實現它在數據庫中,與關係模型車,這實際上是已經實施Order類中定義。

然後你就可以添加一個緩存層,以限制寫入/刪除/更新到數據庫,使用Django的會話(這有性能提升,考慮到你在你的數據庫不存儲會話!)

因此總而言之,您可能需要的是(我使用購物車的概念,以暗示用戶只能有一個活動訂單,如果您的要求不同,它可以很容易地更改爲您「VE提供您的訂單模型):

數據模型:

class Cart: 
    user = 1to1(User, related_name='cart') # Can be a FK if you want several active orders 
    is_approved = Boolean # To tell if the order is considered Over or is still open 
    created_at = DateTimeField 
    ... 

class Material: 
    orders = M2M(Cart, through=CartItem) 
    ... 

class CartItem: 
    cart = FK(Cart) 
    material = FK(Material) 
    ... 

瀏覽:

def list_materials(request): 
    returns_rendered_template_with(materials=Material.objects.all()) 

#Ajax method, called via Post, you probably need a way to also delete, or edit (number of materials to order ?) 
def add_material_to_cart(request, material_id): 
    cart = Cart.objects.get_or_create(user=request.user) 
    material = Material.objects.get(pk=material_id) 
    CartItem(material=material, cart=cart).save() 

def order_detail_view(request): 
    cart = user.cart 
    cart_items = CartItems.objects.filter(cart=cart) 
    returns_rendered_template_with(cart_items=cart_items) 

模板:

material_list.html

.... 
{% for item in materials %} 
     {% show material info, such as price, availability, ... %} 
     <button data-pk={{item.pk}}, ...> to call add_material_to_cart </button> 
{% endfor %} 

order_detail.html

.... 
{% for item in cart_items %} 
     {% show each cart_item.material and its information + whatever you need %} 
{% endfor %} 

這是可以實現的東西最基本的形式,我明白了,你想要的。
您可以合併幾個這方面的意見一起,可以實現無需對車和CartItem模型「完全會話」的解決方案,剛剛完成訂單獲得持續到我不知道,比爾模式?訂單歷史 ?任何你想要的。

+0

一個+1時間,你幾乎在那裏。只有擺脫材料。這不是必需的,並引入了微妙的錯誤。購物車中的所有商品都與CartItem中的多對一完全關聯。介紹物料允許多個購物車物品與多個購物車相關聯,CartItem本身不允許,直到您添加空屬性,然後事情變得時髦。 – Melvyn

+0

@Melvyn如果他擺脫了材料,他就不能有一個公共的*材料清單*頁。這樣,他可以列出用戶選擇的材料,在選擇時選擇一個實際上只屬於該用戶的相應的* CartItem *。與此同時,恕我直言,它更易於列出*材料*爲用戶,而不是列出* CartItem * s。 CartItems將在CartDetail視圖中列出。 – SpiXel

+0

另外一個CartItem的實例只能與一個** single ** Cart相關聯。因此,每個用戶都有一個可能包含多個CartItem的Cart。在結賬時,他可以沖洗當前的CartItems(checked_out = True),這樣用戶就會面對一個全新的Cart。材料用於向用戶顯示可用的信息,Cart和CartItem用於結帳和結算。 – SpiXel

0

您可以通過將「添加動態字段」簡化爲您的訂單明細表單。

當用戶單擊「添加材料」按鈕,一個新的領域(比如說用的材料列表<select>域)將被添加到形成。

link將幫助你實現你的任務。

+0

我沒有得到,這是如何回答我的問題。你能否詳細說明。 – durdenk

1

如果我正確理解你的意圖,你想創建某種購物車的,你不希望創建一個沒有被放置尚未訂單數據庫條目。

我的建議是創建一個Cart模型和一個CartItem模型,該模型存儲有關當前正在購物車中的物品的信息。 當顧客下訂單,你從車及其項目對應的OrderItem情況下創建一個新的Order實例,並堅持這一點。

CartCartItem既可以是存儲在數據庫中的Django模型,也可以是純Python類,並將它們序列化以便存儲在會話中。

在數據庫中存儲它們可能是更容易,但很可能會產生比基於會話的解決方案的更多的數據庫查詢。這是否是一個問題取決於您的服務器容量和預期負載。這個方法在Django的電子商務框架Oscar中實現。

相關問題