diff options
| author | Malcolm Tredinnick <malcolm.tredinnick@gmail.com> | 2007-05-13 06:23:30 +0000 |
|---|---|---|
| committer | Malcolm Tredinnick <malcolm.tredinnick@gmail.com> | 2007-05-13 06:23:30 +0000 |
| commit | 28f66bb097799f34a6ead02fe4ecafa493cee06b (patch) | |
| tree | 1a80e2849772c92b3fc840487848a5222ea4d1d0 /docs | |
| parent | bc044651aaed9eedbc195414a71bde4e375a7c73 (diff) | |
unicode: Merged from trunk up to [5213].
git-svn-id: http://code.djangoproject.com/svn/django/branches/unicode@5214 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/i18n.txt | 2 | ||||
| -rw-r--r-- | docs/install.txt | 16 | ||||
| -rw-r--r-- | docs/newforms.txt | 305 | ||||
| -rw-r--r-- | docs/templates_python.txt | 6 | ||||
| -rw-r--r-- | docs/testing.txt | 19 |
5 files changed, 324 insertions, 24 deletions
diff --git a/docs/i18n.txt b/docs/i18n.txt index 1d7a0063b2..27abadacc9 100644 --- a/docs/i18n.txt +++ b/docs/i18n.txt @@ -236,7 +236,7 @@ To pluralize, specify both the singular and plural forms with the ``{% plural %}`` tag, which appears within ``{% blocktrans %}`` and ``{% endblocktrans %}``. Example:: - {% blocktrans count list|count as counter %} + {% blocktrans count list|length as counter %} There is only one {{ name }} object. {% plural %} There are {{ counter }} {{ name }} objects. diff --git a/docs/install.txt b/docs/install.txt index 112a92d2f5..6be52aab0d 100644 --- a/docs/install.txt +++ b/docs/install.txt @@ -56,7 +56,7 @@ installed. either ``postgresql`` [for version 1] or ``postgresql_psycopg2`` [for version 2].) If you're on Windows, check out the unofficial `compiled Windows version`_. - + * If you're using MySQL, you'll need MySQLdb_, version 1.2.1p2 or higher. You will also want to read the database-specific notes for the `MySQL backend`_. @@ -75,16 +75,16 @@ installed. Remove any old versions of Django ================================= -If you are upgrading your installation of Django from a previous version, -you will need to uninstall the old Django version before installing the -new version. +If you are upgrading your installation of Django from a previous version, +you will need to uninstall the old Django version before installing the +new version. If you installed Django using ``setup.py install``, uninstalling -is as simple as deleting the ``django`` directory from your Python +is as simple as deleting the ``django`` directory from your Python ``site-packages``. -If you installed Django from a Python Egg, remove the Django ``.egg` file, -and remove the reference to the egg in the file named ``easy-install.pth``. +If you installed Django from a Python Egg, remove the Django ``.egg`` file, +and remove the reference to the egg in the file named ``easy-install.pth``. This file should also be located in your ``site-packages`` directory. .. admonition:: Where are my ``site-packages`` stored? @@ -92,7 +92,7 @@ This file should also be located in your ``site-packages`` directory. The location of the ``site-packages`` directory depends on the operating system, and the location in which Python was installed. However, the following locations are common: - + * If you're using Linux: ``/usr/lib/python2.X/site-packages`` * If you're using Windows: ``C:\Python2.X\lib\site-packages`` diff --git a/docs/newforms.txt b/docs/newforms.txt index ddb850f54c..123b554bde 100644 --- a/docs/newforms.txt +++ b/docs/newforms.txt @@ -870,6 +870,308 @@ custom ``Field`` classes. To do this, just create a subclass of mentioned above (``required``, ``label``, ``initial``, ``widget``, ``help_text``). +Generating forms for models +=========================== + +If you're building a database-driven app, chances are you'll have forms that +map closely to Django models. For instance, you might have a ``BlogComment`` +model, and you want to create a form that lets people submit comments. In this +case, it would be redundant to define the field types in your form, because +you've already defined the fields in your model. + +For this reason, Django provides a few helper functions that let you create a +``Form`` class from a Django model. + +``form_for_model()`` +-------------------- + +The method ``django.newforms.form_for_model()`` creates a form based on the +definition of a specific model. Pass it the model class, and it will return a +``Form`` class that contains a form field for each model field. + +For example:: + + >>> from django.newforms import form_for_model + + # Create the form class. + >>> ArticleForm = form_for_model(Article) + + # Create an empty form instance. + >>> f = ArticleForm() + +It bears repeating that ``form_for_model()`` takes the model *class*, not a +model instance, and it returns a ``Form`` *class*, not a ``Form`` instance. + +Field types +~~~~~~~~~~~ + +The generated ``Form`` class will have a form field for every model field. Each +model field has a corresponding default form field. For example, a +``CharField`` on a model is represented as a ``CharField`` on a form. A +model ``ManyToManyField`` is represented as a ``MultipleChoiceField``. Here is +the full list of conversions: + + =============================== ======================================== + Model field Form field + =============================== ======================================== + ``AutoField`` Not represented in the form + ``BooleanField`` ``BooleanField`` + ``CharField`` ``CharField`` with ``max_length`` set to + the model field's ``maxlength`` + ``CommaSeparatedIntegerField`` ``CharField`` + ``DateField`` ``DateField`` + ``DateTimeField`` ``DateTimeField`` + ``EmailField`` ``EmailField`` + ``FileField`` ``CharField`` + ``FilePathField`` ``CharField`` + ``FloatField`` ``CharField`` + ``ForeignKey`` ``ModelChoiceField`` (see below) + ``ImageField`` ``CharField`` + ``IntegerField`` ``IntegerField`` + ``IPAddressField`` ``CharField`` + ``ManyToManyField`` ``ModelMultipleChoiceField`` (see + below) + ``NullBooleanField`` ``CharField`` + ``PhoneNumberField`` ``USPhoneNumberField`` + (from ``django.contrib.localflavor.us``) + ``PositiveIntegerField`` ``IntegerField`` + ``PositiveSmallIntegerField`` ``IntegerField`` + ``SlugField`` ``CharField`` + ``SmallIntegerField`` ``IntegerField`` + ``TextField`` ``CharField`` with ``widget=Textarea`` + ``TimeField`` ``TimeField`` + ``URLField`` ``URLField`` with ``verify_exists`` set + to the model field's ``verify_exists`` + ``USStateField`` ``CharField`` with + ``widget=USStateSelect`` + (``USStateSelect`` is from + ``django.contrib.localflavor.us``) + ``XMLField`` ``CharField`` with ``widget=Textarea`` + =============================== ======================================== + +As you might expect, the ``ForeignKey`` and ``ManyToManyField`` model field +types are special cases: + + * ``ForeignKey`` is represented by ``django.newforms.ModelChoiceField``, + which is a ``ChoiceField`` whose choices are a model ``QuerySet``. + + * ``ManyToManyField`` is represented by + ``django.newforms.ModelMultipleChoiceField``, which is a + ``MultipleChoiceField`` whose choices are a model ``QuerySet``. + +In addition, each generated form field has attributes set as follows: + + * If the model field has ``blank=True``, then ``required`` is set to + ``False`` on the form field. Otherwise, ``required=True``. + + * The form field's ``label`` is set to the ``verbose_name`` of the model + field, with the first character capitalized. + + * The form field's ``help_text`` is set to the ``help_text`` of the model + field. + + * If the model field has ``choices`` set, then the form field's ``widget`` + will be set to ``Select``, with choices coming from the model field's + ``choices``. + +Finally, note that you can override the form field used for a given model +field. See "Overriding the default field types" below. + +A full example +~~~~~~~~~~~~~~ + +Consider this set of models:: + + from django.db import models + + TITLE_CHOICES = ( + ('MR', 'Mr.'), + ('MRS', 'Mrs.'), + ('MS', 'Ms.'), + ) + + class Author(models.Model): + name = models.CharField(maxlength=100) + title = models.CharField(maxlength=3, choices=TITLE_CHOICES) + birth_date = models.DateField(blank=True, null=True) + + def __str__(self): + return self.name + + class Book(models.Model): + name = models.CharField(maxlength=100) + authors = models.ManyToManyField(Author) + +With these models, a call to ``form_for_model(Author)`` would return a ``Form`` +class equivalent to this:: + + class AuthorForm(forms.Form): + name = forms.CharField(max_length=100) + title = forms.CharField(max_length=3, + widget=forms.Select(choices=TITLE_CHOICES)) + birth_date = forms.DateField(required=False) + +A call to ``form_for_model(Book)`` would return a ``Form`` class equivalent to +this:: + + class BookForm(forms.Form): + name = forms.CharField(max_length=100) + authors = forms.ModelMultipleChoiceField(queryset=Author.objects.all()) + +The ``save()`` method +~~~~~~~~~~~~~~~~~~~~~ + +Every form produced by ``form_for_model()`` also has a ``save()`` method. This +method creates and saves a database object from the data bound to the form. For +example:: + + # Create a form instance from POST data. + >>> f = ArticleForm(request.POST) + + # Save a new Article object from the form's data. + >>> new_article = f.save() + +Note that ``save()`` will raise a ``ValueError`` if the data in the form +doesn't validate -- i.e., ``if form.errors``. + +Using an alternate base class +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you want to add custom methods to the form generated by +``form_for_model()``, write a class that extends ``django.newforms.BaseForm`` +and contains your custom methods. Then, use the ``form`` argument to +``form_for_model()`` to tell it to use your custom form as its base class. +For example:: + + # Create the new base class. + >>> class MyBase(BaseForm): + ... def my_method(self): + ... # Do whatever the method does + + # Create the form class with a different base class. + >>> ArticleForm = form_for_model(Article, form=MyBase) + + # Instantiate the form. + >>> f = ArticleForm() + + # Use the base class method. + >>> f.my_method() + +Using a subset of fields on the form +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**New in Django development version** + +In some cases, you may not want all the model fields to appear on the generated +form. There are two ways of telling ``form_for_model()`` to use only a subset +of the model fields: + + 1. Set ``editable=False`` on the model field. As a result, *any* form + created from the model via ``form_for_model()`` will not include that + field. + + 2. Use the ``fields`` argument to ``form_for_model()``. This argument, if + given, should be a list of field names to include in the form. + + For example, if you want a form for the ``Author`` model (defined above) + that includes only the ``name`` and ``title`` fields, you would specify + ``fields`` like this:: + + PartialArticleForm = form_for_model(Author, fields=('name', 'title')) + +.. note:: + + If you specify ``fields`` when creating a form with ``form_for_model()``, + make sure that the fields that are *not* specified can provide default + values, or are allowed to have a value of ``None``. If a field isn't + specified on a form, the object created from the form can't provide + a value for that attribute, which will prevent the new instance from + being saved. + +Overriding the default field types +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The default field types, as described in the "Field types" table above, are +sensible defaults; if you have a ``DateField`` in your model, chances are you'd +want that to be represented as a ``DateField`` in your form. But +``form_for_model()`` gives you the flexibility of changing the form field type +for a given model field. You do this by specifying a **formfield callback**. + +A formfield callback is a function that, when provided with a model field, +returns a form field instance. When constructing a form, ``form_for_model()`` +asks the formfield callback to provide form field types. + +By default, ``form_for_model()`` calls the ``formfield()`` method on the model +field:: + + def default_callback(field, **kwargs): + return field.formfield(**kwargs) + +The ``kwargs`` are any keyword arguments that might be passed to the form +field, such as ``required=True`` or ``label='Foo'``. + +For example, if you wanted to use ``MyDateFormField`` for any ``DateField`` +field on the model, you could define the callback:: + + >>> def my_callback(field, **kwargs): + ... if isinstance(field, models.DateField): + ... return MyDateFormField(**kwargs) + ... else: + ... return field.formfield(**kwargs) + + >>> ArticleForm = form_for_model(formfield_callback=my_callback) + +Note that your callback needs to handle *all* possible model field types, not +just the ones that you want to behave differently to the default. That's why +this example has an ``else`` clause that implements the default behavior. + +Finding the model associated with a form +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The model class that was used to construct the form is available +using the ``_model`` property of the generated form:: + + >>> ArticleForm = form_for_model(Article) + >>> ArticleForm._model + <class 'myapp.models.Article'> + +``form_for_instance()`` +----------------------- + +``form_for_instance()`` is like ``form_for_model()``, but it takes a model +instance instead of a model class:: + + # Create an Author. + >>> a = Author(name='Joe Smith', title='MR', birth_date=None) + >>> a.save() + + # Create a form for this particular Author. + >>> AuthorForm = form_for_instance(a) + + # Instantiate the form. + >>> f = AuthorForm() + +When a form created by ``form_for_instance()`` is created, the initial +data values for the form fields are drawn from the instance. However, +this data is not bound to the form. You will need to bind data to the +form before the form can be saved. + +When you call ``save()`` on a form created by ``form_for_instance()``, +the database instance will be updated. As in ``form_for_model()``, ``save()`` +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()``. + +When should you use ``form_for_model()`` and ``form_for_instance()``? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``form_for_model()`` and ``form_for_instance()`` functions are meant to be +shortcuts for the common case. If you want to create a form whose fields map to +more than one model, or a form that contains fields that *aren't* on a model, +you shouldn't use these shortcuts. Creating a ``Form`` class the "long" way +isn't that difficult, after all. + More coming soon ================ @@ -880,6 +1182,3 @@ what's possible. If you're really itching to learn and use this library, please be patient. We're working hard on finishing both the code and documentation. - -Widgets -======= diff --git a/docs/templates_python.txt b/docs/templates_python.txt index 853707f58c..08a287f572 100644 --- a/docs/templates_python.txt +++ b/docs/templates_python.txt @@ -717,7 +717,7 @@ object:: # split_contents() knows not to split quoted strings. tag_name, format_string = token.split_contents() except ValueError: - raise template.TemplateSyntaxError, "%r tag requires a single argument" % token.contents[0] + raise template.TemplateSyntaxError, "%r tag requires a single argument" % token.contents.split()[0] if not (format_string[0] == format_string[-1] and format_string[0] in ('"', "'")): raise template.TemplateSyntaxError, "%r tag's argument should be in quotes" % tag_name return CurrentTimeNode(format_string[1:-1]) @@ -846,7 +846,7 @@ Now your tag should begin to look like this:: # split_contents() knows not to split quoted strings. tag_name, date_to_be_formatted, format_string = token.split_contents() except ValueError: - raise template.TemplateSyntaxError, "%r tag requires exactly two arguments" % token.contents[0] + raise template.TemplateSyntaxError, "%r tag requires exactly two arguments" % token.contents.split()[0] if not (format_string[0] == format_string[-1] and format_string[0] in ('"', "'")): raise template.TemplateSyntaxError, "%r tag's argument should be in quotes" % tag_name return FormatTimeNode(date_to_be_formatted, format_string[1:-1]) @@ -1080,7 +1080,7 @@ class, like so:: # Splitting by None == splitting by spaces. tag_name, arg = token.contents.split(None, 1) except ValueError: - raise template.TemplateSyntaxError, "%r tag requires arguments" % token.contents[0] + raise template.TemplateSyntaxError, "%r tag requires arguments" % token.contents.split()[0] m = re.search(r'(.*?) as (\w+)', arg) if not m: raise template.TemplateSyntaxError, "%r tag had invalid arguments" % tag_name diff --git a/docs/testing.txt b/docs/testing.txt index b44b67c20a..dd4e9e17b2 100644 --- a/docs/testing.txt +++ b/docs/testing.txt @@ -177,7 +177,7 @@ tools that can be used to establish tests and test conditions. * `Test Client`_ * `TestCase`_ -* `Email services`_ +* `E-mail services`_ Test Client ----------- @@ -459,9 +459,9 @@ Emptying the test outbox **New in Django development version** At the start of each test case, in addition to installing fixtures, -Django clears the contents of the test email outbox. +Django clears the contents of the test e-mail outbox. -For more detail on email services during tests, see `Email services`_. +For more detail on e-mail services during tests, see `E-mail services`_. Assertions ~~~~~~~~~~ @@ -502,16 +502,17 @@ that can be useful in testing the behavior of web sites. Assert that the template with the given name was used in rendering the response. -Email services +E-mail services -------------- + **New in Django development version** -If your view makes use of the `Django email services`_, you don't really -want email to be sent every time you run a test using that view. +If your view makes use of the `Django e-mail services`_, you don't really +want e-mail to be sent every time you run a test using that view. When the Django test framework is initialized, it transparently replaces the normal `SMTPConnection`_ class with a dummy implementation that redirects all -email to a dummy outbox. This outbox, stored as ``django.core.mail.outbox``, +e-mail to a dummy outbox. This outbox, stored as ``django.core.mail.outbox``, is a simple list of all `EmailMessage`_ instances that have been sent. For example, during test conditions, it would be possible to run the following code:: @@ -541,7 +542,7 @@ to mail.outbox:: # Empty the test outbox mail.outbox = [] -.. _`Django email services`: ../email/ +.. _`Django e-mail services`: ../email/ .. _`SMTPConnection`: ../email/#the-emailmessage-and-smtpconnection-classes .. _`EmailMessage`: ../email/#the-emailmessage-and-smtpconnection-classes .. _`previously`: #emptying-the-test-outbox @@ -669,7 +670,7 @@ a number of utility methods in the ``django.test.utils`` module. ``teardown_test_environment()`` Performs any global post-test teardown, such as removing the instrumentation - of the template rendering system and restoring normal email services. + of the template rendering system and restoring normal e-mail services. ``create_test_db(verbosity=1, autoclobber=False)`` Creates a new test database, and run ``syncdb`` against it. |
