2013-07-24 64 views
0

我遇到了一個問題,我在我的視圖函數的GET部分中使用預先存在的模型實例實例化了一個基於ModelForm的表單。這個模型已經有幾個領域填充; ModelForm用於收集模型中的其他字段。 ModelForm定義中不包含預先存在的字段。模型的字段在ModelForm.save()調用後被清除

問題是,在POST處理過程中,成功驗證ModelForm後,我調用了ModelForm.save(commit = False)...並返回了模型(它應該是我傳入的同一個'實例'在GET處理中,請記住)已經以某種方式丟失了以前設置的所有字段。由表單實際設置的字段很好,但它不再是我的模型的原始實例。

這不是我所期望的行爲;事實上,我以前使用過這種模型中的部分模型,它可以在其他地方使用。我在這裏錯過了什麼?

希望一些code'll讓這一切清楚...

因此,這裏的型號:

class Order(models.Model): 

    STATUS = (
     ('Created', -1), 
     ('Pending', 0), 
     ('Charged', 1), 
     ('Credited', 2), 
    ) 

    SHIPPING_STATUS = (
     ('Cancelled', 0), 
     ('Ready for pickup', 1), 
     ('Shipped', 2), 
     ('OTC', 3), 
    ) 

    orderID = models.IntegerField(max_length=15, null=True, blank=True) 
    store = models.ForeignKey(Store) 
    paymentInstrument = models.ForeignKey(PaymentInstrument, null=True, blank=True) 
    shippingMethod = models.ForeignKey(ShippingMethod, null=True, blank=True) 

    last_modified = models.DateTimeField(null=True, blank=True) 
    date = models.DateTimeField(auto_now_add=True, null=True, blank=True) 

    total = models.FloatField(default=0.0, blank=True) 
    shippingCharge = models.FloatField(default=0.0, blank=True) 
    tax = models.FloatField(default=0.0, blank=True) 

    status = models.CharField(max_length=50, choices=STATUS, default = 'Created') 
    shippingStatus = models.CharField(max_length=50, choices=SHIPPING_STATUS, default = '1') 

    errstr = models.CharField(max_length=100, null=True, blank=True) 

    # billing info 
    billingFirstname = models.CharField(max_length = 50, blank = True) 
    billingLastname = models.CharField(max_length = 50, blank = True) 
    billingStreet_line1 = models.CharField(max_length = 100, blank = True) 
    billingStreet_line2 = models.CharField(max_length = 100, blank = True) 
    billingZipcode = models.CharField(max_length = 5, blank = True) 
    billingCity = models.CharField(max_length = 100, blank = True) 
    billingState = models.CharField(max_length = 100, blank = True) 
    billingCountry = models.CharField(max_length = 100, blank = True) 

    email = models.EmailField(max_length=100, blank = True) 
    phone = models.CharField(max_length=20, default='', null=True, blank=True) 

    shipToBillingAddress = models.BooleanField(default=False) 

    # shipping info 
    shippingFirstname = models.CharField(max_length = 50, blank = True) 
    shippingLastname = models.CharField(max_length = 50, blank = True) 
    shippingStreet_line1 = models.CharField(max_length = 100, blank = True) 
    shippingStreet_line2 = models.CharField(max_length = 100, blank = True) 
    shippingZipcode = models.CharField(max_length = 5, blank = True) 
    shippingCity = models.CharField(max_length = 100, blank = True) 
    shippingState = models.CharField(max_length = 100, blank = True) 
    shippingCountry = models.CharField(max_length = 100, blank = True) 

這裏的定義的ModelForm:

class OrderForm(ModelForm): 

    class Meta: 
     model = Order 
     exclude = ('orderID', 
       'store', 
       'shippingMethod', 
       'shippingStatus', 
       'paymentInstrument', 
       'last_modified', 
       'date', 
       'total', 
       'payportCharge', 
       'errstr', 
       'status',) 
     widgets = { 
      'billingCountry': Select(choices = COUNTRIES, attrs = {'size': "1"}), 
      'shippingCountry': Select(choices = COUNTRIES, attrs = {'size': "1"}), 
      'billingState': Select(choices = STATES, attrs = {'size': "1"}), 
      'shippingState': Select(choices = STATES, attrs = {'size': "1"}), 
       } 

這裏是查看功能:

def checkout(request): 

    theDict = {} 

    store = request.session['currentStore'] 
    cart = request.session.get('cart', False) 
    order = request.session['currentOrder'] # some fields already set 
    if not cart: # ...then we don't belong on this page. 
     return HttpResponseRedirect('/%s' % store.urlPrefix) 

    if request.method == 'GET': 

     form = OrderForm(instance=order, prefix='orderForm') 

    else: # request.method == 'POST': 
     logging.info("Processing POST data...") 

     form = OrderForm(request.POST, prefix='orderForm') 

     if form.is_valid(): 
      ### AT THIS POINT, ORDER FIELDS ARE STILL GOOD (I.E. FILLED IN) 
      order = form.save(commit=False) 
      ### AFTER THE SAVE, WE'VE LOST PRE-EXISTING FIELDS; ONLY ONES SET ARE 
      ### THOSE FILLED IN BY THE FORM. 

      chargeDict = store.calculateCharge(order, cart) 

      request.session['currentOrder'] = order 

      return HttpResponseRedirect('/%s/payment' % store.urlPrefix) 

     else: 
      logging.info("Form is NOT valid; errors:") 
      logging.info(form._errors) 

      messages.error(request, form._errors) 

    theDict['form'] = form 
    theDict['productMenu'] = buildCategoryList(store) 

    t = loader.get_template('checkout.html') 
    c = RequestContext(request, theDict) 

    return HttpResponse(t.render(c)) 

任何/所有幫助讚賞...

回答

1

當您在POST期間實例化窗體時,您正在編輯的模型的實例是None,因爲您沒有傳遞它,並且您沒有持續從GET表單實例。 Django不會自己做任何事情來在請求之間保存數據。

嘗試:

... 

form = OrderForm(request.POST or None, instance=order, prefix='orderForm') 

if request.method == 'POST': 
    logging.info("Processing POST data...") 

    if form.is_valid(): 
     ... 

現在的情況下將被填充的GET和POST,但是從request.POST數據是可選的,如果它是無形式。它還可以幫助您不必在兩個地方實例化表格,具體取決於request.method

+0

哈!像魅力一樣工作。謝謝,布蘭登! – user2615148

+0

不客氣。 – Brandon