From 2345029d0d607ebeea7e7a6e1bff6c09eaaff4a8 Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Sat, 12 May 2007 15:50:32 +0000 Subject: [PATCH] Fixed #4018 -- Added code to allow callables as initial data in newforms. Thanks for the patch, David Danier. git-svn-id: http://code.djangoproject.com/svn/django/trunk@5209 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- AUTHORS | 1 + django/newforms/forms.py | 2 + tests/regressiontests/forms/tests.py | 58 ++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+) diff --git a/AUTHORS b/AUTHORS index 855717ea64..2352875027 100644 --- a/AUTHORS +++ b/AUTHORS @@ -78,6 +78,7 @@ answer newbie questions, and generally made Django that much better: flavio.curella@gmail.com Jure Cuhalev dackze+django@gmail.com + David Danier Dirk Datzert Jonathan Daugherty (cygnus) dave@thebarproject.com diff --git a/django/newforms/forms.py b/django/newforms/forms.py index 9fafd20787..edd1992cf4 100644 --- a/django/newforms/forms.py +++ b/django/newforms/forms.py @@ -255,6 +255,8 @@ class BoundField(StrAndUnicode): attrs['id'] = auto_id if not self.form.is_bound: data = self.form.initial.get(self.name, self.field.initial) + if callable(data): + data = data() else: data = self.data return widget.render(self.html_name, data, attrs=attrs) diff --git a/tests/regressiontests/forms/tests.py b/tests/regressiontests/forms/tests.py index 0d3a65277c..d6b08a0cd3 100644 --- a/tests/regressiontests/forms/tests.py +++ b/tests/regressiontests/forms/tests.py @@ -2752,6 +2752,64 @@ then the latter will get precedence.
  • Username:
  • Password:
  • +# Callable initial data ######################################################## + +The previous technique dealt with raw values as initial data, but it's also +possible to specify callable data. + +>>> class UserRegistration(Form): +... username = CharField(max_length=10) +... password = CharField(widget=PasswordInput) + +We need to define functions that get called later. +>>> def initial_django(): +... return 'django' +>>> def initial_stephane(): +... return 'stephane' + +Here, we're not submitting any data, so the initial value will be displayed. +>>> p = UserRegistration(initial={'username': initial_django}, auto_id=False) +>>> print p.as_ul() +
  • Username:
  • +
  • Password:
  • + +The 'initial' parameter is meaningless if you pass data. +>>> p = UserRegistration({}, initial={'username': initial_django}, auto_id=False) +>>> print p.as_ul() +
    • This field is required.
    Username:
  • +
    • This field is required.
    Password:
  • +>>> p = UserRegistration({'username': u''}, initial={'username': initial_django}, auto_id=False) +>>> print p.as_ul() +
    • This field is required.
    Username:
  • +
    • This field is required.
    Password:
  • +>>> p = UserRegistration({'username': u'foo'}, initial={'username': initial_django}, auto_id=False) +>>> print p.as_ul() +
  • Username:
  • +
    • This field is required.
    Password:
  • + +A callable 'initial' value is *not* used as a fallback if data is not provided. +In this example, we don't provide a value for 'username', and the form raises a +validation error rather than using the initial value for 'username'. +>>> p = UserRegistration({'password': 'secret'}, initial={'username': initial_django}) +>>> p.errors +{'username': [u'This field is required.']} +>>> p.is_valid() +False + +If a Form defines 'initial' *and* 'initial' is passed as a parameter to Form(), +then the latter will get precedence. +>>> class UserRegistration(Form): +... username = CharField(max_length=10, initial=initial_django) +... password = CharField(widget=PasswordInput) +>>> p = UserRegistration(auto_id=False) +>>> print p.as_ul() +
  • Username:
  • +
  • Password:
  • +>>> p = UserRegistration(initial={'username': initial_stephane}, auto_id=False) +>>> print p.as_ul() +
  • Username:
  • +
  • Password:
  • + # Help text ################################################################### You can specify descriptive text for a field by using the 'help_text' argument