2010-10-06 25 views
3

我有一個模型,可以創建一個新模型或編輯一個現有的模型 - 這很簡單,應該可以工作,但由於某種原因,我每次都得到一個新實例。Django ModelForms - '實例'不能按預期工作

這種情況是電子商務訂單中的第一步。用戶必須填寫一些描述訂單的信息(存儲在模型中)。我創建模型並保存,然後重定向到下一個視圖以供用戶輸入他們的cc信息。我在會話中使用模型,因此我不必在下一個視圖中進行數據庫查找。第二個(cc信息)視圖的模板中有一個鏈接,用戶可以返回到第一個視圖來編輯它們的順序。

# forms.py 

class MyForm(forms.ModelForm): 
    class Meta: 
     fields = ('field1', 'field2') 
     model = MyModel 

# views.py 

def create_or_update(request): 
    if request.method == 'POST': 
     form = MyForm(request.POST) 
     if form.is_valid(): 
      m = form.save(commit=False) 
      # update some other fields that aren't in the form 
      m.field3 = 'blah' 
      m.field4 = 'blah' 
      m.save() 
      request.session['m'] = m 
      return HttpResponseRedirect(reverse('enter_cc_info')) 
     # invalid form, render template 
     ... 
    else: 
     # check to see if we're coming back to edit an existing model 
     # this part works, I get an instance as expected 
     m = request.session.get('m', None) 
     if m: 
      instance = get_object_or_None(MyModel, id=m.id) 
      if instance: 
       form = MyForm(instance=instance) 
      else: 
       # can't find it in the DB, but it's in the session 
       form = MyForm({'field1': m.field1, 'field2': m.field2}) 
     else: 
      form = MyForm() 

    # render the form 
    ... 

如果我步在調試器,當我回去的視圖來編輯表單與實例設置爲先前創建的模型創建,如預期的訂單。但是,當表單在後續POST中處理時,它會在調用form.save()時創建模型的新實例。

我相信這是因爲我限制了表單中的字段,所以在呈現的HTML中沒有任何地方將id(或其他引用)存儲到現有模型中。但是,我嘗試添加'pk'和'id'字段(不是同時),但是我的表單根本不顯示。

我懷疑我做得比它需要的更復雜,但我現在卡住了,可以使用一些反饋。提前致謝。

+0

「我相信這是因爲我已經限制在窗體中的字段」...所以如果你不限制窗體上的字段會發生什麼? – 2010-10-06 16:38:18

回答

9

這很有趣。這是我的刺傷。考慮以下行:

form = MyForm(request.POST) 

你能檢查request.POST的內容嗎?具體來說,檢查是否有任何有關正在編輯模型的哪個實例的信息。你會發現沒有。換句話說,每次您將表單保存在POST上時,都會創建一個新實例。

爲什麼會發生這種情況?當你創建一個通過instance=instance關鍵字參數的表單時,你告訴Form類返回一個模型實例的實例。但是,當您將呈現爲表單到模板時,此信息僅用於以填寫字段。也就是說,關於特定實例的信息丟失了。自然,當你發佈包時,有辦法連接到舊的實例。

您如何防止這種情況發生?一個常見的習慣用法是將主鍵用作URL的一部分,並在POST上查找實例。然後創建表單。在你的情況下這將意味着:

def create_or_update(request, instance_id): 
#        ^^^^^ 
#        URL param 
    if request.method == 'POST': 
     instance = get_object_or_None(Model, pk = instance_id) 
     # ^^^^^ 
     # Look up the instance 

     form = MyForm(request.POST, instance = instance) 
     #       ^^^^^^^ 
     #       pass the instance now. 
     if form.is_valid(): 
       .... 
+0

進行了一些小改動(從request.session抓取了現有模型而不是URL),這就實現了。不知道MyForm(request.POST,instance = instance),謝謝! – 2010-10-06 17:10:52