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
df27803a
Kaydet (Commit)
df27803a
authored
May 24, 2013
tarafından
yokomizor
Kaydeden (comit)
Tim Graham
Eyl 19, 2013
Dosyalara gözat
Seçenekler
Dosyalara Gözat
İndir
Eposta Yamaları
Sade Fark
Fixed #9532 -- Added min_num and validate_min on formsets.
Thanks gsf for the suggestion.
üst
59a34c43
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
81 additions
and
15 deletions
+81
-15
formsets.py
django/forms/formsets.py
+22
-5
formsets.txt
docs/ref/forms/formsets.txt
+6
-2
1.7.txt
docs/releases/1.7.txt
+4
-0
formsets.txt
docs/topics/forms/formsets.txt
+44
-3
tests.py
tests/admin_views/tests.py
+5
-5
test_formsets.py
tests/forms_tests/tests/test_formsets.py
+0
-0
No files found.
django/forms/formsets.py
Dosyayı görüntüle @
df27803a
...
...
@@ -18,10 +18,14 @@ __all__ = ('BaseFormSet', 'all_valid')
# special field names
TOTAL_FORM_COUNT
=
'TOTAL_FORMS'
INITIAL_FORM_COUNT
=
'INITIAL_FORMS'
MIN_NUM_FORM_COUNT
=
'MIN_NUM_FORMS'
MAX_NUM_FORM_COUNT
=
'MAX_NUM_FORMS'
ORDERING_FIELD_NAME
=
'ORDER'
DELETION_FIELD_NAME
=
'DELETE'
# default minimum number of forms in a formset
DEFAULT_MIN_NUM
=
0
# default maximum number of forms in a formset, to prevent memory exhaustion
DEFAULT_MAX_NUM
=
1000
...
...
@@ -34,9 +38,10 @@ class ManagementForm(Form):
def
__init__
(
self
,
*
args
,
**
kwargs
):
self
.
base_fields
[
TOTAL_FORM_COUNT
]
=
IntegerField
(
widget
=
HiddenInput
)
self
.
base_fields
[
INITIAL_FORM_COUNT
]
=
IntegerField
(
widget
=
HiddenInput
)
# MAX_NUM_FORM_COUNT is output with the rest of the management form,
# but only for the convenience of client-side code. The POST
# value of MAX_NUM_FORM_COUNT returned from the client is not checked.
# MIN_NUM_FORM_COUNT and MAX_NUM_FORM_COUNT are output with the rest of
# the management form, but only for the convenience of client-side
# code. The POST value of them returned from the client is not checked.
self
.
base_fields
[
MIN_NUM_FORM_COUNT
]
=
IntegerField
(
required
=
False
,
widget
=
HiddenInput
)
self
.
base_fields
[
MAX_NUM_FORM_COUNT
]
=
IntegerField
(
required
=
False
,
widget
=
HiddenInput
)
super
(
ManagementForm
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
...
...
@@ -92,6 +97,7 @@ class BaseFormSet(object):
form
=
ManagementForm
(
auto_id
=
self
.
auto_id
,
prefix
=
self
.
prefix
,
initial
=
{
TOTAL_FORM_COUNT
:
self
.
total_form_count
(),
INITIAL_FORM_COUNT
:
self
.
initial_form_count
(),
MIN_NUM_FORM_COUNT
:
self
.
min_num
,
MAX_NUM_FORM_COUNT
:
self
.
max_num
})
return
form
...
...
@@ -323,6 +329,12 @@ class BaseFormSet(object):
"Please submit
%
d or fewer forms."
,
self
.
max_num
)
%
self
.
max_num
,
code
=
'too_many_forms'
,
)
if
(
self
.
validate_min
and
self
.
total_form_count
()
-
len
(
self
.
deleted_forms
)
<
self
.
min_num
):
raise
ValidationError
(
ungettext
(
"Please submit
%
d or more forms."
,
"Please submit
%
d or more forms."
,
self
.
min_num
)
%
self
.
min_num
,
code
=
'too_few_forms'
)
# Give self.clean() a chance to do cross-form validation.
self
.
clean
()
except
ValidationError
as
e
:
...
...
@@ -395,17 +407,22 @@ class BaseFormSet(object):
return
mark_safe
(
'
\n
'
.
join
([
six
.
text_type
(
self
.
management_form
),
forms
]))
def
formset_factory
(
form
,
formset
=
BaseFormSet
,
extra
=
1
,
can_order
=
False
,
can_delete
=
False
,
max_num
=
None
,
validate_max
=
False
):
can_delete
=
False
,
max_num
=
None
,
validate_max
=
False
,
min_num
=
None
,
validate_min
=
False
):
"""Return a FormSet for the given form class."""
if
min_num
is
None
:
min_num
=
DEFAULT_MIN_NUM
if
max_num
is
None
:
max_num
=
DEFAULT_MAX_NUM
# hard limit on forms instantiated, to prevent memory-exhaustion attacks
# limit is simply max_num + DEFAULT_MAX_NUM (which is 2*DEFAULT_MAX_NUM
# if max_num is None in the first place)
absolute_max
=
max_num
+
DEFAULT_MAX_NUM
extra
+=
min_num
attrs
=
{
'form'
:
form
,
'extra'
:
extra
,
'can_order'
:
can_order
,
'can_delete'
:
can_delete
,
'max_num'
:
max_num
,
'absolute_max'
:
absolute_max
,
'min_num'
:
min_num
,
'max_num'
:
max_num
,
'absolute_max'
:
absolute_max
,
'validate_min'
:
validate_min
,
'validate_max'
:
validate_max
}
return
type
(
form
.
__name__
+
str
(
'FormSet'
),
(
formset
,),
attrs
)
...
...
docs/ref/forms/formsets.txt
Dosyayı görüntüle @
df27803a
...
...
@@ -5,12 +5,16 @@ Formset Functions
.. module:: django.forms.formsets
:synopsis: Django's functions for building formsets.
.. function:: formset_factory(form, formset=BaseFormSet, extra=1, can_order=False, can_delete=False, max_num=None, validate_max=False)
.. function:: formset_factory(form, formset=BaseFormSet, extra=1, can_order=False, can_delete=False, max_num=None, validate_max=False
, min_num=None, validate_min=False
)
Returns a ``FormSet`` class for the given ``form`` class.
See :ref:`formsets` for example usage.
.. versionchanged:: 1.6
The ``validate_max`` parameter was added.
.. versionchanged:: 1.7
The ``min_num`` and ``validate_min`` parameters were added.
docs/releases/1.7.txt
Dosyayı görüntüle @
df27803a
...
...
@@ -234,6 +234,10 @@ Forms
<django.forms.extras.widgets.SelectDateWidget.months>` can be used to
customize the wording of the months displayed in the select widget.
* The ``min_num`` and ``validate_min`` parameters were added to
:func:`~django.forms.formsets.formset_factory` to allow validating
a minimum number of submitted forms.
Management Commands
^^^^^^^^^^^^^^^^^^^
...
...
docs/topics/forms/formsets.txt
Dosyayı görüntüle @
df27803a
...
...
@@ -298,6 +298,13 @@ method on the formset.
Validating the number of forms in a formset
-------------------------------------------
Django provides a couple ways to validate the minimum or maximum number of
submitted forms. Applications which need more customizable validation of the
number of forms should use custom formset validation.
``validate_max``
~~~~~~~~~~~~~~~~
If ``validate_max=True`` is passed to
:func:`~django.forms.formsets.formset_factory`, validation will also check
that the number of forms in the data set, minus those marked for
...
...
@@ -309,6 +316,7 @@ deletion, is less than or equal to ``max_num``.
>>> data = {
... 'form-TOTAL_FORMS': u'2',
... 'form-INITIAL_FORMS': u'0',
... 'form-MIN_NUM_FORMS': u'',
... 'form-MAX_NUM_FORMS': u'',
... 'form-0-title': u'Test',
... 'form-0-pub_date': u'1904-06-16',
...
...
@@ -327,9 +335,6 @@ deletion, is less than or equal to ``max_num``.
``max_num`` was exceeded because the amount of initial data supplied was
excessive.
Applications which need more customizable validation of the number of forms
should use custom formset validation.
.. note::
Regardless of ``validate_max``, if the number of forms in a data set
...
...
@@ -344,6 +349,42 @@ should use custom formset validation.
The ``validate_max`` parameter was added to
:func:`~django.forms.formsets.formset_factory`.
``validate_min``
~~~~~~~~~~~~~~~~
.. versionadded:: 1.7
If ``validate_min=True`` is passed to
:func:`~django.forms.formsets.formset_factory`, validation will also check
that the number of forms in the data set, minus those marked for
deletion, is greater than or equal to ``min_num``.
>>> from django.forms.formsets import formset_factory
>>> from myapp.forms import ArticleForm
>>> ArticleFormSet = formset_factory(ArticleForm, min_num=3, validate_min=True)
>>> data = {
... 'form-TOTAL_FORMS': u'2',
... 'form-INITIAL_FORMS': u'0',
... 'form-MIN_NUM_FORMS': u'',
... 'form-MAX_NUM_FORMS': u'',
... 'form-0-title': u'Test',
... 'form-0-pub_date': u'1904-06-16',
... 'form-1-title': u'Test 2',
... 'form-1-pub_date': u'1912-06-23',
... }
>>> formset = ArticleFormSet(data)
>>> formset.is_valid()
False
>>> formset.errors
[{}, {}]
>>> formset.non_form_errors()
[u'Please submit 3 or more forms.']
.. versionchanged:: 1.7
The ``min_num`` and ``validate_min`` parameters were added to
:func:`~django.forms.formsets.formset_factory`.
Dealing with ordering and deletion of forms
-------------------------------------------
...
...
tests/admin_views/tests.py
Dosyayı görüntüle @
df27803a
...
...
@@ -1874,14 +1874,14 @@ class AdminViewListEditable(TestCase):
def
test_changelist_input_html
(
self
):
response
=
self
.
client
.
get
(
'/test_admin/admin/admin_views/person/'
)
# 2 inputs per object(the field and the hidden id field) = 6
#
3 management hidden fields = 3
#
4 management hidden fields = 4
# 4 action inputs (3 regular checkboxes, 1 checkbox to select all)
# main form submit button = 1
# search field and search submit button = 2
# CSRF field = 1
# field to track 'select all' across paginated views = 1
# 6 +
3 + 4 + 1 + 2 + 1 + 1 = 18
inputs
self
.
assertContains
(
response
,
"<input"
,
count
=
1
8
)
# 6 +
4 + 4 + 1 + 2 + 1 + 1 = 19
inputs
self
.
assertContains
(
response
,
"<input"
,
count
=
1
9
)
# 1 select per object = 3 selects
self
.
assertContains
(
response
,
"<select"
,
count
=
4
)
...
...
@@ -3629,9 +3629,9 @@ class ReadonlyTest(TestCase):
response
=
self
.
client
.
get
(
'/test_admin/admin/admin_views/post/add/'
)
self
.
assertEqual
(
response
.
status_code
,
200
)
self
.
assertNotContains
(
response
,
'name="posted"'
)
# 3 fields + 2 submit buttons +
4
inline management form fields, + 2
# 3 fields + 2 submit buttons +
5
inline management form fields, + 2
# hidden fields for inlines + 1 field for the inline + 2 empty form
self
.
assertContains
(
response
,
"<input"
,
count
=
1
4
)
self
.
assertContains
(
response
,
"<input"
,
count
=
1
5
)
self
.
assertContains
(
response
,
formats
.
localize
(
datetime
.
date
.
today
()))
self
.
assertContains
(
response
,
"<label>Awesomeness level:</label>"
)
...
...
tests/forms_tests/tests/test_formsets.py
Dosyayı görüntüle @
df27803a
This diff is collapsed.
Click to expand it.
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