1

提交表单时出现奇怪的错误。当调用 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))

此表单有问题,或者需要添加一些内容。呈现模板时,表单按预期显示,但在提交数据时显然不起作用

4

1 回答 1

2

很抱歉打扰您...我刚刚发现了问题...自定义字段是使用空查询集创建的,因为只能在评估视图时确定查询集。当从 FORM 数据创建表单实例时,我忘记了编辑查询集。现在它按预期工作

于 2012-08-22T12:37:10.143 回答