Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fixed #4572 -- Added an example of form_for_instance usage in a full-…

…fledged view. Based on a patch from toddobryan@mac.com.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@5988 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit c06524bc2d132e80cb4602e5b8bffc6f3378b5d4 1 parent 46ec6b3
Malcolm Tredinnick malcolmt authored
Showing with 57 additions and 20 deletions.
  1. +1 −0  AUTHORS
  2. +56 −20 docs/newforms.txt
1  AUTHORS
View
@@ -213,6 +213,7 @@ answer newbie questions, and generally made Django that much better:
Fraser Nevett <mail@nevett.org>
Sam Newman <http://www.magpiebrain.com/>
Neal Norwitz <nnorwitz@google.com>
+ Todd O'Bryan <toddobryan@mac.com>
oggie rob <oz.robharvey@gmail.com>
Jay Parlar <parlar@gmail.com>
pavithran s <pavithran.s@gmail.com>
76 docs/newforms.txt
View
@@ -1459,10 +1459,10 @@ commonly used groups of widgets:
``Textarea`` ``<textarea>...</textarea>``
``CheckboxInput`` ``<input type='checkbox' ...``
``Select`` ``<select><option ...``
- ``NullBooleanSelect`` Select widget with options 'Unknown',
+ ``NullBooleanSelect`` Select widget with options 'Unknown',
'Yes' and 'No'
``SelectMultiple`` ``<select multiple='multiple'><option ...``
- ``RadioSelect`` ``<ul><li><input type='radio' ...``
+ ``RadioSelect`` ``<ul><li><input type='radio' ...``
``CheckboxSelectMultiple`` ``<ul><li><input type='checkbox' ...``
``MultiWidget`` Wrapper around multiple other widgets
``SplitDateTimeWidget`` Wrapper around two ``TextInput`` widgets:
@@ -1473,19 +1473,19 @@ Specifying widgets
------------------
Whenever you specify a field on a form, Django will use a default widget
-that is appropriate to the type of data that is to be displayed. To find
+that is appropriate to the type of data that is to be displayed. To find
which widget is used on which field, see the documentation for the
built-in Field classes.
-However, if you want to use a different widget for a field, you can -
+However, if you want to use a different widget for a field, you can -
just use the 'widget' argument on the field definition. For example::
class CommentForm(forms.Form):
name = forms.CharField()
url = forms.URLField()
comment = forms.CharField(widget=forms.Textarea)
-
-This would specify a form with a comment that uses a larger Textarea widget,
+
+This would specify a form with a comment that uses a larger Textarea widget,
rather than the default TextInput widget.
Customizing widget instances
@@ -1496,8 +1496,8 @@ HTML - Django doesn't add a class definition, or any other widget-specific
attributes. This means that all 'TextInput' widgets will appear the same
on your web page.
-If you want to make one widget look different to another, you need to
-specify additional attributes for each widget. When you specify a
+If you want to make one widget look different to another, you need to
+specify additional attributes for each widget. When you specify a
widget, you can provide a list of attributes that will be added to the
rendered HTML for the widget.
@@ -1519,13 +1519,13 @@ each widget will be rendered exactly the same::
<tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr>
On a real web page, you probably don't want every widget to look the same. You
-might want a larger input element for the comment, and you might want the
-'name' widget to have some special CSS class. To do this, you specify a
-custom widget for your fields, and specify some attributes to use
+might want a larger input element for the comment, and you might want the
+'name' widget to have some special CSS class. To do this, you specify a
+custom widget for your fields, and specify some attributes to use
when rendering those widgets::
class CommentForm(forms.Form):
- name = forms.CharField(
+ name = forms.CharField(
widget=forms.TextInput(attrs={'class':'special'}))
url = forms.URLField()
comment = forms.CharField(
@@ -1543,19 +1543,19 @@ Custom Widgets
--------------
When you start to write a lot of forms, you will probably find that you will
-reuse certain sets of widget attributes over and over again. Rather than
-repeat these attribute definitions every time you need them, Django allows
+reuse certain sets of widget attributes over and over again. Rather than
+repeat these attribute definitions every time you need them, Django allows
you to capture those definitions as a custom widget.
For example, if you find that you are including a lot of comment fields on forms,
-you could capture the idea of a ``TextInput`` with a specific ``size`` attribute
+you could capture the idea of a ``TextInput`` with a specific ``size`` attribute
as a custom extension to the ``TextInput`` widget::
class CommentWidget(forms.TextInput):
def __init__(self, *args, **kwargs):
kwargs.setdefault('attrs',{}).update({'size': '40'})
super(forms.TextInput, self).__init__(*args, **kwargs)
-
+
Then you can use this widget in your forms::
class CommentForm(forms.Form):
@@ -1563,8 +1563,8 @@ Then you can use this widget in your forms::
url = forms.URLField()
comment = forms.CharField(widget=CommentWidget)
-You can even customize your custom widget, in the same way as you would
-any other widget. Adding a once-off class to your ``CommentWidget`` is as
+You can even customize your custom widget, in the same way as you would
+any other widget. Adding a once-off class to your ``CommentWidget`` is as
simple as adding an attribute definition::
class CommentForm(forms.Form):
@@ -1579,14 +1579,14 @@ by defining::
class CommentInput(forms.CharField):
widget = CommentWidget
-
+
You can then use this field whenever you have a form that requires a comment::
class CommentForm(forms.Form):
name = forms.CharField()
url = forms.URLField()
comment = CommentInput()
-
+
Generating forms for models
===========================
@@ -1931,6 +1931,42 @@ will raise ``ValueError`` if the data doesn't validate.
``form_for_instance()`` has ``form``, ``fields`` and ``formfield_callback``
arguments that behave the same way as they do for ``form_for_model()``.
+Let's modify the earlier `contact form`_ view example a little bit. Suppose we
+have a ``Message`` model that holds each contact submission. Something like::
+
+ class Message(models.Model):
+ subject = models.CharField(max_length=100)
+ message = models.TextField()
+ sender = models.EmailField()
+ cc_myself = models.BooleanField()
+
+You could use this model to create a form (using ``form_for_model()``). You
+could also use existing ``Message`` instances to create a form for editing
+messages. The earlier_ view can be changed slightly to accept the ``id`` value
+of an existing ``Message`` and present it for editing::
+
+ def contact_edit(request, msg_id):
+ # Create the form from the message id.
+ message = get_object_or_404(Message, id=msg_id)
+ ContactForm = form_for_instance(message)
+
+ if request.method == 'POST':
+ form = ContactForm(request.POST)
+ if form.is_valid():
+ form.save()
+ return HttpResponseRedirect('/url/on_success/')
+ else:
+ form = ContactForm()
+ return render_to_response('contact.html', {'form': form})
+
+Aside from how we create the ``ContactForm`` class here, the main point to
+note is that the form display in the ``GET`` branch of the function
+will use the values from the ``message`` instance as initial values for the
+form field.
+
+.. _contact form: `Simple view example`_
+.. _earlier: `Simple view example`_
+
When should you use ``form_for_model()`` and ``form_for_instance()``?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Please sign in to comment.
Something went wrong with that request. Please try again.