Merge remote-tracking branch 'django/master' into t3011

This commit is contained in:
Russell Keith-Magee 2012-09-15 20:18:37 +08:00
commit 579f152e4a
9 changed files with 317 additions and 85 deletions

View File

@ -191,7 +191,8 @@ class GeoModelTest(TestCase):
cities1 = City.objects.all() cities1 = City.objects.all()
# Only PostGIS would support a 'select *' query because of its recognized # Only PostGIS would support a 'select *' query because of its recognized
# HEXEWKB format for geometry fields # HEXEWKB format for geometry fields
cities2 = City.objects.raw('select id, name, asText(point) from geoapp_city') as_text = 'ST_AsText' if postgis else 'asText'
cities2 = City.objects.raw('select id, name, %s(point) from geoapp_city' % as_text)
self.assertEqual(len(cities1), len(list(cities2))) self.assertEqual(len(cities1), len(list(cities2)))
self.assertTrue(isinstance(cities2[0].point, Point)) self.assertTrue(isinstance(cities2[0].point, Point))

View File

@ -187,6 +187,14 @@ The ``ContentTypeManager``
probably won't ever need to call this method yourself; Django will call probably won't ever need to call this method yourself; Django will call
it automatically when it's needed. it automatically when it's needed.
.. method:: get_for_id(id)
Lookup a :class:`~django.contrib.contenttypes.models.ContentType` by ID.
Since this method uses the same shared cache as
:meth:`~django.contrib.contenttypes.models.ContentTypeManager.get_for_model`,
it's preferred to use this method over the usual
``ContentType.objects.get(pk=id)``
.. method:: get_for_model(model[, for_concrete_model=True]) .. method:: get_for_model(model[, for_concrete_model=True])
Takes either a model class or an instance of a model, and returns the Takes either a model class or an instance of a model, and returns the

View File

@ -155,7 +155,8 @@ or the
:meth:`~django.views.generic.base.TemplateResponseMixin.get_template_names()` :meth:`~django.views.generic.base.TemplateResponseMixin.get_template_names()`
method, which are documented in the method, which are documented in the
:class:`~django.views.generic.base.TemplateResponseMixin` documentation. The :class:`~django.views.generic.base.TemplateResponseMixin` documentation. The
latter one allows you to use a different template for each form. latter one allows you to use a different template for each form (:ref:`see the
example below <wizard-template-for-each-form>`).
This template expects a ``wizard`` object that has various items attached to This template expects a ``wizard`` object that has various items attached to
it: it:
@ -238,6 +239,65 @@ wizard's :meth:`as_view` method takes a list of your
(r'^contact/$', ContactWizard.as_view([ContactForm1, ContactForm2])), (r'^contact/$', ContactWizard.as_view([ContactForm1, ContactForm2])),
) )
.. _wizard-template-for-each-form:
Using a different template for each form
----------------------------------------
As mentioned above, you may specify a different template for each form.
Consider an example using a form wizard to implement a multi-step checkout
process for an online store. In the first step, the user specifies a billing
and shipping address. In the second step, the user chooses payment type. If
they chose to pay by credit card, they will enter credit card information in
the next step. In the final step, they will confirm the purchase.
Here's what the view code might look like::
from django.http import HttpResponseRedirect
from django.contrib.formtools.wizard.views import SessionWizardView
FORMS = [("address", myapp.forms.AddressForm),
("paytype", myapp.forms.PaymentChoiceForm),
("cc", myapp.forms.CreditCardForm),
("confirmation", myapp.forms.OrderForm)]
TEMPLATES = {"address": "checkout/billingaddress.html",
"paytype": "checkout/paymentmethod.html",
"cc": "checkout/creditcard.html",
"confirmation": "checkout/confirmation.html"}
def pay_by_credit_card(wizard):
"""Return true if user opts to pay by credit card"""
# Get cleaned data from payment step
cleaned_data = wizard.get_cleaned_data_for_step('paytype') or {'method': 'none'}
# Return true if the user selected credit card
return cleaned_data['method'] == 'cc'
class OrderWizard(SessionWizardView):
def get_template_names(self):
return [TEMPLATES[self.steps.current]]
def done(self, form_list, **kwargs):
do_something_with_the_form_data(form_list)
return HttpResponseRedirect('/page-to-redirect-to-when-done/')
...
The ``urls.py`` file would contain something like::
urlpatterns = patterns('',
(r'^checkout/$', OrderWizard.as_view(FORMS, condition_dict={'cc': pay_by_credit_card})),
)
Note that the ``OrderWizard`` object is initialized with a list of pairs.
The first element in the pair is a string that corresponds to the name of the
step and the second is the form class.
In this example, the
:meth:`~django.views.generic.base.TemplateResponseMixin.get_template_names()`
method returns a list containing a single template, which is selected based on
the name of the current step.
.. _wizardview-advanced-methods: .. _wizardview-advanced-methods:
Advanced ``WizardView`` methods Advanced ``WizardView`` methods

