我遇到了一个问题,我在视图函数的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))
任何/所有帮助表示赞赏...
答案 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