2017-11-11 111 views
0

我有產品和訂單的簡單的Django模型結構中,通過確定一個給定的順序中的每個產品的數量的中間錶鏈接:Django的形式與來自數據庫填充輸入

models.py:

class Product(models.Model): 
    name = models.CharField() 

class Order(models.Model): 
    id = models.IntegerField() 
    products = models.ManyToManyField(Product, through='OrderProduct') 

class OrderProduct(models.Model): 
    order=models.ForeignKey(Order, on_delete=models.CASCADE) 
    product = models.ForeignKey(Product, on_delete=models.CASCADE) 
    quantity = models.PositiveSmallIntegerField() 

我想在我的forms.py文件中設計一個表單,該表單1)拉取數據庫中每個產品的列表; 2)爲用戶提供了調整每個訂購產品數量的選項(例如,在CharField輸入中),以及3)創建新的Order和OrderProduct對象,存儲用戶訂購的每個產品的數量記錄。

但是,我找不到一個好方法來創建一個表單,它將自動從數據庫中提取所有產品,並添加字段來表示給定產品的訂購數量。理想情況下,結果會是這個樣子,但自動編碼:

forms.py:

class OrderForm(forms.Form): 
    product_1_quantity = forms.IntegerField() 
    product_2_quantity = forms.IntegerField() 
    product_3_quantity = forms.IntegerField() 

....等,每個產品。什麼是最好的方法來做到這一點?它是否涉及爲數據庫中的每個產品創建新字段的for循環?

回答

1

我認爲Django Formsets可能對您有用。根據您決定的數量,您可以反覆創建相同表單的集合,因此您的產品。檢查出來here。你可以做下面的例子。

class ArticleForm(forms.Form): 
    title = forms.CharField() 

from django.forms import formset_factory 
ArticleFormSet = formset_factory(ArticleForm, extra=2) 

的數據如您還可以預填充它,

formset = ArticleFormSet(initial=[ 
     {'title': 'Django is now open source'} 
    ]) 

希望這有助於!

+0

這很好用 - 非常感謝您的幫助!我將在另一篇文章中更詳細地回答這個問題,以便人們可以看到整個代碼。 – Sam

+0

很高興我可以幫助:) – devdob

0

您可以使用ModelChoiceField顯示所有產品無for循環做:

class OrderForm(forms.Form): 
    product = forms.ModelChoiceField(queryset=Product.objects.all()) # with queryset you can show a checkbox with the query 
    quantify = forms.IntegerField() 

現在你的觀點要小心保存您的數據。例如,如果你需要一個按鈕「添加新的」,你可以使用ajax,否則you can use formset

+0

感謝您的迴應!我試過這個,但是這會產生一個'select'下拉列表,而我想爲我的數據庫中的每個產品單獨一行,旁邊有一個數量字段。 Formset在這裏完成了目標 - 請參閱上面的答案! – Sam

0

詳細說明從user3140312下面的答案 - Django的formsets提供瞭解決方案!

models.py:

class Product(models.Model): 
    name = models.CharField() 

class Order(models.Model): 
    id = models.IntegerField() 
    products = models.ManyToManyField(Product, through='OrderProduct') 

class OrderProduct(models.Model): 
    order=models.ForeignKey(Order, on_delete=models.CASCADE) 
    product = models.ForeignKey(Product, on_delete=models.CASCADE) 
    quantity = models.PositiveSmallIntegerField() 

forms.py

class ProductForm(forms.Form): 
    product_id = forms.IntegerField(widget=forms.HiddenInput) 
    quantity = forms.IntegerField() 

views.py

from .forms import ProductForm 
from django.forms import formset_factory 
from .models import Product 

# Show a form asking for the user's product quantities 
def product_form(request): 

    # If this form is being processed... 
    if request.method == 'POST': 

     ProductFormSet = formset_factory(ProductForm) 

     # Grab the form from the POST variable 
     formset = ProductFormSet(request.POST) 

     # If the form is valid... 
     if formset.is_valid(): 

      # Do whatever you want with the results 

    # If the form is not being processed, create a new ProductFormSet and render it 
    else: 

     product_list = [] 

     for product in Product.objects.all(): 
      product_list.append({'product_id': product.id, 'quantity': 0}) 

     ProductFormSet = formset_factory(ProductForm, extra=0) 
     formset = ProductFormSet(initial=product_list) 
     return render(request, 'template.html', {'formset': formset}) 

template.html:

<form action="{% url '' %}" method="post"> 
    {% csrf_token %} 
    {{ formset.as_table }} 
    {{ formset.management_form }} 
    <input type="submit" value="Submit" /> 
</form> 
+0

不要忘記接受來自@ user3140312 –

+0

完成的答案。謝謝! – Sam