django - template - from.models import post




Django內聯表單與自定義表單 (2)

您好我有一個域模型,用於Django應用程序,我想在一個表單上。 我用自定義的ModelForms創建了我的應用程序(沒有太多的變化,一些領域排除等)。 該模型的依賴關係如下所示:

Complaint
   \
    .--- CarInfo
    .--- Customer

我的看法功能如下所示:

def make(request):
  if request.method == 'POST':
    parameters = copy.copy(request.POST)
    complaint = Complaint()
    carInfo = CarInfo()
    customer = Customer()

    customer_form = CustomerForm(parameters, instance=customer)
    carInfo_form = CarInfoForm(parameters, instance=carInfo)
    parameters['complaint_date'] = get_current_date()
    parameters['customer'] = 1 # dummy value to allow validation success
    parameters['car_info'] = 1 # dummy value to allow validation success
    form = ComplaintForm(parameters, instance=complaint)
    if form.is_valid() and customer_form.is_valid() and carInfo_form.is_valid():
      carInfo_form.save()
      customer_form.save()
      parameters['customer'] = customer.id
      parameters['car_info'] = carInfo.id
      form = ComplaintForm(parameters, instance=complaint)
      form.save()
      return index(request)
  else:
    form = ComplaintForm()
    carInfo_form = CarInfoForm()
    customer_form = CustomerForm()
  return render_to_response('complaints/make_complaint.html', {'complaint_form' : form, 'customer_form' : customer_form, 'carInfo' : carInfo_form})