View File

@ -674,8 +674,8 @@ __ http://spatialreference.org/ref/epsg/32140/
.. admonition:: Raw queries .. admonition:: Raw queries
When using :doc:`raw queries </topics/db/sql>`, you should generally wrap When using :doc:`raw queries </topics/db/sql>`, you should generally wrap
your geometry fields with the ``asText()`` SQL function so as the field your geometry fields with the ``asText()`` SQL function (or ``ST_AsText``
value will be recognized by GEOS:: for PostGIS) so as the field value will be recognized by GEOS::
City.objects.raw('SELECT id, name, asText(point) from myapp_city') City.objects.raw('SELECT id, name, asText(point) from myapp_city')

View File

@ -852,7 +852,7 @@ Slightly complex built-in ``Field`` classes
``MultiValueField`` ``MultiValueField``
~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~
.. class:: MultiValueField(**kwargs) .. class:: MultiValueField(fields=(), **kwargs)
* Default widget: ``TextInput`` * Default widget: ``TextInput``
* Empty value: ``''`` (an empty string) * Empty value: ``''`` (an empty string)
@ -861,22 +861,39 @@ Slightly complex built-in ``Field`` classes
as an argument to the ``MultiValueField``. as an argument to the ``MultiValueField``.
* Error message keys: ``required``, ``invalid`` * Error message keys: ``required``, ``invalid``
This abstract field (must be subclassed) aggregates the logic of multiple Aggregates the logic of multiple fields that together produce a single
fields. Subclasses should not have to implement clean(). Instead, they must value.
implement compress(), which takes a list of valid values and returns a
"compressed" version of those values -- a single value. For example, This field is abstract and must be subclassed. In contrast with the
:class:`SplitDateTimeField` is a subclass which combines a time field and single-value fields, subclasses of :class:`MultiValueField` must not
a date field into a datetime object. implement :meth:`~django.forms.Field.clean` but instead - implement
:meth:`~MultiValueField.compress`.
Takes one extra required argument: Takes one extra required argument:
.. attribute:: fields .. attribute:: fields
A list of fields which are cleaned into a single field. Each value in A tuple of fields whose values are cleaned and subsequently combined
``clean`` is cleaned by the corresponding field in ``fields`` -- the first into a single value. Each value of the field is cleaned by the
value is cleaned by the first field, the second value is cleaned by corresponding field in ``fields`` -- the first value is cleaned by the
the second field, etc. Once all fields are cleaned, the list of clean first field, the second value is cleaned by the second field, etc.
values is "compressed" into a single value. Once all fields are cleaned, the list of clean values is combined into
a single value by :meth:`~MultiValueField.compress`.
.. attribute:: MultiValueField.widget
Must be a subclass of :class:`django.forms.MultiWidget`.
Default value is :class:`~django.forms.widgets.TextInput`, which
probably is not very useful in this case.
.. method:: compress(data_list)
Takes a list of valid values and returns a "compressed" version of
those values -- in a single value. For example,
:class:`SplitDateTimeField` is a subclass which combines a time field
and a date field into a ``datetime`` object.
This method must be implemented in the subclasses.
``SplitDateTimeField`` ``SplitDateTimeField``
~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~

View File

@ -11,6 +11,16 @@ A widget is Django's representation of a HTML input element. The widget
handles the rendering of the HTML, and the extraction of data from a GET/POST handles the rendering of the HTML, and the extraction of data from a GET/POST
dictionary that corresponds to the widget. dictionary that corresponds to the widget.
.. tip::
Widgets should not be confused with the :doc:`form fields </ref/forms/fields>`.
Form fields deal with the logic of input validation and are used directly
in templates. Widgets deal with rendering of HTML form input elements on
the web page and extraction of raw submitted data. However, widgets do
need to be :ref:`assigned <widget-to-field>` to form fields.
.. _widget-to-field:
Specifying widgets Specifying widgets
------------------ ------------------
@ -95,15 +105,23 @@ choices are inherent to the model and not just the representational widget.
Customizing widget instances Customizing widget instances
---------------------------- ----------------------------
When Django renders a widget as HTML, it only renders the bare minimum When Django renders a widget as HTML, it only renders very minimal markup -
HTML - Django doesn't add a class definition, or any other widget-specific Django doesn't add class names, or any other widget-specific attributes. This
attributes. This means that all :class:`TextInput` widgets will appear the same means, for example, that all :class:`TextInput` widgets will appear the same
on your Web page. on your Web pages.
If you want to make one widget look different to another, you need to There are two ways to customize widgets: :ref:`per widget instance
specify additional attributes for each widget. When you specify a <styling-widget-instances>` and :ref:`per widget class <styling-widget-classes>`.
widget, you can provide a list of attributes that will be added to the
rendered HTML for the widget. .. _styling-widget-instances:
Styling widget instances
^^^^^^^^^^^^^^^^^^^^^^^^
If you want to make one widget instance look different from another, you will
need to specify additional attributes at the time when the widget object is
instantiated and assigned to a form field (and perhaps add some rules to your
CSS files).
For example, take the following simple form:: For example, take the following simple form::
@ -128,9 +146,7 @@ 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 might want a larger input element for the comment, and you might want the
'name' widget to have some special CSS class. It is also possible to specify 'name' widget to have some special CSS class. It is also possible to specify
the 'type' attribute to take advantage of the new HTML5 input types. To do the 'type' attribute to take advantage of the new HTML5 input types. To do
this, you use the :attr:`Widget.attrs` argument when creating the widget: this, you use the :attr:`Widget.attrs` argument when creating the widget::
For example::
class CommentForm(forms.Form): class CommentForm(forms.Form):
name = forms.CharField( name = forms.CharField(
@ -147,24 +163,41 @@ Django will then include the extra attributes in the rendered output:
<tr><th>Url:</th><td><input type="text" name="url"/></td></tr> <tr><th>Url:</th><td><input type="text" name="url"/></td></tr>
<tr><th>Comment:</th><td><input type="text" name="comment" size="40"/></td></tr> <tr><th>Comment:</th><td><input type="text" name="comment" size="40"/></td></tr>
.. _built-in widgets: .. _styling-widget-classes:
Built-in widgets Styling widget classes
---------------- ^^^^^^^^^^^^^^^^^^^^^^
Django provides a representation of all the basic HTML widgets, plus some With widgets, it is possible to add media (``css`` and ``javascript``)
commonly used groups of widgets: and more deeply customize their appearance and behavior.
``Widget`` In a nutshell, you will need to subclass the widget and either
~~~~~~~~~~ :ref:`define a class "Media" <media-as-a-static-definition>` as a member of the
subclass, or :ref:`create a property "media" <dynamic-property>`, returning an
instance of that class.
.. class:: Widget These methods involve somewhat advanced Python programming and are described in
detail in the :doc:`Form Media </topics/forms/media>` topic guide.
This abstract class cannot be rendered, but provides the basic attribute :attr:`~Widget.attrs`. .. _base-widget-classes:
Base Widget classes
-------------------
Base widget classes :class:`Widget` and :class:`MultiWidget` are subclassed by
all the :ref:`built-in widgets <built-in widgets>` and may serve as a
foundation for custom widgets.
.. class:: Widget(attrs=None)
This abstract class cannot be rendered, but provides the basic attribute
:attr:`~Widget.attrs`. You may also implement or override the
:meth:`~Widget.render()` method on custom widgets.
.. attribute:: Widget.attrs .. attribute:: Widget.attrs
A dictionary containing HTML attributes to be set on the rendered widget. A dictionary containing HTML attributes to be set on the rendered
widget.
.. code-block:: python .. code-block:: python
@ -172,6 +205,74 @@ commonly used groups of widgets:
>>> name.render('name', 'A name') >>> name.render('name', 'A name')
u'<input title="Your name" type="text" name="name" value="A name" size="10" />' u'<input title="Your name" type="text" name="name" value="A name" size="10" />'
.. method:: render(name, value, attrs=None)
Returns HTML for the widget, as a Unicode string. This method must be
implemented by the subclass, otherwise ``NotImplementedError`` will be
raised.
The 'value' given is not guaranteed to be valid input, therefore
subclass implementations should program defensively.
.. class:: MultiWidget(widgets, attrs=None)
A widget that is composed of multiple widgets.
:class:`~django.forms.widgets.MultiWidget` works hand in hand with the
:class:`~django.forms.MultiValueField`.
.. method:: render(name, value, attrs=None)
Argument `value` is handled differently in this method from the
subclasses of :class:`~Widget`.
If `value` is a list, output of :meth:`~MultiWidget.render` will be a
concatenation of rendered child widgets. If `value` is not a list, it
will be first processed by the method :meth:`~MultiWidget.decompress()`
to create the list and then processed as above.
Unlike in the single value widgets, method :meth:`~MultiWidget.render`
need not be implemented in the subclasses.
.. method:: decompress(value)
Returns a list of "decompressed" values for the given value of the
multi-value field that makes use of the widget. The input value can be
assumed as valid, but not necessarily non-empty.
This method **must be implemented** by the subclass, and since the
value may be empty, the implementation must be defensive.
The rationale behind "decompression" is that it is necessary to "split"
the combined value of the form field into the values of the individual
field encapsulated within the multi-value field (e.g. when displaying
the partially or fully filled-out form).
.. tip::
Note that :class:`~django.forms.MultiValueField` has a
complementary method :meth:`~django.forms.MultiValueField.compress`
with the opposite responsibility - to combine cleaned values of
all member fields into one.
.. _built-in widgets:
Built-in widgets
----------------
Django provides a representation of all the basic HTML widgets, plus some
commonly used groups of widgets in the ``django.forms.widgets`` module,
including :ref:`the input of text <text-widgets>`, :ref:`various checkboxes
and selectors <selector-widgets>`, :ref:`uploading files <file-upload-widgets>`,
and :ref:`handling of multi-valued input <composite-widgets>`.
.. _text-widgets:
Widgets handling input of text
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
These widgets make use of the HTML elements ``input`` and ``textarea``.
``TextInput`` ``TextInput``
~~~~~~~~~~~~~ ~~~~~~~~~~~~~
@ -205,39 +306,8 @@ commonly used groups of widgets:
Hidden input: ``<input type='hidden' ...>`` Hidden input: ``<input type='hidden' ...>``
``MultipleHiddenInput`` Note that there also is a :class:`MultipleHiddenInput` widget that
~~~~~~~~~~~~~~~~~~~~~~~ encapsulates a set of hidden input elements.
.. class:: MultipleHiddenInput
Multiple ``<input type='hidden' ...>`` widgets.
A widget that handles multiple hidden widgets for fields that have a list
of values.
.. attribute:: MultipleHiddenInput.choices
This attribute is optional when the field does not have a
:attr:`~Field.choices` attribute. If it does, it will override anything
you set here when the attribute is updated on the :class:`Field`.
``FileInput``
~~~~~~~~~~~~~
.. class:: FileInput
File upload input: ``<input type='file' ...>``
``ClearableFileInput``
~~~~~~~~~~~~~~~~~~~~~~
.. class:: ClearableFileInput
.. versionadded:: 1.3
File upload input: ``<input type='file' ...>``, with an additional checkbox
input to clear the field's value, if the field is not required and has
initial data.
``DateInput`` ``DateInput``
~~~~~~~~~~~~~ ~~~~~~~~~~~~~
@ -297,6 +367,11 @@ commonly used groups of widgets:
Text area: ``<textarea>...</textarea>`` Text area: ``<textarea>...</textarea>``
.. _selector-widgets:
Selector and checkbox widgets
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
``CheckboxInput`` ``CheckboxInput``
~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~
@ -440,6 +515,50 @@ commonly used groups of widgets:
... ...
</ul> </ul>
.. _file-upload-widgets:
File upload widgets
^^^^^^^^^^^^^^^^^^^
``FileInput``
~~~~~~~~~~~~~
.. class:: FileInput
File upload input: ``<input type='file' ...>``
``ClearableFileInput``
~~~~~~~~~~~~~~~~~~~~~~
.. class:: ClearableFileInput
.. versionadded:: 1.3
File upload input: ``<input type='file' ...>``, with an additional checkbox
input to clear the field's value, if the field is not required and has
initial data.
.. _composite-widgets:
Composite widgets
^^^^^^^^^^^^^^^^^
``MultipleHiddenInput``
~~~~~~~~~~~~~~~~~~~~~~~
.. class:: MultipleHiddenInput
Multiple ``<input type='hidden' ...>`` widgets.
A widget that handles multiple hidden widgets for fields that have a list
of values.
.. attribute:: MultipleHiddenInput.choices
This attribute is optional when the field does not have a
:attr:`~Field.choices` attribute. If it does, it will override anything
you set here when the attribute is updated on the :class:`Field`.
``MultiWidget`` ``MultiWidget``
~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~

View File

@ -1338,9 +1338,6 @@ Default: ``'/accounts/logout/'``
LOGIN_URL counterpart. LOGIN_URL counterpart.
.. note::
See the `note on LOGIN_REDIRECT_URL setting`_
.. setting:: MANAGERS .. setting:: MANAGERS
MANAGERS MANAGERS

View File

@ -660,6 +660,36 @@ the handler, if ``created`` is ``True``, create the associated user profile::
.. seealso:: :doc:`/topics/signals` for more information on Django's signal .. seealso:: :doc:`/topics/signals` for more information on Django's signal
dispatcher. dispatcher.
Adding UserProfile fields to the admin
--------------------------------------
To add the UserProfile fields to the user page in the admin, define an
:class:`~django.contrib.admin.InlineModelAdmin` (for this example, we'll use a
:class:`~django.contrib.admin.StackedInline`) in your app's ``admin.py`` and
add it to a ``UserAdmin`` class which is registered with the
:class:`~django.contrib.auth.models.User` class::
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User
from my_user_profile_app.models import UserProfile
# Define an inline admin descriptor for UserProfile model
# which acts a bit like a singleton
class UserProfileInline(admin.StackedInline):
model = UserProfile
can_delete = False
verbose_name_plural = 'profile'
# Define a new User admin
class UserAdmin(UserAdmin):
inlines = (UserProfileInline, )
# Re-register UserAdmin
admin.site.unregister(User)
admin.site.register(User, UserAdmin)
Authentication in Web requests Authentication in Web requests
============================== ==============================

View File

@ -38,6 +38,8 @@ in a form suitable for easy inclusion on your Web page.
whichever toolkit suits your requirements. Django is able to integrate whichever toolkit suits your requirements. Django is able to integrate
with any JavaScript toolkit. with any JavaScript toolkit.
.. _media-as-a-static-definition:
Media as a static definition Media as a static definition
---------------------------- ----------------------------
@ -78,10 +80,8 @@ A dictionary describing the CSS files required for various forms of output
media. media.
The values in the dictionary should be a tuple/list of file names. See The values in the dictionary should be a tuple/list of file names. See
`the section on media paths`_ for details of how to specify paths to media :ref:`the section on media paths <form-media-paths>` for details of how to
files. specify paths to media files.
.. _the section on media paths: `Paths in media definitions`_
The keys in the dictionary are the output media types. These are the same The keys in the dictionary are the output media types. These are the same
types accepted by CSS files in media declarations: 'all', 'aural', 'braille', types accepted by CSS files in media declarations: 'all', 'aural', 'braille',
@ -117,8 +117,8 @@ If this last CSS definition were to be rendered, it would become the following H
``js`` ``js``
~~~~~~ ~~~~~~
A tuple describing the required JavaScript files. See A tuple describing the required JavaScript files. See :ref:`the section on
`the section on media paths`_ for details of how to specify paths to media media paths <form-media-paths>` for details of how to specify paths to media
files. files.
``extend`` ``extend``
@ -164,10 +164,10 @@ declaration to the media declaration::
<script type="text/javascript" src="http://static.example.com/whizbang.js"></script> <script type="text/javascript" src="http://static.example.com/whizbang.js"></script>
If you require even more control over media inheritance, define your media If you require even more control over media inheritance, define your media
using a `dynamic property`_. Dynamic properties give you complete control over using a :ref:`dynamic property <dynamic-property>`. Dynamic properties give
which media files are inherited, and which are not. you complete control over which media files are inherited, and which are not.
.. _dynamic property: `Media as a dynamic property`_ .. _dynamic-property:
Media as a dynamic property Media as a dynamic property
--------------------------- ---------------------------
@ -198,9 +198,9 @@ Paths in media definitions
.. versionchanged:: 1.3 .. versionchanged:: 1.3
Paths used to specify media can be either relative or absolute. If a path Paths used to specify media can be either relative or absolute. If a path
starts with '/', 'http://' or 'https://', it will be interpreted as an absolute starts with ``/``, ``http://`` or ``https://``, it will be interpreted as an
path, and left as-is. All other paths will be prepended with the value of absolute path, and left as-is. All other paths will be prepended with the value
the appropriate prefix. of the appropriate prefix.
As part of the introduction of the As part of the introduction of the
:doc:`staticfiles app </ref/contrib/staticfiles>` two new settings were added :doc:`staticfiles app </ref/contrib/staticfiles>` two new settings were added