Code

Ticket #8620: 8620_3.diff

File 8620_3.diff, 3.4 KB (added by koenb, 3 years ago)

patch with test and doc for 8620

Line 
1Index: docs/topics/forms/modelforms.txt
2===================================================================
3--- docs/topics/forms/modelforms.txt    (revision 17068)
4+++ docs/topics/forms/modelforms.txt    (working copy)
5@@ -516,6 +516,24 @@
6 This adds the extra method from the ``EnhancedArticleForm`` and modifies
7 the original ``ArticleForm.Meta`` to remove one field.
8 
9+If you need to remove a field from the child form that was explicitly defined in
10+a parent form, you can include it in the ``Meta.exclude`` list.
11+
12+An example::
13+
14+    class ArticleForm(ModelForm):
15+        notes = TextField()
16+       
17+        class Meta:
18+            model = Article
19+
20+    class EnhancedArticleForm(ArticleForm):
21+        class Meta(ArticleForm.Meta):
22+            exclude = ('notes',)
23+
24+The ``EnhancedArticleForm`` will not include the field ``notes``, though it was
25+explicitly declared on ``ArticleForm``.
26+
27 There are a couple of things to note, however.
28 
29 * Normal Python name resolution rules apply. If you have multiple base
30Index: django/forms/models.py
31===================================================================
32--- django/forms/models.py      (revision 17068)
33+++ django/forms/models.py      (working copy)
34@@ -215,6 +215,9 @@
35                 raise FieldError(message)
36             # Override default model fields with any custom declared ones
37             # (plus, include all the other declared fields).
38+            # Leave out custom declared fields mentioned in exclude
39+            if opts.exclude:
40+                [declared_fields.pop(f) for f in declared_fields.keys() if f in opts.exclude]
41             fields.update(declared_fields)
42         else:
43             fields = declared_fields
44Index: tests/regressiontests/forms/tests/models.py
45===================================================================
46--- tests/regressiontests/forms/tests/models.py (revision 17068)
47+++ tests/regressiontests/forms/tests/models.py (working copy)
48@@ -5,7 +5,7 @@
49 
50 from django.core.files.uploadedfile import SimpleUploadedFile
51 from django.db import models
52-from django.forms import Form, ModelForm, FileField, ModelChoiceField
53+from django.forms import Form, ModelForm, FileField, ModelChoiceField, CharField
54 from django.forms.models import ModelFormMetaclass
55 from django.test import TestCase
56 
57@@ -160,7 +160,7 @@
58 
59         f = ExcludingForm({'name': u'Hello', 'value': 99, 'def_date': datetime.date(1999, 3, 2)})
60         self.assertTrue(f.is_valid())
61-        self.assertEqual(f.cleaned_data['name'], u'Hello')
62+        self.assertNotIn('name', f.cleaned_data)
63         obj = f.save()
64         self.assertEqual(obj.name, u'class default value')
65         self.assertEqual(obj.value, 99)
66@@ -196,3 +196,21 @@
67             model=A
68 
69         self.assertTrue(issubclass(ModelFormMetaclass('Form', (ModelForm,), {'Meta': Meta}), ModelForm))
70+
71+
72+class TestTicket8620(TestCase):
73+    '''Allow exclusion of not only model fields but also form fields (as
74+    might be defined in a superclass) using the exclude Meta attribute.'''
75+
76+    class ParentForm(ModelForm):
77+        extra_non_model_field = CharField()
78+
79+    class ChildForm(ParentForm):
80+        class Meta:
81+            model = Defaults  # any model is suitable for this test
82+            exclude = ('extra_non_model_field',)
83+
84+    def test_extra_non_model_field_is_excluded(self):
85+        form = TestTicket8620.ChildForm()
86+        self.assertNotIn('extra_non_model_field', form.fields)
87+