Fixed #20000 -- Allowed ModelForm meta overrides for label, help_text and error_messages
This commit is contained in:
parent
dc9c359546
commit
9e50833e22
|
@ -138,7 +138,9 @@ def model_to_dict(instance, fields=None, exclude=None):
|
||||||
data[f.name] = f.value_from_object(instance)
|
data[f.name] = f.value_from_object(instance)
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def fields_for_model(model, fields=None, exclude=None, widgets=None, formfield_callback=None, localized_fields=None):
|
def fields_for_model(model, fields=None, exclude=None, widgets=None,
|
||||||
|
formfield_callback=None, localized_fields=None,
|
||||||
|
labels=None, help_texts=None, error_messages=None):
|
||||||
"""
|
"""
|
||||||
Returns a ``SortedDict`` containing form fields for the given model.
|
Returns a ``SortedDict`` containing form fields for the given model.
|
||||||
|
|
||||||
|
@ -149,7 +151,16 @@ def fields_for_model(model, fields=None, exclude=None, widgets=None, formfield_c
|
||||||
fields will be excluded from the returned fields, even if they are listed
|
fields will be excluded from the returned fields, even if they are listed
|
||||||
in the ``fields`` argument.
|
in the ``fields`` argument.
|
||||||
|
|
||||||
``widgets`` is a dictionary of model field names mapped to a widget
|
``widgets`` is a dictionary of model field names mapped to a widget.
|
||||||
|
|
||||||
|
``localized_fields`` is a list of names of fields which should be localized.
|
||||||
|
|
||||||
|
``labels`` is a dictionary of model field names mapped to a label.
|
||||||
|
|
||||||
|
``help_texts`` is a dictionary of model field names mapped to a help text.
|
||||||
|
|
||||||
|
``error_messages`` is a dictionary of model field names mapped to a
|
||||||
|
dictionary of error messages.
|
||||||
|
|
||||||
``formfield_callback`` is a callable that takes a model field and returns
|
``formfield_callback`` is a callable that takes a model field and returns
|
||||||
a form field.
|
a form field.
|
||||||
|
@ -170,6 +181,12 @@ def fields_for_model(model, fields=None, exclude=None, widgets=None, formfield_c
|
||||||
kwargs['widget'] = widgets[f.name]
|
kwargs['widget'] = widgets[f.name]
|
||||||
if localized_fields == ALL_FIELDS or (localized_fields and f.name in localized_fields):
|
if localized_fields == ALL_FIELDS or (localized_fields and f.name in localized_fields):
|
||||||
kwargs['localize'] = True
|
kwargs['localize'] = True
|
||||||
|
if labels and f.name in labels:
|
||||||
|
kwargs['label'] = labels[f.name]
|
||||||
|
if help_texts and f.name in help_texts:
|
||||||
|
kwargs['help_text'] = help_texts[f.name]
|
||||||
|
if error_messages and f.name in error_messages:
|
||||||
|
kwargs['error_messages'] = error_messages[f.name]
|
||||||
|
|
||||||
if formfield_callback is None:
|
if formfield_callback is None:
|
||||||
formfield = f.formfield(**kwargs)
|
formfield = f.formfield(**kwargs)
|
||||||
|
@ -197,6 +214,9 @@ class ModelFormOptions(object):
|
||||||
self.exclude = getattr(options, 'exclude', None)
|
self.exclude = getattr(options, 'exclude', None)
|
||||||
self.widgets = getattr(options, 'widgets', None)
|
self.widgets = getattr(options, 'widgets', None)
|
||||||
self.localized_fields = getattr(options, 'localized_fields', None)
|
self.localized_fields = getattr(options, 'localized_fields', None)
|
||||||
|
self.labels = getattr(options, 'labels', None)
|
||||||
|
self.help_texts = getattr(options, 'help_texts', None)
|
||||||
|
self.error_messages = getattr(options, 'error_messages', None)
|
||||||
|
|
||||||
|
|
||||||
class ModelFormMetaclass(type):
|
class ModelFormMetaclass(type):
|
||||||
|
@ -248,7 +268,9 @@ class ModelFormMetaclass(type):
|
||||||
opts.fields = None
|
opts.fields = None
|
||||||
|
|
||||||
fields = fields_for_model(opts.model, opts.fields, opts.exclude,
|
fields = fields_for_model(opts.model, opts.fields, opts.exclude,
|
||||||
opts.widgets, formfield_callback, opts.localized_fields)
|
opts.widgets, formfield_callback,
|
||||||
|
opts.localized_fields, opts.labels,
|
||||||
|
opts.help_texts, opts.error_messages)
|
||||||
|
|
||||||
# make sure opts.fields doesn't specify an invalid field
|
# make sure opts.fields doesn't specify an invalid field
|
||||||
none_model_fields = [k for k, v in six.iteritems(fields) if not v]
|
none_model_fields = [k for k, v in six.iteritems(fields) if not v]
|
||||||
|
@ -416,7 +438,8 @@ class ModelForm(six.with_metaclass(ModelFormMetaclass, BaseModelForm)):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def modelform_factory(model, form=ModelForm, fields=None, exclude=None,
|
def modelform_factory(model, form=ModelForm, fields=None, exclude=None,
|
||||||
formfield_callback=None, widgets=None, localized_fields=None):
|
formfield_callback=None, widgets=None, localized_fields=None,
|
||||||
|
labels=None, help_texts=None, error_messages=None):
|
||||||
"""
|
"""
|
||||||
Returns a ModelForm containing form fields for the given model.
|
Returns a ModelForm containing form fields for the given model.
|
||||||
|
|
||||||
|
@ -434,6 +457,13 @@ def modelform_factory(model, form=ModelForm, fields=None, exclude=None,
|
||||||
|
|
||||||
``formfield_callback`` is a callable that takes a model field and returns
|
``formfield_callback`` is a callable that takes a model field and returns
|
||||||
a form field.
|
a form field.
|
||||||
|
|
||||||
|
``labels`` is a dictionary of model field names mapped to a label.
|
||||||
|
|
||||||
|
``help_texts`` is a dictionary of model field names mapped to a help text.
|
||||||
|
|
||||||
|
``error_messages`` is a dictionary of model field names mapped to a
|
||||||
|
dictionary of error messages.
|
||||||
"""
|
"""
|
||||||
# Create the inner Meta class. FIXME: ideally, we should be able to
|
# Create the inner Meta class. FIXME: ideally, we should be able to
|
||||||
# construct a ModelForm without creating and passing in a temporary
|
# construct a ModelForm without creating and passing in a temporary
|
||||||
|
@ -449,6 +479,12 @@ def modelform_factory(model, form=ModelForm, fields=None, exclude=None,
|
||||||
attrs['widgets'] = widgets
|
attrs['widgets'] = widgets
|
||||||
if localized_fields is not None:
|
if localized_fields is not None:
|
||||||
attrs['localized_fields'] = localized_fields
|
attrs['localized_fields'] = localized_fields
|
||||||
|
if labels is not None:
|
||||||
|
attrs['labels'] = labels
|
||||||
|
if help_texts is not None:
|
||||||
|
attrs['help_texts'] = help_texts
|
||||||
|
if error_messages is not None:
|
||||||
|
attrs['error_messages'] = error_messages
|
||||||
|
|
||||||
# If parent form class already has an inner Meta, the Meta we're
|
# If parent form class already has an inner Meta, the Meta we're
|
||||||
# creating needs to inherit from the parent's inner meta.
|
# creating needs to inherit from the parent's inner meta.
|
||||||
|
@ -738,7 +774,8 @@ class BaseModelFormSet(BaseFormSet):
|
||||||
def modelformset_factory(model, form=ModelForm, formfield_callback=None,
|
def modelformset_factory(model, form=ModelForm, formfield_callback=None,
|
||||||
formset=BaseModelFormSet, extra=1, can_delete=False,
|
formset=BaseModelFormSet, extra=1, can_delete=False,
|
||||||
can_order=False, max_num=None, fields=None, exclude=None,
|
can_order=False, max_num=None, fields=None, exclude=None,
|
||||||
widgets=None, validate_max=False, localized_fields=None):
|
widgets=None, validate_max=False, localized_fields=None,
|
||||||
|
labels=None, help_texts=None, error_messages=None):
|
||||||
"""
|
"""
|
||||||
Returns a FormSet class for the given Django model class.
|
Returns a FormSet class for the given Django model class.
|
||||||
"""
|
"""
|
||||||
|
@ -759,7 +796,8 @@ def modelformset_factory(model, form=ModelForm, formfield_callback=None,
|
||||||
|
|
||||||
form = modelform_factory(model, form=form, fields=fields, exclude=exclude,
|
form = modelform_factory(model, form=form, fields=fields, exclude=exclude,
|
||||||
formfield_callback=formfield_callback,
|
formfield_callback=formfield_callback,
|
||||||
widgets=widgets, localized_fields=localized_fields)
|
widgets=widgets, localized_fields=localized_fields,
|
||||||
|
labels=labels, help_texts=help_texts, error_messages=error_messages)
|
||||||
FormSet = formset_factory(form, formset, extra=extra, max_num=max_num,
|
FormSet = formset_factory(form, formset, extra=extra, max_num=max_num,
|
||||||
can_order=can_order, can_delete=can_delete,
|
can_order=can_order, can_delete=can_delete,
|
||||||
validate_max=validate_max)
|
validate_max=validate_max)
|
||||||
|
@ -898,7 +936,8 @@ def inlineformset_factory(parent_model, model, form=ModelForm,
|
||||||
formset=BaseInlineFormSet, fk_name=None,
|
formset=BaseInlineFormSet, fk_name=None,
|
||||||
fields=None, exclude=None, extra=3, can_order=False,
|
fields=None, exclude=None, extra=3, can_order=False,
|
||||||
can_delete=True, max_num=None, formfield_callback=None,
|
can_delete=True, max_num=None, formfield_callback=None,
|
||||||
widgets=None, validate_max=False, localized_fields=None):
|
widgets=None, validate_max=False, localized_fields=None,
|
||||||
|
labels=None, help_texts=None, error_messages=None):
|
||||||
"""
|
"""
|
||||||
Returns an ``InlineFormSet`` for the given kwargs.
|
Returns an ``InlineFormSet`` for the given kwargs.
|
||||||
|
|
||||||
|
@ -922,6 +961,9 @@ def inlineformset_factory(parent_model, model, form=ModelForm,
|
||||||
'widgets': widgets,
|
'widgets': widgets,
|
||||||
'validate_max': validate_max,
|
'validate_max': validate_max,
|
||||||
'localized_fields': localized_fields,
|
'localized_fields': localized_fields,
|
||||||
|
'labels': labels,
|
||||||
|
'help_texts': help_texts,
|
||||||
|
'error_messages': error_messages,
|
||||||
}
|
}
|
||||||
FormSet = modelformset_factory(model, **kwargs)
|
FormSet = modelformset_factory(model, **kwargs)
|
||||||
FormSet.fk = fk
|
FormSet.fk = fk
|
||||||
|
|
|
@ -5,7 +5,7 @@ Model Form Functions
|
||||||
.. module:: django.forms.models
|
.. module:: django.forms.models
|
||||||
:synopsis: Django's functions for building model forms and formsets.
|
:synopsis: Django's functions for building model forms and formsets.
|
||||||
|
|
||||||
.. function:: modelform_factory(model, form=ModelForm, fields=None, exclude=None, formfield_callback=None, widgets=None, localized_fields=None)
|
.. function:: modelform_factory(model, form=ModelForm, fields=None, exclude=None, formfield_callback=None, widgets=None, localized_fields=None, labels=None, help_texts=None, error_messages=None)
|
||||||
|
|
||||||
Returns a :class:`~django.forms.ModelForm` class for the given ``model``.
|
Returns a :class:`~django.forms.ModelForm` class for the given ``model``.
|
||||||
You can optionally pass a ``form`` argument to use as a starting point for
|
You can optionally pass a ``form`` argument to use as a starting point for
|
||||||
|
@ -20,11 +20,18 @@ Model Form Functions
|
||||||
|
|
||||||
``widgets`` is a dictionary of model field names mapped to a widget.
|
``widgets`` is a dictionary of model field names mapped to a widget.
|
||||||
|
|
||||||
``localized_fields`` is a list of names of fields which should be localized.
|
|
||||||
|
|
||||||
``formfield_callback`` is a callable that takes a model field and returns
|
``formfield_callback`` is a callable that takes a model field and returns
|
||||||
a form field.
|
a form field.
|
||||||
|
|
||||||
|
``localized_fields`` is a list of names of fields which should be localized.
|
||||||
|
|
||||||
|
``labels`` is a dictionary of model field names mapped to a label.
|
||||||
|
|
||||||
|
``help_texts`` is a dictionary of model field names mapped to a help text.
|
||||||
|
|
||||||
|
``error_messages`` is a dictionary of model field names mapped to a
|
||||||
|
dictionary of error messages.
|
||||||
|
|
||||||
See :ref:`modelforms-factory` for example usage.
|
See :ref:`modelforms-factory` for example usage.
|
||||||
|
|
||||||
.. versionchanged:: 1.6
|
.. versionchanged:: 1.6
|
||||||
|
@ -35,14 +42,16 @@ Model Form Functions
|
||||||
information. Omitting any definition of the fields to use will result in all
|
information. Omitting any definition of the fields to use will result in all
|
||||||
fields being used, but this behavior is deprecated.
|
fields being used, but this behavior is deprecated.
|
||||||
|
|
||||||
The ``localized_fields`` parameter was added.
|
The ``localized_fields``, ``labels``, ``help_texts``, and
|
||||||
|
``error_messages`` parameters were added.
|
||||||
|
|
||||||
.. function:: modelformset_factory(model, form=ModelForm, formfield_callback=None, formset=BaseModelFormSet, extra=1, can_delete=False, can_order=False, max_num=None, fields=None, exclude=None, widgets=None, validate_max=False, localized_fields=None)
|
.. function:: modelformset_factory(model, form=ModelForm, formfield_callback=None, formset=BaseModelFormSet, extra=1, can_delete=False, can_order=False, max_num=None, fields=None, exclude=None, widgets=None, validate_max=False, localized_fields=None, labels=None, help_texts=None, error_messages=None)
|
||||||
|
|
||||||
Returns a ``FormSet`` class for the given ``model`` class.
|
Returns a ``FormSet`` class for the given ``model`` class.
|
||||||
|
|
||||||
Arguments ``model``, ``form``, ``fields``, ``exclude``,
|
Arguments ``model``, ``form``, ``fields``, ``exclude``,
|
||||||
``formfield_callback``, ``widgets`` and ``localized_fields`` are all passed through to
|
``formfield_callback``, ``widgets``, ``localized_fields``, ``labels``,
|
||||||
|
``help_texts``, and ``error_messages`` are all passed through to
|
||||||
:func:`~django.forms.models.modelform_factory`.
|
:func:`~django.forms.models.modelform_factory`.
|
||||||
|
|
||||||
Arguments ``formset``, ``extra``, ``max_num``, ``can_order``,
|
Arguments ``formset``, ``extra``, ``max_num``, ``can_order``,
|
||||||
|
@ -54,9 +63,10 @@ Model Form Functions
|
||||||
|
|
||||||
.. versionchanged:: 1.6
|
.. versionchanged:: 1.6
|
||||||
|
|
||||||
The ``widgets``, ``validate_max`` and ``localized_fields`` parameters were added.
|
The ``widgets``, ``validate_max``, ``localized_fields``, ``labels``,
|
||||||
|
``help_texts``, and ``error_messages`` parameters were added.
|
||||||
|
|
||||||
.. function:: inlineformset_factory(parent_model, model, form=ModelForm, formset=BaseInlineFormSet, fk_name=None, fields=None, exclude=None, extra=3, can_order=False, can_delete=True, max_num=None, formfield_callback=None, widgets=None, validate_max=False, localized_fields=None)
|
.. function:: inlineformset_factory(parent_model, model, form=ModelForm, formset=BaseInlineFormSet, fk_name=None, fields=None, exclude=None, extra=3, can_order=False, can_delete=True, max_num=None, formfield_callback=None, widgets=None, validate_max=False, localized_fields=None, labels=None, help_texts=None, error_messages=None)
|
||||||
|
|
||||||
Returns an ``InlineFormSet`` using :func:`modelformset_factory` with
|
Returns an ``InlineFormSet`` using :func:`modelformset_factory` with
|
||||||
defaults of ``formset=BaseInlineFormSet``, ``can_delete=True``, and
|
defaults of ``formset=BaseInlineFormSet``, ``can_delete=True``, and
|
||||||
|
@ -69,4 +79,5 @@ Model Form Functions
|
||||||
|
|
||||||
.. versionchanged:: 1.6
|
.. versionchanged:: 1.6
|
||||||
|
|
||||||
The ``widgets``, ``validate_max`` and ``localized_fields`` parameters were added.
|
The ``widgets``, ``validate_max`` and ``localized_fields``, ``labels``,
|
||||||
|
``help_texts``, and ``error_messages`` parameters were added.
|
||||||
|
|
|
@ -236,9 +236,14 @@ Minor features
|
||||||
.. _`Pillow`: https://pypi.python.org/pypi/Pillow
|
.. _`Pillow`: https://pypi.python.org/pypi/Pillow
|
||||||
.. _`PIL`: https://pypi.python.org/pypi/PIL
|
.. _`PIL`: https://pypi.python.org/pypi/PIL
|
||||||
|
|
||||||
* :doc:`ModelForm </topics/forms/modelforms/>` accepts a new
|
* :class:`~django.forms.ModelForm` accepts several new ``Meta``
|
||||||
Meta option: ``localized_fields``. Fields included in this list will be localized
|
options.
|
||||||
(by setting ``localize`` on the form field).
|
|
||||||
|
* Fields included in the ``localized_fields`` list will be localized
|
||||||
|
(by setting ``localize`` on the form field).
|
||||||
|
* The ``labels``, ``help_texts`` and ``error_messages`` options may be used
|
||||||
|
to customize the default fields, see
|
||||||
|
:ref:`modelforms-overriding-default-fields` for details.
|
||||||
|
|
||||||
* The ``choices`` argument to model fields now accepts an iterable of iterables
|
* The ``choices`` argument to model fields now accepts an iterable of iterables
|
||||||
instead of requiring an iterable of lists or tuples.
|
instead of requiring an iterable of lists or tuples.
|
||||||
|
|
|
@ -141,7 +141,7 @@ In addition, each generated form field has attributes set as follows:
|
||||||
``default`` value will be initially selected instead).
|
``default`` value will be initially selected instead).
|
||||||
|
|
||||||
Finally, note that you can override the form field used for a given model
|
Finally, note that you can override the form field used for a given model
|
||||||
field. See `Overriding the default field types or widgets`_ below.
|
field. See `Overriding the default fields`_ below.
|
||||||
|
|
||||||
A full example
|
A full example
|
||||||
--------------
|
--------------
|
||||||
|
@ -388,8 +388,10 @@ include that field.
|
||||||
|
|
||||||
.. _section on saving forms: `The save() method`_
|
.. _section on saving forms: `The save() method`_
|
||||||
|
|
||||||
Overriding the default field types or widgets
|
.. _modelforms-overriding-default-fields:
|
||||||
---------------------------------------------
|
|
||||||
|
Overriding the default fields
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
The default field types, as described in the `Field types`_ table above, are
|
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
|
sensible defaults. If you have a ``DateField`` in your model, chances are you'd
|
||||||
|
@ -420,38 +422,65 @@ widget::
|
||||||
The ``widgets`` dictionary accepts either widget instances (e.g.,
|
The ``widgets`` dictionary accepts either widget instances (e.g.,
|
||||||
``Textarea(...)``) or classes (e.g., ``Textarea``).
|
``Textarea(...)``) or classes (e.g., ``Textarea``).
|
||||||
|
|
||||||
If you want to further customize a field -- including its type, label, etc. --
|
.. versionadded:: 1.6
|
||||||
you can do this by declaratively specifying fields like you would in a regular
|
|
||||||
``Form``. Declared fields will override the default ones generated by using the
|
|
||||||
``model`` attribute.
|
|
||||||
|
|
||||||
For example, if you wanted to use ``MyDateFormField`` for the ``pub_date``
|
The ``labels``, ``help_texts`` and ``error_messages`` options were added.
|
||||||
|
|
||||||
|
Similarly, you can specify the ``labels``, ``help_texts`` and ``error_messages``
|
||||||
|
attributes of the inner ``Meta`` class if you want to further customize a field.
|
||||||
|
|
||||||
|
For example if you wanted to customize the wording of all user facing strings for
|
||||||
|
the ``name`` field::
|
||||||
|
|
||||||
|
class AuthorForm(ModelForm):
|
||||||
|
class Meta:
|
||||||
|
model = Author
|
||||||
|
fields = ('name', 'title', 'birth_date')
|
||||||
|
labels = {
|
||||||
|
'name': _('Writer'),
|
||||||
|
}
|
||||||
|
help_texts = {
|
||||||
|
'name': _('Some useful help text.'),
|
||||||
|
}
|
||||||
|
error_messages = {
|
||||||
|
'name': {
|
||||||
|
'max_length': _("This writer's name is too long."),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
Finally, if you want complete control over of a field -- including its type,
|
||||||
|
validators, etc. -- you can do this by declaratively specifying fields like you
|
||||||
|
would in a regular ``Form``. Declared fields will override the default ones
|
||||||
|
generated by using the ``model`` attribute. Fields declared like this will
|
||||||
|
ignore any customizations in the ``widgets``, ``labels``, ``help_texts``, and
|
||||||
|
``error_messages`` options declared on ``Meta``.
|
||||||
|
|
||||||
|
For example, if you wanted to use ``MySlugFormField`` for the ``slug``
|
||||||
field, you could do the following::
|
field, you could do the following::
|
||||||
|
|
||||||
from django.forms import ModelForm
|
from django.forms import ModelForm
|
||||||
from myapp.models import Article
|
from myapp.models import Article
|
||||||
|
|
||||||
class ArticleForm(ModelForm):
|
class ArticleForm(ModelForm):
|
||||||
pub_date = MyDateFormField()
|
slug = MySlugFormField()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Article
|
model = Article
|
||||||
fields = ['pub_date', 'headline', 'content', 'reporter']
|
fields = ['pub_date', 'headline', 'content', 'reporter']
|
||||||
|
|
||||||
|
|
||||||
If you want to override a field's default label, then specify the ``label``
|
If you want to override a field's default validators, then specify the
|
||||||
parameter when declaring the form field::
|
``validators`` parameter when declaring the form field::
|
||||||
|
|
||||||
from django.forms import ModelForm, DateField
|
from django.forms import ModelForm, DateField
|
||||||
from myapp.models import Article
|
from myapp.models import Article
|
||||||
|
|
||||||
class ArticleForm(ModelForm):
|
class ArticleForm(ModelForm):
|
||||||
pub_date = DateField(label='Publication date')
|
slug = CharField(validators=[validate_slug])
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Article
|
model = Article
|
||||||
fields = ['pub_date', 'headline', 'content', 'reporter']
|
fields = ['pub_date', 'headline', 'content', 'reporter', 'slug']
|
||||||
|
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
|
@ -597,7 +626,7 @@ example by specifying the widgets to be used for a given field::
|
||||||
|
|
||||||
>>> from django.forms import Textarea
|
>>> from django.forms import Textarea
|
||||||
>>> Form = modelform_factory(Book, form=BookForm,
|
>>> Form = modelform_factory(Book, form=BookForm,
|
||||||
widgets={"title": Textarea()})
|
... widgets={"title": Textarea()})
|
||||||
|
|
||||||
The fields to include can be specified using the ``fields`` and ``exclude``
|
The fields to include can be specified using the ``fields`` and ``exclude``
|
||||||
keyword arguments, or the corresponding attributes on the ``ModelForm`` inner
|
keyword arguments, or the corresponding attributes on the ``ModelForm`` inner
|
||||||
|
|
|
@ -490,7 +490,7 @@ class ModelFormBaseTest(TestCase):
|
||||||
['slug', 'name'])
|
['slug', 'name'])
|
||||||
|
|
||||||
|
|
||||||
class TestWidgetForm(forms.ModelForm):
|
class FieldOverridesTroughFormMetaForm(forms.ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Category
|
model = Category
|
||||||
fields = ['name', 'url', 'slug']
|
fields = ['name', 'url', 'slug']
|
||||||
|
@ -498,25 +498,74 @@ class TestWidgetForm(forms.ModelForm):
|
||||||
'name': forms.Textarea,
|
'name': forms.Textarea,
|
||||||
'url': forms.TextInput(attrs={'class': 'url'})
|
'url': forms.TextInput(attrs={'class': 'url'})
|
||||||
}
|
}
|
||||||
|
labels = {
|
||||||
|
'name': 'Title',
|
||||||
|
}
|
||||||
|
help_texts = {
|
||||||
|
'slug': 'Watch out! Letters, numbers, underscores and hyphens only.',
|
||||||
|
}
|
||||||
|
error_messages = {
|
||||||
|
'slug': {
|
||||||
|
'invalid': (
|
||||||
|
"Didn't you read the help text? "
|
||||||
|
"We said letters, numbers, underscores and hyphens only!"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class TestFieldOverridesTroughFormMeta(TestCase):
|
||||||
|
def test_widget_overrides(self):
|
||||||
|
form = FieldOverridesTroughFormMetaForm()
|
||||||
|
self.assertHTMLEqual(
|
||||||
|
str(form['name']),
|
||||||
|
'<textarea id="id_name" rows="10" cols="40" name="name"></textarea>',
|
||||||
|
)
|
||||||
|
self.assertHTMLEqual(
|
||||||
|
str(form['url']),
|
||||||
|
'<input id="id_url" type="text" class="url" name="url" maxlength="40" />',
|
||||||
|
)
|
||||||
|
self.assertHTMLEqual(
|
||||||
|
str(form['slug']),
|
||||||
|
'<input id="id_slug" type="text" name="slug" maxlength="20" />',
|
||||||
|
)
|
||||||
|
|
||||||
class TestWidgets(TestCase):
|
def test_label_overrides(self):
|
||||||
def test_base_widgets(self):
|
form = FieldOverridesTroughFormMetaForm()
|
||||||
frm = TestWidgetForm()
|
|
||||||
self.assertHTMLEqual(
|
self.assertHTMLEqual(
|
||||||
str(frm['name']),
|
str(form['name'].label_tag()),
|
||||||
'<textarea id="id_name" rows="10" cols="40" name="name"></textarea>'
|
'<label for="id_name">Title:</label>',
|
||||||
)
|
)
|
||||||
self.assertHTMLEqual(
|
self.assertHTMLEqual(
|
||||||
str(frm['url']),
|
str(form['url'].label_tag()),
|
||||||
'<input id="id_url" type="text" class="url" name="url" maxlength="40" />'
|
'<label for="id_url">The URL:</label>',
|
||||||
)
|
)
|
||||||
self.assertHTMLEqual(
|
self.assertHTMLEqual(
|
||||||
str(frm['slug']),
|
str(form['slug'].label_tag()),
|
||||||
'<input id="id_slug" type="text" name="slug" maxlength="20" />'
|
'<label for="id_slug">Slug:</label>',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_help_text_overrides(self):
|
||||||
|
form = FieldOverridesTroughFormMetaForm()
|
||||||
|
self.assertEqual(
|
||||||
|
form['slug'].help_text,
|
||||||
|
'Watch out! Letters, numbers, underscores and hyphens only.',
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_error_messages_overrides(self):
|
||||||
|
form = FieldOverridesTroughFormMetaForm(data={
|
||||||
|
'name': 'Category',
|
||||||
|
'url': '/category/',
|
||||||
|
'slug': '!%#*@',
|
||||||
|
})
|
||||||
|
form.full_clean()
|
||||||
|
|
||||||
|
error = [
|
||||||
|
"Didn't you read the help text? "
|
||||||
|
"We said letters, numbers, underscores and hyphens only!",
|
||||||
|
]
|
||||||
|
self.assertEqual(form.errors, {'slug': error})
|
||||||
|
|
||||||
|
|
||||||
class IncompleteCategoryFormWithFields(forms.ModelForm):
|
class IncompleteCategoryFormWithFields(forms.ModelForm):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -1261,7 +1261,7 @@ class ModelFormsetTest(TestCase):
|
||||||
['Please correct the duplicate data for subtitle which must be unique for the month in posted.'])
|
['Please correct the duplicate data for subtitle which must be unique for the month in posted.'])
|
||||||
|
|
||||||
|
|
||||||
class TestModelFormsetWidgets(TestCase):
|
class TestModelFormsetOverridesTroughFormMeta(TestCase):
|
||||||
def test_modelformset_factory_widgets(self):
|
def test_modelformset_factory_widgets(self):
|
||||||
widgets = {
|
widgets = {
|
||||||
'name': forms.TextInput(attrs={'class': 'poet'})
|
'name': forms.TextInput(attrs={'class': 'poet'})
|
||||||
|
@ -1283,3 +1283,53 @@ class TestModelFormsetWidgets(TestCase):
|
||||||
"%s" % form['title'],
|
"%s" % form['title'],
|
||||||
'<input class="book" id="id_title" maxlength="100" name="title" type="text" />'
|
'<input class="book" id="id_title" maxlength="100" name="title" type="text" />'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_modelformset_factory_labels_overrides(self):
|
||||||
|
BookFormSet = modelformset_factory(Book, fields="__all__", labels={
|
||||||
|
'title': 'Name'
|
||||||
|
})
|
||||||
|
form = BookFormSet.form()
|
||||||
|
self.assertHTMLEqual(form['title'].label_tag(), '<label for="id_title">Name:</label>')
|
||||||
|
|
||||||
|
def test_inlineformset_factory_labels_overrides(self):
|
||||||
|
BookFormSet = inlineformset_factory(Author, Book, fields="__all__", labels={
|
||||||
|
'title': 'Name'
|
||||||
|
})
|
||||||
|
form = BookFormSet.form()
|
||||||
|
self.assertHTMLEqual(form['title'].label_tag(), '<label for="id_title">Name:</label>')
|
||||||
|
|
||||||
|
def test_modelformset_factory_help_text_overrides(self):
|
||||||
|
BookFormSet = modelformset_factory(Book, fields="__all__", help_texts={
|
||||||
|
'title': 'Choose carefully.'
|
||||||
|
})
|
||||||
|
form = BookFormSet.form()
|
||||||
|
self.assertEqual(form['title'].help_text, 'Choose carefully.')
|
||||||
|
|
||||||
|
def test_inlineformset_factory_help_text_overrides(self):
|
||||||
|
BookFormSet = inlineformset_factory(Author, Book, fields="__all__", help_texts={
|
||||||
|
'title': 'Choose carefully.'
|
||||||
|
})
|
||||||
|
form = BookFormSet.form()
|
||||||
|
self.assertEqual(form['title'].help_text, 'Choose carefully.')
|
||||||
|
|
||||||
|
def test_modelformset_factory_error_messages_overrides(self):
|
||||||
|
author = Author.objects.create(pk=1, name='Charles Baudelaire')
|
||||||
|
BookFormSet = modelformset_factory(Book, fields="__all__", error_messages={
|
||||||
|
'title': {
|
||||||
|
'max_length': 'Title too long!!'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
form = BookFormSet.form(data={'title': 'Foo ' * 30, 'author': author.id})
|
||||||
|
form.full_clean()
|
||||||
|
self.assertEqual(form.errors, {'title': ['Title too long!!']})
|
||||||
|
|
||||||
|
def test_inlineformset_factory_error_messages_overrides(self):
|
||||||
|
author = Author.objects.create(pk=1, name='Charles Baudelaire')
|
||||||
|
BookFormSet = inlineformset_factory(Author, Book, fields="__all__", error_messages={
|
||||||
|
'title': {
|
||||||
|
'max_length': 'Title too long!!'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
form = BookFormSet.form(data={'title': 'Foo ' * 30, 'author': author.id})
|
||||||
|
form.full_clean()
|
||||||
|
self.assertEqual(form.errors, {'title': ['Title too long!!']})
|
||||||
|
|
Loading…
Reference in New Issue