Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

newforms: Implemented form_for_instance(). The resulting Form class d…

…oes not yet have a method that saves the changes

git-svn-id: http://code.djangoproject.com/svn/django/trunk@4250 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 71ce11f617cc56024300b4fa968af345329c8ecd 1 parent 2cb0fe7
Adrian Holovaty authored
38  django/db/models/fields/__init__.py
@@ -334,10 +334,10 @@ def _get_choices(self):
334 334
             return self._choices
335 335
     choices = property(_get_choices)
336 336
 
337  
-    def formfield(self):
  337
+    def formfield(self, initial=None):
338 338
         "Returns a django.newforms.Field instance for this database Field."
339 339
         # TODO: This is just a temporary default during development.
340  
-        return forms.CharField(required=not self.blank, label=capfirst(self.verbose_name))
  340
+        return forms.CharField(required=not self.blank, label=capfirst(self.verbose_name), initial=initial)
341 341
 
342 342
 class AutoField(Field):
343 343
     empty_strings_allowed = False
@@ -375,7 +375,7 @@ def contribute_to_class(self, cls, name):
375 375
         super(AutoField, self).contribute_to_class(cls, name)
376 376
         cls._meta.has_auto_field = True
377 377
 
378  
-    def formfield(self):
  378
+    def formfield(self, initial=None):
379 379
         return None
380 380
 
381 381
 class BooleanField(Field):
@@ -392,8 +392,8 @@ def to_python(self, value):
392 392
     def get_manipulator_field_objs(self):
393 393
         return [oldforms.CheckboxField]
394 394
 
395  
-    def formfield(self):
396  
-        return forms.BooleanField(required=not self.blank, label=capfirst(self.verbose_name))
  395
+    def formfield(self, initial=None):
  396
+        return forms.BooleanField(required=not self.blank, label=capfirst(self.verbose_name), initial=initial)
397 397
 
398 398
 class CharField(Field):
399 399
     def get_manipulator_field_objs(self):
@@ -409,8 +409,8 @@ def to_python(self, value):
409 409
                 raise validators.ValidationError, gettext_lazy("This field cannot be null.")
410 410
         return str(value)
411 411
 
412  
-    def formfield(self):
413  
-        return forms.CharField(max_length=self.maxlength, required=not self.blank, label=capfirst(self.verbose_name))
  412
+    def formfield(self, initial=None):
  413
+        return forms.CharField(max_length=self.maxlength, required=not self.blank, label=capfirst(self.verbose_name), initial=initial)
414 414
 
415 415
 # TODO: Maybe move this into contrib, because it's specialized.
416 416
 class CommaSeparatedIntegerField(CharField):
@@ -483,8 +483,8 @@ def flatten_data(self, follow, obj = None):
483 483
         val = self._get_val_from_obj(obj)
484 484
         return {self.attname: (val is not None and val.strftime("%Y-%m-%d") or '')}
485 485
 
486  
-    def formfield(self):
487  
-        return forms.DateField(required=not self.blank, label=capfirst(self.verbose_name))
  486
+    def formfield(self, initial=None):
  487
+        return forms.DateField(required=not self.blank, label=capfirst(self.verbose_name), initial=initial)
488 488
 
489 489
 class DateTimeField(DateField):
490 490
     def to_python(self, value):
@@ -544,8 +544,8 @@ def flatten_data(self,follow, obj = None):
544 544
         return {date_field: (val is not None and val.strftime("%Y-%m-%d") or ''),
545 545
                 time_field: (val is not None and val.strftime("%H:%M:%S") or '')}
546 546
 
547  
-    def formfield(self):
548  
-        return forms.DateTimeField(required=not self.blank, label=capfirst(self.verbose_name))
  547
+    def formfield(self, initial=None):
  548
+        return forms.DateTimeField(required=not self.blank, label=capfirst(self.verbose_name), initial=initial)
549 549
 
550 550
 class EmailField(CharField):
551 551
     def __init__(self, *args, **kwargs):
@@ -561,8 +561,8 @@ def get_manipulator_field_objs(self):
561 561
     def validate(self, field_data, all_data):
562 562
         validators.isValidEmail(field_data, all_data)
563 563
 
564  
-    def formfield(self):
565  
-        return forms.EmailField(required=not self.blank, label=capfirst(self.verbose_name))
  564
+    def formfield(self, initial=None):
  565
+        return forms.EmailField(required=not self.blank, label=capfirst(self.verbose_name), initial=initial)
566 566
 
567 567
 class FileField(Field):
568 568
     def __init__(self, verbose_name=None, name=None, upload_to='', **kwargs):
@@ -696,8 +696,8 @@ class IntegerField(Field):
696 696
     def get_manipulator_field_objs(self):
697 697
         return [oldforms.IntegerField]
698 698
 
699  
-    def formfield(self):
700  
-        return forms.IntegerField(required=not self.blank, label=capfirst(self.verbose_name))
  699
+    def formfield(self, initial=None):
  700
+        return forms.IntegerField(required=not self.blank, label=capfirst(self.verbose_name), initial=initial)
701 701
 
702 702
 class IPAddressField(Field):
703 703
     def __init__(self, *args, **kwargs):
@@ -793,8 +793,8 @@ def flatten_data(self,follow, obj = None):
793 793
         val = self._get_val_from_obj(obj)
