Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed #7888 -- Handle model inheritance with model formsets correctly…

…. Thanks bpeschier for the report.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@8528 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 82a1d5471cba138d90b5bb99d8313486af06d56a 1 parent 05e8c3e
Brian Rosner authored August 25, 2008
1  django/db/models/fields/__init__.py
@@ -97,6 +97,7 @@ def __init__(self, verbose_name=None, name=None, primary_key=False,
97 97
         self.help_text = help_text
98 98
         self.db_column = db_column
99 99
         self.db_tablespace = db_tablespace or settings.DEFAULT_INDEX_TABLESPACE
  100
+        self.auto_created = auto_created
100 101
 
101 102
         # Set db_index to True if the field has a relationship and doesn't explicitly set db_index.
102 103
         self.db_index = db_index
6  django/forms/models.py
@@ -96,7 +96,7 @@ def model_to_dict(instance, fields=None, exclude=None):
96 96
     the ``fields`` argument.
97 97
     """
98 98
     # avoid a circular import
99  
-    from django.db.models.fields.related import ManyToManyField
  99
+    from django.db.models.fields.related import ManyToManyField, OneToOneField
100 100
     opts = instance._meta
101 101
     data = {}
102 102
     for f in opts.fields + opts.many_to_many:
@@ -115,6 +115,8 @@ def model_to_dict(instance, fields=None, exclude=None):
115 115
             else:
116 116
                 # MultipleChoiceWidget needs a list of pks, not object instances.
117 117
                 data[f.name] = [obj.pk for obj in f.value_from_object(instance)]
  118
+        elif isinstance(f, OneToOneField):
  119
+            data[f.attname] = f.value_from_object(instance)
118 120
         else:
119 121
             data[f.name] = f.value_from_object(instance)
120 122
     return data
@@ -317,7 +319,7 @@ def save_new_objects(self, commit=True):
317 319
 
318 320
     def add_fields(self, form, index):
319 321
         """Add a hidden field for the object's primary key."""
320  
-        if self.model._meta.has_auto_field:
  322
+        if self.model._meta.pk.auto_created:
321 323
             self._pk_field_name = self.model._meta.pk.attname
322 324
             form.fields[self._pk_field_name] = IntegerField(required=False, widget=HiddenInput)
323 325
         super(BaseModelFormSet, self).add_fields(form, index)
16  tests/modeltests/model_forms/models.py
@@ -13,6 +13,12 @@
13 13
 from django.db import models
14 14
 from django.core.files.storage import FileSystemStorage
15 15
 
  16
+# Python 2.3 doesn't have sorted()
  17
+try:
  18
+    sorted
  19
+except NameError:
  20
+    from django.utils.itercompat import sorted
  21
+
16 22
 temp_storage = FileSystemStorage(tempfile.gettempdir())
17 23
 
18 24
 ARTICLE_STATUS = (
@@ -60,6 +66,9 @@ class ImprovedArticle(models.Model):
60 66
 class ImprovedArticleWithParentLink(models.Model):
61 67
     article = models.OneToOneField(Article, parent_link=True)
62 68
 
  69
+class BetterWriter(Writer):
  70
+    pass
  71
+
63 72
 class PhoneNumber(models.Model):
64 73
     phone = models.PhoneNumberField()
65 74
     description = models.CharField(max_length=20)
@@ -91,7 +100,7 @@ def __unicode__(self):
91 100
 
92 101
 __test__ = {'API_TESTS': """
93 102
 >>> from django import forms
94  
->>> from django.forms.models import ModelForm
  103
+>>> from django.forms.models import ModelForm, model_to_dict
95 104
 >>> from django.core.files.uploadedfile import SimpleUploadedFile
96 105
 
97 106
 The bare bones, absolutely nothing custom, basic case.
@@ -793,6 +802,11 @@ def __unicode__(self):
793 802
 >>> ImprovedArticleWithParentLinkForm.base_fields.keys()
794 803
 []
795 804
 
  805
+>>> bw = BetterWriter(name=u'Joe Better')
  806
+>>> bw.save()
  807
+>>> sorted(model_to_dict(bw).keys())
  808
+['id', 'name', 'writer_ptr_id']
  809
+
796 810
 # PhoneNumberField ############################################################
797 811
 
798 812
 >>> class PhoneNumberForm(ModelForm):
50  tests/modeltests/model_formsets/models.py
@@ -14,6 +14,9 @@ class Meta:
14 14
     def __unicode__(self):
15 15
         return self.name
16 16
 
  17
+class BetterAuthor(Author):
  18
+    write_speed = models.IntegerField()
  19
+
17 20
 class Book(models.Model):
18 21
     author = models.ForeignKey(Author)
19 22
     title = models.CharField(max_length=100)
@@ -229,6 +232,53 @@ class CustomPrimaryKey(models.Model):
229 232
 >>> [sorted(x.items()) for x in formset.initial]
230 233
 [[('id', 1), ('name', u'Charles Baudelaire')], [('id', 3), ('name', u'Paul Verlaine')], [('id', 2), ('name', u'Walt Whitman')]]
231 234
 
  235
+# Model inheritance in model formsets ########################################
  236
+
  237
+>>> BetterAuthorFormSet = modelformset_factory(BetterAuthor)
  238
+>>> formset = BetterAuthorFormSet()
  239
+>>> for form in formset.forms:
  240
+...     print form.as_p()
  241
+<p><label for="id_form-0-name">Name:</label> <input id="id_form-0-name" type="text" name="form-0-name" maxlength="100" /></p>
  242
+<p><label for="id_form-0-write_speed">Write speed:</label> <input type="text" name="form-0-write_speed" id="id_form-0-write_speed" /><input type="hidden" name="form-0-author_ptr_id" id="id_form-0-author_ptr_id" /></p>
  243
+
  244
+>>> data = {
  245
+...     'form-TOTAL_FORMS': '1', # the number of forms rendered
  246
+...     'form-INITIAL_FORMS': '0', # the number of forms with initial data
  247
+...     'form-0-author_ptr_id': '',
  248
+...     'form-0-name': 'Ernest Hemingway',
  249
+...     'form-0-write_speed': '10',
  250
+... }
  251
+
  252
+>>> formset = BetterAuthorFormSet(data)
  253
+>>> formset.is_valid()
  254
+True
  255
+>>> formset.save()
  256
+[<BetterAuthor: Ernest Hemingway>]
  257
+
  258
+>>> formset = BetterAuthorFormSet()
  259
+>>> for form in formset.forms:
  260
+...     print form.as_p()
  261
+<p><label for="id_form-0-name">Name:</label> <input id="id_form-0-name" type="text" name="form-0-name" value="Ernest Hemingway" maxlength="100" /></p>
  262
+<p><label for="id_form-0-write_speed">Write speed:</label> <input type="text" name="form-0-write_speed" value="10" id="id_form-0-write_speed" /><input type="hidden" name="form-0-author_ptr_id" value="4" id="id_form-0-author_ptr_id" /></p>
  263
+<p><label for="id_form-1-name">Name:</label> <input id="id_form-1-name" type="text" name="form-1-name" maxlength="100" /></p>
  264
+<p><label for="id_form-1-write_speed">Write speed:</label> <input type="text" name="form-1-write_speed" id="id_form-1-write_speed" /><input type="hidden" name="form-1-author_ptr_id" id="id_form-1-author_ptr_id" /></p>
  265
+
  266
+>>> data = {
  267
+...     'form-TOTAL_FORMS': '2', # the number of forms rendered
  268
+...     'form-INITIAL_FORMS': '1', # the number of forms with initial data
  269
+...     'form-0-author_ptr_id': '4',
  270
+...     'form-0-name': 'Ernest Hemingway',
  271
+...     'form-0-write_speed': '10',
  272
+...     'form-1-author_ptr_id': '',
  273
+...     'form-1-name': '',
  274
+...     'form-1-write_speed': '',
  275
+... }
  276
+
  277
+>>> formset = BetterAuthorFormSet(data)
  278
+>>> formset.is_valid()
  279
+True
  280
+>>> formset.save()
  281
+[]
232 282
 
233 283
 # Inline Formsets ############################################################
234 284
 

0 notes on commit 82a1d54

Please sign in to comment.
Something went wrong with that request. Please try again.