我不太喜歡這個方法,而且它在所有的環境下都不起作用 - 我沒有找到它不工作的原因。 我一直在尋找修復這個代碼,找到像內聯formset (http://docs.djangoproject.com/en/dev/topics/forms/modelforms/#inline-formsets)。 這個解決方案似乎沒問題,但是因為我的表單是自定義的,我可以使用它。

也許有人可以就如何妥善解決這種情況提供一些建議。 清潔解決方案非常感謝。

編輯有一種情況下,我這個解決方案不起作用。 儘管在外鍵上設置了虛擬值,當我調用is_valid()時,我得到FALSE,錯誤消息說這些字段沒有設置。 我正在用django 1.2.5觀察這個問題 - 它發生在服務器上,我打算運行這個應用程序,但是我的筆記本電腦(也是django 1.2.5)沒有這個問題。


可能formset工廠和內聯formset應該解決您的問題...您可以修改或重寫從模型創建的表單域,對於子模型,您可以使用內聯formset ...

表單集和內嵌表單集...

可能的解決方案:

在你的表單定義中:

class CarInfoFrm(forms.ModelForm):
    class Meta:
        model = CarInfo
        fields = (....)
carInfoForm = inlineformset_factory(Complaint, CarInfo, form=carInfoFrm,)
CustomerForm = inlineformset_factory(Complaint, Customer, form=carInfoFrm,)

在你看來:

complaint = Complaint()
carInfo = CarInfo()
customer = Customer()

cus_form = CustomerForm(parameters, instance=complaint)
car_form = CarInfoForm(parameters, instance=complaint)
comp_form = ComplaintForm(parameters, instance=complaint)

if cus_form.is_valid() and ...... :
    comp = comp_form.save(commit=False)#do not save it yet
    comp.<attr> = "some_value" #you can edit your data before save...
    comp.save()
    car = car_form(commit=False)
    # do as complaint form... edit and save... 

編輯:我在定義實例參數,同時保存內聯格式時做一個misteke。 所以我糾正它...

當你更新現有的記錄時,你不會有問題,但最好是像這樣使用它:

if comp_form.is_valid():
    comp = comp_form.save(commit=False)
    comp.<attr> = "some_value"
    comp.save()
if car_form.is_valid():
    # edit if neccessary then save...

if cust_form.is_Valid():
    # edit if neccessary then save...

更簡單的是,當你定義你的表單時,你通過一個外鍵來設置一個父表單

carInfoForm = inlineformset_factory(Complaint, CarInfo, form=carInfoFrm,)

而當你使用內聯表單進行更新時,你用你的父Compalaint記錄進行初始化,

car_form = CarInfoForm(parameters, instance=complaint)

所以,car_form不接受一個carInfo實例,而是一個投訴實例(這是我的第一個答案中的錯誤,所以我糾正了它)。 如果它創建一個新的記錄,它會自動綁定到相關的投訴記錄。 如果是更新,則只更新所需的字段。

對我來說,iti最好是使用框架的moehods,而不是寫你的擁有者。 通過這樣做,你將保證所有的驗證檢查由django進行。


您可以將您的投訴模式的投訴日期更改為這樣的

complaint_date = models.DateField(default=datetime.date.today())

這樣你可以擺脫

parameters['complaint_date'] = get_current_date()

至於你的多表單視圖,你可以使用一個未綁定的表單來達到你想要的行為。

通過在投訴表格中將fk排除在汽車和客戶之外,表格應該被驗證。 同時檢查所有3個表單的.is_valid(),然後保存你的投訴對象所依賴的2個表單,用commit提交到數據庫(commit = False)創建投訴對象,添加客戶的id和車到那個對象,然後保存。

在你看來。

def make(request):
    if request.method == 'POST':
        customer_form = CustomerForm(request.POST)
        carInfo_form = CarInfoForm(request.POST)
        form = ComplaintForm(request.POST)

        if form.is_valid() and customer_form.is_valid() and carInfo_form.is_valid():
            car_instance = carInfo_form.save()
            customer_instance = customer_form.save()

            complaint_instance = form.save(commit=False)
            complaint_instance.car_info = car_instance
            complaint_instance.customer_info = customer_instance          
            complaint_instance.save()

            return index(request)
    else:
        form = ComplaintForm()
        carInfo_form = CarInfoForm()
        customer_form = CustomerForm()

    context = { 'complaint_form' : form,
                'customer_form' : customer_form, 
                'carInfo' : carInfo_form,
              }
    return render_to_response('complaints/make_complaint.html', context, context_instance=RequestContext(request))

編輯:

模型看起來像這樣:

class CarInfo(models.Model):
    some_car_info = models.CharField()

class Customer(models.Model):
    some_customer_info = models.CharField()

class Complaint(models.Model):
    car_info = models.ForeignKey(CarInfo)
    customer_info = models.ForeignKey(Customer)
    some_complaint_info = models.CharField()

forms.py應該看起來像這樣:

class CarInfoForm(forms.ModelForm):
    class Meta:
        model = CarInfo

class CustomerForm(forms.ModelForm):
    class Meta:
        model = Customer

class ComplaintForm(forms.ModelForm):
    class Meta:
        model = Complaint
        exclude = ('car_info', 'customer_info',) # or include = ('some_complaint_info',)

讓我們一起來看看我上面寫的觀點: form in view docs

  • 第一遍,沒有request.method,所以我們創建3個未綁定的表單。

    else:
        form = ComplaintForm()
        carInfo_form = CarInfoForm()
        customer_form = CustomerForm()
  • 這些表單被傳遞給模板並呈現。

  • 當再次調用request.method ==“POST”來評估視圖的時候,我們使用request.POST中的數據創建3個綁定的表單實例。

    if request.method == 'POST':
        customer_form = CustomerForm(request.POST)
        carInfo_form = CarInfoForm(request.POST)
        form = ComplaintForm(request.POST)
  • 接下來我們在每個表單上調用.is_valid()方法。 在我們的示例中,因為我們在投訴模型表單中排除了“customer_info”和“car_info”外鍵字段,所以每個表單都只檢查字符輸入字段是否有效。

  • 如果驗證全部通過,那麼我們可以開始將我們的表單保存到模型中,並且在這裡我們需要小心地填充我們的投訴所需的fk:

        if form.is_valid() and customer_form.is_valid() and carInfo_form.is_valid():
            car_instance = carInfo_form.save()
            customer_instance = customer_form.save()
  • 通過這兩種形式,我們可以像往常一樣調用.save()。 然而,我們將返回值分配給car_instance和customer_instance。 這些將包含我們剛在表單上使用.save()方法創建的CarInfo和Customer模型的實例。

  • 接下來,在.save()方法中使用commit=False參數,我們可以從綁定的表單(包含request.POST數據)創建一個對象,而不是將其保存到數據庫中。

            complaint_instance = form.save(commit=False)
            complaint_instance.car_info = car_instance
            complaint_instance.customer_info = customer_instance          
            complaint_instance.save()
  • 為了使這個更清楚,你也可以創建一個像這樣的新的Complaint對象:

    complaint_info = form.cleaned_data.get('some_complaint_info')
    complaint_instance = Complaint(car_info=car_instance, customer_info=customer_instance, some_complaint_info=some_complaint_info)
    complaint_instance.save()
  • 給予





django-forms