模型的字段在ModelForm.save()调用后被清除

时间:2013-07-24 15:45:14

标签: django modelform

我遇到了一个问题,我在视图函数的GET部分中使用预先存在的模型实例来实例化基于ModelForm的表单。这个模型已经填写了几个字段; ModelForm用于收集模型中的其他字段。 ModelForm的定义中排除了预先存在的字段。

问题是,在POST处理期间,在成功验证ModelForm之后,我正在调用ModelForm.save(commit = False)...并且返回了模型(应该与我作为'实例传入的模型相同) '在GET处理中,请记住)以某种方式丢失了之前设置的所有字段。实际由表格设定的字段很好;但它不再是我模型的原始实例。

这不是我预期的行为;事实上我之前已经使用过这种模型中的部分模型,并且它在其他地方工作。我在这里想念的是什么?

希望有些代码可以清楚地说明这一切......

所以这是模型:

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 个答案:

答案 0 :(得分: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填充实例,但如果表单为None,则request.POST中的数据对于表单是可选的。它还使您不必在两个地方实例化表单,具体取决于request.method