提交表单时出现奇怪的错误。当调用 form.is_valid() 方法时,堆栈会向下运行,直到一些内置代码尝试访问一个属性,这并不常见......我不明白问题出在哪里。我只是跑
mform = InvAddMainForm(request.POST)
if mform.is_valid():
...
正如我在其他表格上做过几次而没有遇到麻烦一样。知道是什么原因造成的吗?
编辑:有问题的表格如下所示:
class InvAddMainForm(ModelForm):
class Meta:
model = Maintenance
fields = ('serial','end','discount','vat')
def __init__(self, *args, **kwargs):
super(InvAddMainForm, self).__init__(*args, **kwargs)
# The queryset of the field 'serial' is set to None here, as it is
# Derived from the context
self.fields['serial'] = SelectMaintenanceSerialField(required=True, queryset=None)
self.fields['serial'].empty_label = None
self.fields['end'].initial = Option.objects.get(pk='enddate').value
self.fields['vat'].empty_label = None
self.fields['vat'].queryset = Vat.objects.filter(disabled=False).order_by('name')
视图的相关部分如下所示:
if 'addmain' in request.POST:
mform = InvAddMainForm(request.POST)
print str(mform)
if mform.is_valid():
mf = mform.save(commit=False)
it = mf.serial
if it.disabled:
raise Exception('Cannot buy maintenance to disabled license')
# check if maintenance for given item already is on invoice
if Maintenance.objects.filter(invoice=inv, serial=it):
raise Exception('Item already has maintenance on draft')
startdate = None
# continue maintenance
latest = it.latest_main()
if latest:
startdate = latest.end
# if maintenance date used, add one day
if startdate:
startdate += timedelta(days=1)
if not startdate:
startdate = it.pdate
if not startdate:
itinv = it.invoice()
if itinv:
startdate = itinv.idate
# otherwise use quote date
if not startdate:
ii = ItemInv.objects.filter(invoice=inv, item=it)
if ii:
startdate = inv.qdate
if not startdate:
raise Exception('Could not determine start date')
if startdate > mf.end:
raise Exception("Start date after end date")
# add back maintenance
if startdate < inv.qdate:
back = Maintenance(serial = mf.serial,
invoice = inv,
back = True,
start = startdate,
end = inv.qdate,
price = it.prod.prodprice_set.get(cur=inv.cur).bmprice,
discount = mf.discount,
vat = mf.vat,
parent = latest)
latest = back.save()
startdate = inv.qdate
nm = Maintenance(serial = it,
invoice = inv,
start = startdate,
end = mf.end,
price = it.prod.prodprice_set.get(cur=inv.cur).mprice,
discount = mf.discount,
vat = mf.vat,
parent = latest)
nm.save()
updateinvoice(inv.iid)
return redirect('invoice.invoice.invoice', inv.iid)
else:
mform = InvAddMainForm()
# vat = null AND pdate = null, license imported and removed
mform.fields['serial'].queryset = Item.objects.filter(
account__in=cust_acc
).exclude(
prod__in=Product.objects.filter(prodprice__mprice__exact=0, prodprice__cur=inv.cur)
).exclude(
disabled=True
).exclude(
vat__isnull=True,
pdate__isnull=True
)
mform.fields['discount'].initial = def_discount
mform.fields['vat'].initial = Vat.objects.get(name=calcVAT(inv.customer.main_address.country.cc, inv.customer.vatnr, 'PTS'), disabled=False)
...
模板只是调用 form.as_table()... 没有魔法...
回溯如下所示:
AttributeError at /invoice/10013/
'NoneType' object has no attribute 'model'
Request Method: POST
Request URL: http://127.0.0.1:8000/invoice/10013/
Django Version: 1.3.1
Exception Type: AttributeError
Exception Value:
'NoneType' object has no attribute 'model'
Exception Location: /usr/lib/python2.7/dist-packages/django/forms/models.py in to_python, line 973
Python Executable: /usr/bin/python
Python Version: 2.7.3
Python Path:
['/home/ruben/mnt/derby/v2',
'/usr/lib/python2.7',
'/usr/lib/python2.7/plat-linux2',
'/usr/lib/python2.7/lib-tk',
'/usr/lib/python2.7/lib-old',
'/usr/lib/python2.7/lib-dynload',
'/usr/local/lib/python2.7/dist-packages',
'/usr/lib/python2.7/dist-packages',
'/usr/lib/python2.7/dist-packages/PIL',
'/usr/lib/python2.7/dist-packages/gst-0.10',
'/usr/lib/python2.7/dist-packages/gtk-2.0',
'/usr/lib/python2.7/dist-packages/ubuntu-sso-client',
'/usr/lib/python2.7/dist-packages/ubuntuone-client',
'/usr/lib/python2.7/dist-packages/ubuntuone-control-panel',
'/usr/lib/python2.7/dist-packages/ubuntuone-couch',
'/usr/lib/python2.7/dist-packages/ubuntuone-installer',
'/usr/lib/python2.7/dist-packages/ubuntuone-storage-protocol']
Server time: Wed, 22 Aug 2012 14:13:06 +0200
Traceback Switch to copy-and-paste view
/usr/lib/python2.7/dist-packages/django/core/handlers/base.py in get_response
response = callback(request, *callback_args, **callback_kwargs) ...
▶ Local vars
/usr/lib/python2.7/dist-packages/django/db/transaction.py in inner
res = func(*args, **kwargs) ...
▶ Local vars
/home/ruben/mnt/derby/v2/invoice/invoice.py in invoice
print str(mform) ...
▶ Local vars
/usr/lib/python2.7/dist-packages/django/utils/encoding.py in __str__
return self.__unicode__().encode('utf-8') ...
▶ Local vars
/usr/lib/python2.7/dist-packages/django/forms/forms.py in __unicode__
return self.as_table() ...
▶ Local vars
/usr/lib/python2.7/dist-packages/django/forms/forms.py in as_table
errors_on_separate_row = False) ...
▶ Local vars
/usr/lib/python2.7/dist-packages/django/forms/forms.py in _html_output
top_errors = self.non_field_errors() # Errors that should be displayed above all fields. ...
▶ Local vars
/usr/lib/python2.7/dist-packages/django/forms/forms.py in non_field_errors
return self.errors.get(NON_FIELD_ERRORS, self.error_class()) ...
▶ Local vars
/usr/lib/python2.7/dist-packages/django/forms/forms.py in _get_errors
self.full_clean() ...
▶ Local vars
/usr/lib/python2.7/dist-packages/django/forms/forms.py in full_clean
self._clean_fields() ...
▶ Local vars
/usr/lib/python2.7/dist-packages/django/forms/forms.py in _clean_fields
value = field.clean(value) ...
▶ Local vars
/usr/lib/python2.7/dist-packages/django/forms/fields.py in clean
def clean(self, value):
"""
Validates the given value and returns its "cleaned" value as an
appropriate Python object.
Raises ValidationError for any errors.
"""
value = self.to_python(value) ...
self.validate(value)
self.run_validators(value)
return value
def bound_data(self, data, initial):
"""
▶ Local vars
/usr/lib/python2.7/dist-packages/django/forms/models.py in to_python
def to_python(self, value):
if value in EMPTY_VALUES:
return None
try:
key = self.to_field_name or 'pk'
value = self.queryset.get(**{key: value})
except (ValueError, self.queryset.model.DoesNotExist): ...
raise ValidationError(self.error_messages['invalid_choice'])
return value
def validate(self, value):
return Field.validate(self, value)
▼ Local vars
Variable Value
self
<invoice.forms.SelectMaintenanceSerialField object at 0x7f14c83dc250>
value
u'100035'
key
'pk'
我在最后一点感到困惑,内置代码不起作用
编辑:现在,我找到了问题,但不是原因......我为表单使用了定制的表单字段。该字段称为 SelectMaintenanceSerialField。当我使用默认字段时,一切正常。自定义字段的代码如下所示:
class SelectMaintenanceSerialField(ModelChoiceField):
'''
When adding maintenance to a product on a draft; formerly,
only the serial of the product was shown. This field allows
for a custom label for that form
'''
def label_from_instance(self, obj):
'''
This method sets the label for each of the objects of the queryset
'''
item = Item.objects.get(pk=str(obj.serial))
name = item.prod.name
return "%s, %s"%(str(obj.serial), str(name))
此表单有问题,或者需要添加一些内容。呈现模板时,表单按预期显示,但在提交数据时显然不起作用