2017-04-10 58 views
1

我已经创建了如下的inlineformset_factory:清洁数据在Django 1.11中消失了吗?

formset = inlineformset_factory(Author, Book, form=BookForm, 
           formset=BaseBookFormSet, 
           can_order=False, can_delete=True, 
           extra=1, fields=('id', name) 
           ) 

BookForm是如下:

Exception Type: AttributeError 
Exception Value: 'BookForm' object has no attribute 'cleaned_data' 

时formset.is_valid:

class BookForm(forms.ModelForm): 
    name = forms.Charfield(required=True) 

    def __init__(self, *args, **kwargs): 
     super(BookForm, self).__init__(*args, **kwargs) 
     self.helper = FormHelper() 
     self.helper.form_tag = False 
     self.helper.layout = Layout(
      Div(
       Field("id", type="hidden"), 
       Field("name"), 
       Field("DELETE") 
       ) 
    ) 

    class Meta: 
     model = Book 
     fields = ('id', 'name') 

    def clean_name(self): 
     book_name = self.cleaned_data['name'] 
     try: 
      book = Book.objects.get(name=book_name) 
      return book 
     except: 
      return book_name 

    def clean(self): 
     cleaned_data = super(BookForm, self).clean() 
     ... other operations on cleaned_data ... 

    def has_changed(self): 
     changed = super(BookForm, self).has_changed() 
     cleaned_data = self.clean() 
     ... other code here ... 

这是在提交表单抛出一个错误()在views.py中被调用。 Traceback首先显示调用self.clean的has_changed中的行,然后显示调用super clean的clean()中的行。

这用于在Django 1.10中正常工作。

当我尝试在Django 1.10中打印dir(self)时,它确实显示'cleaned_data'是属于Django 1.11中的其中一个属性。

Django 1.11中'deleted_data'在哪里消失?

编辑:添加回溯:

Traceback (most recent call last): 
    File "/home/vagrant/venv/local/lib/python2.7/site-packages/django/core/handlers/exception.py", line 41, in inner 
    response = get_response(request) 
    File "/home/vagrant/venv/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 249, in _legacy_get_response 
    response = self._get_response(request) 
    File "/home/vagrant/venv/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 187, in _get_response 
    response = self.process_exception_by_middleware(e, request) 
    File "/home/vagrant/venv/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 185, in _get_response 
    response = wrapped_callback(request, *callback_args, **callback_kwargs) 
    File "/home/vagrant/venv/local/lib/python2.7/site-packages/django/views/generic/base.py", line 68, in view 
    return self.dispatch(request, *args, **kwargs) 
    File "/home/vagrant/venv/local/lib/python2.7/site-packages/django/views/generic/base.py", line 88, in dispatch 
    return handler(request, *args, **kwargs) 
    File "/vagrant/test_os/inventory/views.py", line 297, in post 
    if formset.is_valid(): 
    File "/home/vagrant/venv/local/lib/python2.7/site-packages/django/forms/formsets.py", line 321, in is_valid 
    self.errors 
    File "/home/vagrant/venv/local/lib/python2.7/site-packages/django/forms/formsets.py", line 295, in errors 
    self.full_clean() 
    File "/home/vagrant/venv/local/lib/python2.7/site-packages/django/forms/formsets.py", line 345, in full_clean 
    if not form.has_changed(): 
    File "/vagrant/test_os/inventory/forms.py", line 220, in has_changed 
    cleaned_data = self.clean() 
    File "/vagrant/test_os/inventory/forms.py", line 177, in clean 
    cleaned_data = super(BookForm, self).clean() 
    File "/home/vagrant/venv/local/lib/python2.7/site-packages/django/forms/models.py", line 344, in clean 
    return self.cleaned_data 
AttributeError: 'BookForm' object has no attribute 'cleaned_data' 
+1

请显示完整的回溯。 '超级(StockForm,self)'是一个错字吗? – knbk

+0

是的,StockForm是一个错字。添加了追溯。 – anshuman

回答

3

表单集被固定在1.11(in #26844)验证形式的最小数量时忽略空形式。作为一种副作用,formsets在验证表单之前,现在在每个表单上调用form.has_changed()。 Django预计form.has_changed()在表单验证之前可以安全地调用,并且默认实现确实可以安全地调用。

您已覆盖form.has_changed()以致电self.clean(),现在发生在表单被验证之前。由于form.clean()要求表单经过验证,因此失败。

由于form.full_clean()实际上调用self.has_changed(),因此不能简单地从form.has_changed()内验证表单。您不会在has_changed()中显示您的操作,但在其他位置放置此代码很可能是个好主意。

+0

我使用inlineformset_factory以及编辑视图CreateView和UpdateView。因此,当我在UpdateView中初始化formset时,它将显示外键的ID而不是内联表单中的名称。 因此,在BookForm __init__中,我使用名称填充字段。 '如果self.instance.id和不self.data: 名称= self.instance.name 如果名称: self.initial [ 'SKU'] = name' Django的将其作为变更的数据和标志作为has_changed真。 因此,在has_changed中,我检查名称和相应的ID是否匹配,将has_changed标记为False。 – anshuman

+1

在这种情况下,请查看[changed_data()']的源代码(https://github.com/django/django/blob/stable/1.11.x/django/forms/forms.py#L442 )以查看如何在表单验证之前访问数据。 – knbk

+0

好的,在'try'块中包含'self.cleaned_data'的'has_changed'方法中做了一个解决方法,并在'except'中传递。 – anshuman