794 794
         return {self.attname: (val is not None and val.strftime("%H:%M:%S") or '')}
795 795
 
796  
-    def formfield(self):
797  
-        return forms.TimeField(required=not self.blank, label=capfirst(self.verbose_name))
  796
+    def formfield(self, initial=None):
  797
+        return forms.TimeField(required=not self.blank, label=capfirst(self.verbose_name), initial=initial)
798 798
 
799 799
 class URLField(Field):
800 800
     def __init__(self, verbose_name=None, name=None, verify_exists=True, **kwargs):
@@ -806,8 +806,8 @@ def __init__(self, verbose_name=None, name=None, verify_exists=True, **kwargs):
806 806
     def get_manipulator_field_objs(self):
807 807
         return [oldforms.URLField]
808 808
 
809  
-    def formfield(self):
810  
-        return forms.URLField(required=not self.blank, verify_exists=self.verify_exists, label=capfirst(self.verbose_name))
  809
+    def formfield(self, initial=None):
  810
+        return forms.URLField(required=not self.blank, verify_exists=self.verify_exists, label=capfirst(self.verbose_name), initial=initial)
811 811
 
812 812
 class USStateField(Field):
813 813
     def get_manipulator_field_objs(self):
12  django/db/models/fields/related.py
@@ -548,8 +548,8 @@ def contribute_to_class(self, cls, name):
@@ -612,8 +612,8 @@ def contribute_to_related_class(self, cls, related):
@@ -721,8 +721,8 @@ def contribute_to_related_class(self, cls, related):
28  django/newforms/models.py
@@ -5,10 +5,14 @@
5 5
 
6 6
 from forms import BaseForm, DeclarativeFieldsMetaclass, SortedDictFromList
7 7
 
8  
-__all__ = ('form_for_model', 'form_for_fields')
  8
+__all__ = ('form_for_model', 'form_for_instance', 'form_for_fields')
9 9
 
10 10
 def create(self, save=True):
11  
-    "Creates and returns model instance according to self.clean_data."
  11
+    """
  12
+    Creates and returns model instance according to self.clean_data.
  13
+
  14
+    This method is created for any form_for_model Form.
  15
+    """
12 16
     if self.errors:
13 17
         raise ValueError("The %s could not be created because the data didn't validate." % self._model._meta.object_name)
14 18
     obj = self._model(**self.clean_data)
@@ -16,7 +20,7 @@ def create(self, save=True):
16 20
         obj.save()
17 21
     return obj
18 22
 
19  
-def form_for_model(model, form=None):
  23
+def form_for_model(model, form=BaseForm):
20 24
     """
21 25
     Returns a Form class for the given Django model class.
22 26
 
@@ -29,9 +33,25 @@ def form_for_model(model, form=None):
29 33
         if formfield:
30 34
             field_list.append((f.name, formfield))
31 35
     fields = SortedDictFromList(field_list)
32  
-    form = form or BaseForm
33 36
     return type(opts.object_name + 'Form', (form,), {'fields': fields, '_model': model, 'create': create})
34 37
 
  38
+def form_for_instance(instance, form=BaseForm):
  39
+    """
  40
+    Returns a Form class for the given Django model instance.
  41
+
  42
+    Provide 'form' if you want to use a custom BaseForm subclass.
  43
+    """
  44
+    model = instance.__class__
  45
+    opts = model._meta
  46
+    field_list = []
  47
+    for f in opts.fields + opts.many_to_many:
  48
+        current_value = getattr(instance, f.attname)
  49
+        formfield = f.formfield(initial=current_value)
  50
+        if formfield:
  51
+            field_list.append((f.name, formfield))
  52
+    fields = SortedDictFromList(field_list)
  53
+    return type(opts.object_name + 'InstanceForm', (form,), {'fields': fields, '_model': model})
  54
+
35 55
 def form_for_fields(field_list):
36 56
     "Returns a Form class for the given list of Django database field instances."
37 57
     fields = SortedDictFromList([(f.name, f.formfield()) for f in field_list])
11  tests/modeltests/model_forms/models.py
@@ -36,7 +36,7 @@ def __str__(self):
36 36
         return self.headline
37 37
 
38 38
 __test__ = {'API_TESTS': """
39  
->>> from django.newforms import form_for_model, BaseForm
  39
+>>> from django.newforms import form_for_model, form_for_instance, BaseForm
40 40
 
41 41
 >>> Category.objects.all()
42 42
 []
@@ -141,4 +141,13 @@ def __str__(self):
141 141
 >>> f = CategoryForm()
142 142
 >>> f.say_hello()
143 143
 hello
  144
+
  145
+Use form_for_instance to create a Form from a model instance. The difference
  146
+between this Form and one created via form_for_model is that the object's
  147
+current values are inserted as 'initial' data in each Field.
  148
+>>> w = Writer.objects.get(name='Mike Royko')
  149
+>>> RoykoForm = form_for_instance(w)
  150
+>>> f = RoykoForm(auto_id=False)
  151
+>>> print f
  152
+<tr><th>Name:</th><td><input type="text" name="name" value="Mike Royko" maxlength="50" /></td></tr>
144 153
 """}

0 notes on commit 71ce11f

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