Skip to content
Projeler
Gruplar
Parçacıklar
Yardım
Yükleniyor...
Oturum aç / Kaydol
Gezinmeyi değiştir
D
django
Proje
Proje
Ayrıntılar
Etkinlik
Cycle Analytics
Depo (repository)
Depo (repository)
Dosyalar
Kayıtlar (commit)
Dallar (branch)
Etiketler
Katkıda bulunanlar
Grafik
Karşılaştır
Grafikler
Konular (issue)
0
Konular (issue)
0
Liste
Pano
Etiketler
Kilometre Taşları
Birleştirme (merge) Talepleri
0
Birleştirme (merge) Talepleri
0
CI / CD
CI / CD
İş akışları (pipeline)
İşler
Zamanlamalar
Grafikler
Paketler
Paketler
Wiki
Wiki
Parçacıklar
Parçacıklar
Üyeler
Üyeler
Collapse sidebar
Close sidebar
Etkinlik
Grafik
Grafikler
Yeni bir konu (issue) oluştur
İşler
Kayıtlar (commit)
Konu (issue) Panoları
Kenar çubuğunu aç
Batuhan Osman TASKAYA
django
Commits
00a88916
Kaydet (Commit)
00a88916
authored
Şub 06, 2015
tarafından
Loic Bistuer
Dosyalara gözat
Seçenekler
Dosyalara Gözat
İndir
Eposta Yamaları
Sade Fark
Fixed #24295 -- Allowed ModelForm meta to specify form field classes.
Thanks Carl Meyer and Markus Holtermann for the reviews.
üst
e8cf4f8a
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
92 additions
and
26 deletions
+92
-26
models.py
django/forms/models.py
+24
-8
models.txt
docs/ref/forms/models.txt
+22
-7
1.9.txt
docs/releases/1.9.txt
+3
-1
modelforms.txt
docs/topics/forms/modelforms.txt
+15
-8
tests.py
tests/model_forms/tests.py
+10
-2
tests.py
tests/model_formsets/tests.py
+18
-0
No files found.
django/forms/models.py
Dosyayı görüntüle @
00a88916
...
...
@@ -154,7 +154,8 @@ def model_to_dict(instance, fields=None, exclude=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
):
labels
=
None
,
help_texts
=
None
,
error_messages
=
None
,
field_classes
=
None
):
"""
Returns a ``OrderedDict`` containing form fields for the given model.
...
...
@@ -167,6 +168,9 @@ def fields_for_model(model, fields=None, exclude=None, widgets=None,
``widgets`` is a dictionary of model field names mapped to a widget.
``formfield_callback`` is a callable that takes a model field and returns
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.
...
...
@@ -176,8 +180,8 @@ def fields_for_model(model, fields=None, exclude=None, widgets=None,
``error_messages`` is a dictionary of model field names mapped to a
dictionary of error messages.
``f
ormfield_callback`` is a callable that takes a model field and returns
a form field
.
``f
ield_classes`` is a dictionary of model field names mapped to a form
field class
.
"""
field_list
=
[]
ignored
=
[]
...
...
@@ -205,6 +209,8 @@ def fields_for_model(model, fields=None, exclude=None, widgets=None,
kwargs
[
'help_text'
]
=
help_texts
[
f
.
name
]
if
error_messages
and
f
.
name
in
error_messages
:
kwargs
[
'error_messages'
]
=
error_messages
[
f
.
name
]
if
field_classes
and
f
.
name
in
field_classes
:
kwargs
[
'form_class'
]
=
field_classes
[
f
.
name
]
if
formfield_callback
is
None
:
formfield
=
f
.
formfield
(
**
kwargs
)
...
...
@@ -236,6 +242,7 @@ class ModelFormOptions(object):
self
.
labels
=
getattr
(
options
,
'labels'
,
None
)
self
.
help_texts
=
getattr
(
options
,
'help_texts'
,
None
)
self
.
error_messages
=
getattr
(
options
,
'error_messages'
,
None
)
self
.
field_classes
=
getattr
(
options
,
'field_classes'
,
None
)
class
ModelFormMetaclass
(
DeclarativeFieldsMetaclass
):
...
...
@@ -280,7 +287,8 @@ class ModelFormMetaclass(DeclarativeFieldsMetaclass):
fields
=
fields_for_model
(
opts
.
model
,
opts
.
fields
,
opts
.
exclude
,
opts
.
widgets
,
formfield_callback
,
opts
.
localized_fields
,
opts
.
labels
,
opts
.
help_texts
,
opts
.
error_messages
)
opts
.
help_texts
,
opts
.
error_messages
,
opts
.
field_classes
)
# make sure opts.fields doesn't specify an invalid field
none_model_fields
=
[
k
for
k
,
v
in
six
.
iteritems
(
fields
)
if
not
v
]
...
...
@@ -469,7 +477,8 @@ class ModelForm(six.with_metaclass(ModelFormMetaclass, BaseModelForm)):
def
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
):
labels
=
None
,
help_texts
=
None
,
error_messages
=
None
,
field_classes
=
None
):
"""
Returns a ModelForm containing form fields for the given model.
...
...
@@ -494,6 +503,9 @@ def modelform_factory(model, form=ModelForm, fields=None, exclude=None,
``error_messages`` is a dictionary of model field names mapped to a
dictionary of error messages.
``field_classes`` is a dictionary of model field names mapped to a form
field class.
"""
# Create the inner Meta class. FIXME: ideally, we should be able to
# construct a ModelForm without creating and passing in a temporary
...
...
@@ -515,6 +527,8 @@ def modelform_factory(model, form=ModelForm, fields=None, exclude=None,
attrs
[
'help_texts'
]
=
help_texts
if
error_messages
is
not
None
:
attrs
[
'error_messages'
]
=
error_messages
if
field_classes
is
not
None
:
attrs
[
'field_classes'
]
=
field_classes
# If parent form class already has an inner Meta, the Meta we're
# creating needs to inherit from the parent's inner meta.
...
...
@@ -813,7 +827,7 @@ def modelformset_factory(model, form=ModelForm, formfield_callback=None,
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
,
min_num
=
None
,
validate_min
=
False
):
min_num
=
None
,
validate_min
=
False
,
field_classes
=
None
):
"""
Returns a FormSet class for the given Django model class.
"""
...
...
@@ -830,7 +844,8 @@ def modelformset_factory(model, form=ModelForm, formfield_callback=None,
form
=
modelform_factory
(
model
,
form
=
form
,
fields
=
fields
,
exclude
=
exclude
,
formfield_callback
=
formfield_callback
,
widgets
=
widgets
,
localized_fields
=
localized_fields
,
labels
=
labels
,
help_texts
=
help_texts
,
error_messages
=
error_messages
)
labels
=
labels
,
help_texts
=
help_texts
,
error_messages
=
error_messages
,
field_classes
=
field_classes
)
FormSet
=
formset_factory
(
form
,
formset
,
extra
=
extra
,
min_num
=
min_num
,
max_num
=
max_num
,
can_order
=
can_order
,
can_delete
=
can_delete
,
validate_min
=
validate_min
,
validate_max
=
validate_max
)
...
...
@@ -991,7 +1006,7 @@ def inlineformset_factory(parent_model, model, form=ModelForm,
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
,
min_num
=
None
,
validate_min
=
False
):
min_num
=
None
,
validate_min
=
False
,
field_classes
=
None
):
"""
Returns an ``InlineFormSet`` for the given kwargs.
...
...
@@ -1020,6 +1035,7 @@ def inlineformset_factory(parent_model, model, form=ModelForm,
'labels'
:
labels
,
'help_texts'
:
help_texts
,
'error_messages'
:
error_messages
,
'field_classes'
:
field_classes
,
}
FormSet
=
modelformset_factory
(
model
,
**
kwargs
)
FormSet
.
fk
=
fk
...
...
docs/ref/forms/models.txt
Dosyayı görüntüle @
00a88916
...
...
@@ -8,7 +8,7 @@ Model Form API reference. For introductory material about model forms, see the
.. module:: django.forms.models
: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, labels=None, help_texts=None, error_messages=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
, field_classes=None
)
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
...
...
@@ -21,11 +21,11 @@ Model Form API reference. For introductory material about model forms, see the
fields will be excluded from the returned fields, even if they are listed
in the ``fields`` argument.
``widgets`` is a dictionary of model field names mapped to a widget.
``formfield_callback`` is a callable that takes a model field and returns
a form field.
``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.
...
...
@@ -35,6 +35,9 @@ Model Form API reference. For introductory material about model forms, see the
``error_messages`` is a dictionary of model field names mapped to a
dictionary of error messages.
``field_classes`` is a dictionary of model field names mapped to a form
field class.
See :ref:`modelforms-factory` for example usage.
You must provide the list of fields explicitly, either via keyword arguments
...
...
@@ -48,14 +51,18 @@ Model Form API reference. For introductory material about model forms, see the
Previously, omitting the list of fields was allowed and resulted in
a form with all fields of the model.
.. 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, min_num=None, validate_min=False)
.. versionadded:: 1.9
The ``field_classes`` keyword argument was 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, labels=None, help_texts=None, error_messages=None, min_num=None, validate_min=False, field_classes=None)
Returns a ``FormSet`` class for the given ``model`` class.
Arguments ``model``, ``form``, ``fields``, ``exclude``,
``formfield_callback``, ``widgets``, ``localized_fields``, ``labels``,
``help_texts``,
and ``error_messages`` are all passed through to
:func:`~django.forms.models.modelform_factory`.
``help_texts``,
``error_messages``, and ``field_classes`` are all passed
through to
:func:`~django.forms.models.modelform_factory`.
Arguments ``formset``, ``extra``, ``max_num``, ``can_order``,
``can_delete`` and ``validate_max`` are passed through to
...
...
@@ -64,7 +71,11 @@ Model Form API reference. For introductory material about model forms, see the
See :ref:`model-formsets` for example usage.
.. 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, min_num=None, validate_min=False)
.. versionadded:: 1.9
The ``field_classes`` keyword argument was 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, labels=None, help_texts=None, error_messages=None, min_num=None, validate_min=False, field_classes=None)
Returns an ``InlineFormSet`` using :func:`modelformset_factory` with
defaults of ``formset=``:class:`~django.forms.models.BaseInlineFormSet`,
...
...
@@ -74,3 +85,7 @@ Model Form API reference. For introductory material about model forms, see the
the ``parent_model``, you must specify a ``fk_name``.
See :ref:`inline-formsets` for example usage.
.. versionadded:: 1.9
The ``field_classes`` keyword argument was added.
docs/releases/1.9.txt
Dosyayı görüntüle @
00a88916
...
...
@@ -106,7 +106,9 @@ File Uploads
Forms
^^^^^
* ...
* :class:`~django.forms.ModelForm` accepts the new ``Meta`` option
``field_classes`` to customize the type of the fields. See
:ref:`modelforms-overriding-default-fields` for details.
Generic Views
^^^^^^^^^^^^^
...
...
docs/topics/forms/modelforms.txt
Dosyayı görüntüle @
00a88916
...
...
@@ -475,9 +475,8 @@ Overriding the default fields
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
``ModelForm`` gives you the flexibility of changing the form field type and
widget for a given model field.
want that to be represented as a ``DateField`` in your form. But ``ModelForm``
gives you the flexibility of changing the form field for a given model.
To specify a custom widget for a field, use the ``widgets`` attribute of the
inner ``Meta`` class. This should be a dictionary mapping field names to widget
...
...
@@ -525,9 +524,8 @@ the ``name`` field::
},
}
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``.
You can also specify ``field_classes`` to customize the type of fields
instantiated by the form.
For example, if you wanted to use ``MySlugFormField`` for the ``slug``
field, you could do the following::
...
...
@@ -536,13 +534,18 @@ field, you could do the following::
from myapp.models import Article
class ArticleForm(ModelForm):
slug = MySlugFormField()
class Meta:
model = Article
fields = ['pub_date', 'headline', 'content', 'reporter', 'slug']
field_classes = {
'slug': MySlugFormField,
}
Finally, if you want complete control over of a field -- including its type,
validators, required, etc. -- you can do this by declaratively specifying
fields like you would in a regular ``Form``.
If you want to specify a field's validators, you can do so by defining
the field declaratively and setting its ``validators`` parameter::
...
...
@@ -556,6 +559,10 @@ the field declaratively and setting its ``validators`` parameter::
model = Article
fields = ['pub_date', 'headline', 'content', 'reporter', 'slug']
.. versionadded:: 1.9
The ``Meta.field_classes`` attribute was added.
.. note::
When you explicitly instantiate a form field like this, it is important to
...
...
tests/model_forms/tests.py
Dosyayı görüntüle @
00a88916
...
...
@@ -11,7 +11,7 @@ from django.core.exceptions import (
)
from
django.core.files.uploadedfile
import
SimpleUploadedFile
from
django.core.validators
import
ValidationError
from
django.db
import
connection
from
django.db
import
connection
,
models
from
django.db.models.query
import
EmptyQuerySet
from
django.forms.models
import
(
ModelFormMetaclass
,
construct_instance
,
fields_for_model
,
model_to_dict
,
...
...
@@ -545,6 +545,9 @@ class FieldOverridesByFormMetaForm(forms.ModelForm):
)
}
}
field_classes
=
{
'url'
:
forms
.
URLField
,
}
class
TestFieldOverridesByFormMeta
(
TestCase
):
...
...
@@ -588,7 +591,7 @@ class TestFieldOverridesByFormMeta(TestCase):
def
test_error_messages_overrides
(
self
):
form
=
FieldOverridesByFormMetaForm
(
data
=
{
'name'
:
'Category'
,
'url'
:
'/category/'
,
'url'
:
'
http://www.example.com
/category/'
,
'slug'
:
'!
%#*
@'
,
})
form
.
full_clean
()
...
...
@@ -599,6 +602,11 @@ class TestFieldOverridesByFormMeta(TestCase):
]
self
.
assertEqual
(
form
.
errors
,
{
'slug'
:
error
})
def
test_field_type_overrides
(
self
):
form
=
FieldOverridesByFormMetaForm
()
self
.
assertIs
(
Category
.
_meta
.
get_field
(
'url'
)
.
__class__
,
models
.
CharField
)
self
.
assertIsInstance
(
form
.
fields
[
'url'
],
forms
.
URLField
)
class
IncompleteCategoryFormWithFields
(
forms
.
ModelForm
):
"""
...
...
tests/model_formsets/tests.py
Dosyayı görüntüle @
00a88916
...
...
@@ -1431,3 +1431,21 @@ class TestModelFormsetOverridesTroughFormMeta(TestCase):
form
=
BookFormSet
.
form
(
data
=
{
'title'
:
'Foo '
*
30
,
'author'
:
author
.
id
})
form
.
full_clean
()
self
.
assertEqual
(
form
.
errors
,
{
'title'
:
[
'Title too long!!'
]})
def
test_modelformset_factory_field_class_overrides
(
self
):
author
=
Author
.
objects
.
create
(
pk
=
1
,
name
=
'Charles Baudelaire'
)
BookFormSet
=
modelformset_factory
(
Book
,
fields
=
"__all__"
,
field_classes
=
{
'title'
:
forms
.
SlugField
,
})
form
=
BookFormSet
.
form
(
data
=
{
'title'
:
'Foo '
*
30
,
'author'
:
author
.
id
})
self
.
assertIs
(
Book
.
_meta
.
get_field
(
'title'
)
.
__class__
,
models
.
CharField
)
self
.
assertIsInstance
(
form
.
fields
[
'title'
],
forms
.
SlugField
)
def
test_inlineformset_factory_field_class_overrides
(
self
):
author
=
Author
.
objects
.
create
(
pk
=
1
,
name
=
'Charles Baudelaire'
)
BookFormSet
=
inlineformset_factory
(
Author
,
Book
,
fields
=
"__all__"
,
field_classes
=
{
'title'
:
forms
.
SlugField
,
})
form
=
BookFormSet
.
form
(
data
=
{
'title'
:
'Foo '
*
30
,
'author'
:
author
.
id
})
self
.
assertIs
(
Book
.
_meta
.
get_field
(
'title'
)
.
__class__
,
models
.
CharField
)
self
.
assertIsInstance
(
form
.
fields
[
'title'
],
forms
.
SlugField
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment