Django 2.1
Formsets

Formsets
-
class BaseFormSet
[source]
एक फ़ॉर्मेट एक पृष्ठ पर कई रूपों के साथ काम करने के लिए अमूर्तता की एक परत है। यह डेटा ग्रिड की तुलना में सबसे अच्छा हो सकता है। मान लें कि आपके पास निम्नलिखित फ़ॉर्म हैं:
>>> from django import forms >>> class ArticleForm(forms.Form): ... title = forms.CharField() ... pub_date = forms.DateField()
आप उपयोगकर्ता को एक साथ कई लेख बनाने की अनुमति देना चाह सकते हैं। एक ArticleForm से बाहर एक फॉर्मेट बनाने के लिए आप क्या करेंगे:
>>> from django.forms import formset_factory >>> ArticleFormSet = formset_factory(ArticleForm)
अब आपने ArticleFormSet नाम का एक फॉर्मेट बनाया है। फ़ॉर्मेट आपको फ़ॉर्मेट में प्रपत्रों पर पुनरावृति करने और उन्हें प्रदर्शित करने की क्षमता देता है, जैसा कि आप नियमित रूप से करते हैं:
>>> formset = ArticleFormSet() >>> for form in formset: ... print(form.as_table()) <tr><th><label for="id_form-0-title">Title:</label></th><td><input type="text" name="form-0-title" id="id_form-0-title"></td></tr> <tr><th><label for="id_form-0-pub_date">Pub date:</label></th><td><input type="text" name="form-0-pub_date" id="id_form-0-pub_date"></td></tr>
जैसा कि आप देख सकते हैं कि यह केवल एक खाली रूप प्रदर्शित करता है।
प्रदर्शित किए जाने वाले खाली रूपों की संख्या को
extra
पैरामीटर द्वारा नियंत्रित किया जाता है।
डिफ़ॉल्ट रूप से,
formset_factory()
एक अतिरिक्त रूप को परिभाषित करता है;
निम्नलिखित उदाहरण दो रिक्त रूपों को प्रदर्शित करेगा:
>>> ArticleFormSet = formset_factory(ArticleForm, extra=2)
फ़ार्मेट पर
formset
वे बनाए गए क्रम में प्रपत्र रेंडर करेंगे।
आप इस आदेश को
__iter__()
विधि के लिए एक वैकल्पिक कार्यान्वयन प्रदान करके बदल सकते हैं।
फॉर्मसेट को भी अनुक्रमित किया जा सकता है, जो संबंधित फॉर्म लौटाता है।
यदि आप
__iter__
ओवरराइड
__iter__
, तो आपको मैचिंग व्यवहार करने के लिए
__getitem__
को भी ओवरराइड करना होगा।
एक फॉर्मेट के साथ प्रारंभिक डेटा का उपयोग करना
प्रारंभिक डेटा वह है जो किसी फॉर्मेट की मुख्य उपयोगिता को चलाता है। जैसा कि ऊपर दिखाया गया है आप अतिरिक्त रूपों की संख्या को परिभाषित कर सकते हैं। इसका मतलब यह है कि आप फॉर्मेट को बता रहे हैं कि प्रारंभिक डेटा से उत्पन्न होने वाले फॉर्म के अलावा कितने अतिरिक्त फॉर्म दिखाने हैं। आइए एक उदाहरण देखें:
>>> import datetime >>> from django.forms import formset_factory >>> from myapp.forms import ArticleForm >>> ArticleFormSet = formset_factory(ArticleForm, extra=2) >>> formset = ArticleFormSet(initial=[ ... {'title': 'Django is now open source', ... 'pub_date': datetime.date.today(),} ... ]) >>> for form in formset: ... print(form.as_table()) <tr><th><label for="id_form-0-title">Title:</label></th><td><input type="text" name="form-0-title" value="Django is now open source" id="id_form-0-title"></td></tr> <tr><th><label for="id_form-0-pub_date">Pub date:</label></th><td><input type="text" name="form-0-pub_date" value="2008-05-12" id="id_form-0-pub_date"></td></tr> <tr><th><label for="id_form-1-title">Title:</label></th><td><input type="text" name="form-1-title" id="id_form-1-title"></td></tr> <tr><th><label for="id_form-1-pub_date">Pub date:</label></th><td><input type="text" name="form-1-pub_date" id="id_form-1-pub_date"></td></tr> <tr><th><label for="id_form-2-title">Title:</label></th><td><input type="text" name="form-2-title" id="id_form-2-title"></td></tr> <tr><th><label for="id_form-2-pub_date">Pub date:</label></th><td><input type="text" name="form-2-pub_date" id="id_form-2-pub_date"></td></tr>
अब कुल तीन फॉर्म दिखाई दे रहे हैं। प्रारंभिक डेटा के लिए एक जिसे दो अतिरिक्त रूपों में पारित किया गया था। यह भी ध्यान दें कि हम प्रारंभिक डेटा के रूप में शब्दकोशों की सूची में पास कर रहे हैं।
यदि आप किसी फॉर्मेट को प्रदर्शित करने के लिए
initial
उपयोग करते हैं, तो आपको उस फॉर्मेट को सबमिट करते समय उसी
initial
को पास करना चाहिए, ताकि फॉर्मेट यह पता लगा सके कि उपयोगकर्ता द्वारा कौन से फॉर्म बदले गए हैं।
उदाहरण के लिए, आपके पास कुछ ऐसा हो सकता है:
ArticleFormSet(request.POST, initial=[...])
।
यह भी देखें
रूपों की अधिकतम संख्या को सीमित करना
formset_factory()
लिए
max_num
पैरामीटर आपको
formset_factory()
प्रदर्शित करने वाले रूपों की संख्या को सीमित करने की क्षमता देता है:
>>> from django.forms import formset_factory >>> from myapp.forms import ArticleForm >>> ArticleFormSet = formset_factory(ArticleForm, extra=2, max_num=1) >>> formset = ArticleFormSet() >>> for form in formset: ... print(form.as_table()) <tr><th><label for="id_form-0-title">Title:</label></th><td><input type="text" name="form-0-title" id="id_form-0-title"></td></tr> <tr><th><label for="id_form-0-pub_date">Pub date:</label></th><td><input type="text" name="form-0-pub_date" id="id_form-0-pub_date"></td></tr>
यदि शुरुआती डेटा में
max_num
की
max_num
मौजूदा आइटम्स की संख्या से अधिक है, तो
extra
अतिरिक्त ब्लैंक फॉर्म को
max_num
जोड़ा जाएगा, इसलिए जब तक कि फॉर्म की कुल संख्या
max_num
से
max_num
न हो
max_num
।
उदाहरण के लिए, यदि
extra=2
और
max_num=2
extra=2
और
max_num=2
को एक
initial
आइटम के साथ आरंभीकृत किया गया है, तो प्रारंभिक आइटम के लिए एक फॉर्म और एक रिक्त फॉर्म प्रदर्शित किया जाएगा।
यदि प्रारंभिक डेटा में आइटमों की संख्या
max_num
से अधिक है, तो सभी आरंभिक डेटा फ़ॉर्म
max_num
के मान की परवाह किए बिना प्रदर्शित किए
max_num
और कोई अतिरिक्त फ़ॉर्म प्रदर्शित नहीं किए जाएंगे।
उदाहरण के लिए, यदि
extra=3
और
max_num=1
और
max_num=1
को दो प्रारंभिक वस्तुओं के साथ आरंभ किया गया है, तो प्रारंभिक डेटा वाले दो रूपों को प्रदर्शित किया जाएगा।
None
(
max_num
एक
max_num
मूल्य प्रदर्शित (1000) रूपों की संख्या पर एक उच्च सीमा डालता है।
व्यवहार में यह कोई सीमा नहीं के बराबर है।
डिफ़ॉल्ट रूप से,
max_num
केवल कितने रूपों को प्रदर्शित करता है और सत्यापन को प्रभावित नहीं करता है।
यदि
validate_max=True
को
formset_factory()
, तो
max_num
सत्यापन को प्रभावित करेगा।
देखें
validate_max
फॉर्मेट सत्यापन
एक फॉर्मेट के साथ सत्यापन एक नियमित रूप से लगभग समान है।
is_valid
में सभी रूपों को मान्य करने के लिए एक सुविधाजनक तरीका प्रदान करने के लिए
is_valid
पर एक
is_valid
विधि है:
>>> from django.forms import formset_factory >>> from myapp.forms import ArticleForm >>> ArticleFormSet = formset_factory(ArticleForm) >>> data = { ... 'form-TOTAL_FORMS': '1', ... 'form-INITIAL_FORMS': '0', ... 'form-MAX_NUM_FORMS': '', ... } >>> formset = ArticleFormSet(data) >>> formset.is_valid() True
हम उस फॉर्मेट के लिए बिना किसी डेटा के पास हुए, जिसके परिणामस्वरूप एक वैध फॉर्म है। फ़ॉर्मेट अतिरिक्त रूपों को अनदेखा करने के लिए पर्याप्त स्मार्ट है जिन्हें परिवर्तित नहीं किया गया था। यदि हम एक अमान्य लेख प्रदान करते हैं:
>>> data = { ... 'form-TOTAL_FORMS': '2', ... 'form-INITIAL_FORMS': '0', ... 'form-MAX_NUM_FORMS': '', ... 'form-0-title': 'Test', ... 'form-0-pub_date': '1904-06-16', ... 'form-1-title': 'Test', ... 'form-1-pub_date': '', # <-- this date is missing but required ... } >>> formset = ArticleFormSet(data) >>> formset.is_valid() False >>> formset.errors [{}, {'pub_date': ['This field is required.']}]
जैसा कि हम देख सकते हैं,
formset.errors
एक सूची है जिसकी प्रविष्टियाँ
formset.errors
में रूपों से मेल खाती हैं।
प्रत्येक दो रूपों के लिए सत्यापन किया गया था, और दूसरे आइटम के लिए अपेक्षित त्रुटि संदेश प्रकट होता है।
सामान्य
Form
का उपयोग करते समय,
maxlength
के प्रत्येक फ़ील्ड में HTML विशेषताएँ शामिल हो सकती हैं जैसे ब्राउज़र सत्यापन के लिए
maxlength
।
हालाँकि, प्रपत्रों के प्रपत्र फ़ील्ड में
required
विशेषता शामिल नहीं होगी क्योंकि प्रपत्र जोड़ते और हटाते समय सत्यापन गलत हो सकता है।
-
BaseFormSet.total_error_count()
[source]
यह सुनिश्चित करने के लिए कि
total_error_count
में कितनी त्रुटियां हैं, हम
total_error_count
विधि का उपयोग कर सकते हैं:
>>> # Using the previous example >>> formset.errors [{}, {'pub_date': ['This field is required.']}] >>> len(formset.errors) 2 >>> formset.total_error_count() 1
हम यह भी जांच सकते हैं कि क्या फॉर्म डेटा प्रारंभिक डेटा से भिन्न है (यानी फॉर्म बिना किसी डेटा के भेजा गया था):
>>> data = { ... 'form-TOTAL_FORMS': '1', ... 'form-INITIAL_FORMS': '0', ... 'form-MAX_NUM_FORMS': '', ... 'form-0-title': '', ... 'form-0-pub_date': '', ... } >>> formset = ArticleFormSet(data) >>> formset.has_changed() False
ManagementForm
को समझना
आपने अतिरिक्त डेटा (
form-TOTAL_FORMS
,
form-TOTAL_FORMS
form-INITIAL_FORMS
और
form-TOTAL_FORMS
form-MAX_NUM_FORMS
) पर ध्यान दिया होगा जो ऊपर दिए गए फॉर्मेट के डेटा में आवश्यक थे।
यह डेटा
ManagementForm
लिए आवश्यक है।
इस फॉर्म का उपयोग फॉर्मेट में निहित फॉर्म के संग्रह को प्रबंधित करने के लिए फॉर्मेट द्वारा किया जाता है।
यदि आप यह प्रबंधन डेटा प्रदान नहीं करते हैं, तो एक अपवाद उठाया जाएगा:
>>> data = { ... 'form-0-title': 'Test', ... 'form-0-pub_date': '', ... } >>> formset = ArticleFormSet(data) >>> formset.is_valid() Traceback (most recent call last): ... django.forms.utils.ValidationError: ['ManagementForm data is missing or has been tampered with']
इसका उपयोग यह देखने के लिए किया जाता है कि कितने फॉर्म इंस्टेंस प्रदर्शित किए जा रहे हैं।
यदि आप जावास्क्रिप्ट के माध्यम से नए फॉर्म जोड़ रहे हैं, तो आपको इस फॉर्म में गिनती फ़ील्ड भी बढ़ाना चाहिए।
दूसरी ओर, यदि आप मौजूदा वस्तुओं को हटाने की अनुमति देने के लिए जावास्क्रिप्ट का उपयोग कर रहे हैं, तो आपको यह सुनिश्चित करने की आवश्यकता है कि हटाए जा रहे लोगों को
POST
डेटा में
form-#-DELETE
सहित ठीक से हटाने के लिए चिह्नित किया गया है।
यह उम्मीद की जाती है कि सभी फॉर्म
POST
डेटा में मौजूद हैं।
प्रबंधन प्रपत्र स्वयं फॉर्मेट की विशेषता के रूप में उपलब्ध है।
किसी टेम्प्लेट में किसी
{{ my_formset.management_form }}
को प्रस्तुत करते समय, आप
{{ my_formset.management_form }}
प्रतिपादन करके अपने प्रबंधन के सभी आंकड़ों को शामिल कर सकते हैं (उचित रूप में अपने
{{ my_formset.management_form }}
के नाम का प्रतिस्थापन)।
total_form_count
और
initial_form_count
BaseFormSet
में कुछ तरीके हैं जो
ManagementForm
,
total_form_count
और
initial_form_count
से निकटता से संबंधित हैं।
total_form_count
इस
total_form_count
में कुल
total_form_count
लौटाता है।
initial_form_count
पूर्व-भरे गए फ़ॉर्मेट में प्रपत्रों की संख्या लौटाता है, और यह निर्धारित करने के लिए भी उपयोग किया जाता है कि कितने फ़ॉर्म आवश्यक हैं।
आपको शायद इन तरीकों में से किसी को भी ओवरराइड करने की आवश्यकता नहीं होगी, इसलिए कृपया सुनिश्चित करें कि आप ऐसा करने से पहले समझते हैं कि वे क्या करते हैं।
empty_form
BaseFormSet
एक अतिरिक्त विशेषता प्रदान करता है
empty_form
जो जावास्क्रिप्ट के साथ गतिशील रूपों में आसान उपयोग के लिए
__prefix__
उपसर्ग के साथ एक प्रपत्र उदाहरण देता है।
कस्टम फॉर्मेट सत्यापन
एक फॉर्मेट में एक
Form
क्लास पर एक समान विधि होती है।
यह वह जगह है जहाँ आप अपने स्वयं के सत्यापन को परिभाषित करते हैं जो फॉर्मेट स्तर पर काम करता है:
>>> from django.forms import BaseFormSet >>> from django.forms import formset_factory >>> from myapp.forms import ArticleForm >>> class BaseArticleFormSet(BaseFormSet): ... def clean(self): ... """Checks that no two articles have the same title.""" ... if any(self.errors): ... # Don't bother validating the formset unless each form is valid on its own ... return ... titles = [] ... for form in self.forms: ... title = form.cleaned_data['title'] ... if title in titles: ... raise forms.ValidationError("Articles in a set must have distinct titles.") ... titles.append(title) >>> ArticleFormSet = formset_factory(ArticleForm, formset=BaseArticleFormSet) >>> data = { ... 'form-TOTAL_FORMS': '2', ... 'form-INITIAL_FORMS': '0', ... 'form-MAX_NUM_FORMS': '', ... 'form-0-title': 'Test', ... 'form-0-pub_date': '1904-06-16', ... 'form-1-title': 'Test', ... 'form-1-pub_date': '1912-06-23', ... } >>> formset = ArticleFormSet(data) >>> formset.is_valid() False >>> formset.errors [{}, {}] >>> formset.non_form_errors() ['Articles in a set must have distinct titles.']
Form.clean
clean
विधि को सभी
Form.clean
विधियों के बाद कहा जाता है।
त्रुटियों को
non_form_errors()
पर
non_form_errors()
पद्धति का उपयोग करके पाया जाएगा।
एक फॉर्मेट में रूपों की संख्या को मान्य करना
Django न्यूनतम या अधिकतम सबमिट किए गए फ़ॉर्म को मान्य करने के लिए कुछ तरीके प्रदान करता है। जिन अनुप्रयोगों को प्रपत्रों की संख्या के अधिक अनुकूलन योग्य सत्यापन की आवश्यकता है, उन्हें कस्टम फॉर्मसेट सत्यापन का उपयोग करना चाहिए।
validate_max
यदि
validate_max=True
को
formset_factory()
, तो सत्यापन यह भी जाँच करेगा कि डेटा सेट में कितने फॉर्म हैं, जो
max_num
करने के लिए चिह्नित हैं, अधिकतम या उससे अधिक के बराबर है।
>>> from django.forms import formset_factory >>> from myapp.forms import ArticleForm >>> ArticleFormSet = formset_factory(ArticleForm, max_num=1, validate_max=True) >>> data = { ... 'form-TOTAL_FORMS': '2', ... 'form-INITIAL_FORMS': '0', ... 'form-MIN_NUM_FORMS': '', ... 'form-MAX_NUM_FORMS': '', ... 'form-0-title': 'Test', ... 'form-0-pub_date': '1904-06-16', ... 'form-1-title': 'Test 2', ... 'form-1-pub_date': '1912-06-23', ... } >>> formset = ArticleFormSet(data) >>> formset.is_valid() False >>> formset.errors [{}, {}] >>> formset.non_form_errors() ['Please submit 1 or fewer forms.']
validate_max=True
max_num
खिलाफ सख्ती से मान्य होता है, भले ही
max_num
पार हो गया हो क्योंकि आरंभिक डेटा की मात्रा अत्यधिक थी।
ध्यान दें
max_num
बावजूद, यदि डेटा सेट में प्रपत्रों की संख्या
max_num
1000 से अधिक हो
max_num
है, तो वह प्रपत्र मान्य करने में विफल हो जाएगा जैसे कि
validate_max
सेट किए गए थे, और इसके अलावा केवल
max_num
के पहले 1000 फ़ॉर्म ही मान्य होंगे।
शेष को पूरी तरह से काट दिया जाएगा।
यह जाली POST अनुरोधों का उपयोग करके मेमोरी थकावट के हमलों से बचाने के लिए है।
validate_min
यदि
validate_min=True
को
formset_factory()
, तो सत्यापन यह भी जाँच करेगा कि डेटा सेट में रूपों की संख्या, मिटाने के लिए चिह्नित किए गए
formset_factory()
की संख्या,
min_num
से अधिक या बराबर है।
>>> from django.forms import formset_factory >>> from myapp.forms import ArticleForm >>> ArticleFormSet = formset_factory(ArticleForm, min_num=3, validate_min=True) >>> data = { ... 'form-TOTAL_FORMS': '2', ... 'form-INITIAL_FORMS': '0', ... 'form-MIN_NUM_FORMS': '', ... 'form-MAX_NUM_FORMS': '', ... 'form-0-title': 'Test', ... 'form-0-pub_date': '1904-06-16', ... 'form-1-title': 'Test 2', ... 'form-1-pub_date': '1912-06-23', ... } >>> formset = ArticleFormSet(data) >>> formset.is_valid() False >>> formset.errors [{}, {}] >>> formset.non_form_errors() ['Please submit 3 or more forms.']
आदेशों और प्रपत्रों को हटाने के साथ व्यवहार करना
formset_factory()
दो वैकल्पिक पैरामीटर्स
can_order
और
can_delete
को
can_delete
में फॉर्म के ऑर्डर देने और
can_delete
से
can_delete
करने में मदद करता है।
can_order
-
BaseFormSet.can_order
डिफ़ॉल्ट:
False
आप ऑर्डर करने की क्षमता के साथ एक फॉर्मेट बनाते हैं:
>>> from django.forms import formset_factory >>> from myapp.forms import ArticleForm >>> ArticleFormSet = formset_factory(ArticleForm, can_order=True) >>> formset = ArticleFormSet(initial=[ ... {'title': 'Article #1', 'pub_date': datetime.date(2008, 5, 10)}, ... {'title': 'Article #2', 'pub_date': datetime.date(2008, 5, 11)}, ... ]) >>> for form in formset: ... print(form.as_table()) <tr><th><label for="id_form-0-title">Title:</label></th><td><input type="text" name="form-0-title" value="Article #1" id="id_form-0-title"></td></tr> <tr><th><label for="id_form-0-pub_date">Pub date:</label></th><td><input type="text" name="form-0-pub_date" value="2008-05-10" id="id_form-0-pub_date"></td></tr> <tr><th><label for="id_form-0-ORDER">Order:</label></th><td><input type="number" name="form-0-ORDER" value="1" id="id_form-0-ORDER"></td></tr> <tr><th><label for="id_form-1-title">Title:</label></th><td><input type="text" name="form-1-title" value="Article #2" id="id_form-1-title"></td></tr> <tr><th><label for="id_form-1-pub_date">Pub date:</label></th><td><input type="text" name="form-1-pub_date" value="2008-05-11" id="id_form-1-pub_date"></td></tr> <tr><th><label for="id_form-1-ORDER">Order:</label></th><td><input type="number" name="form-1-ORDER" value="2" id="id_form-1-ORDER"></td></tr> <tr><th><label for="id_form-2-title">Title:</label></th><td><input type="text" name="form-2-title" id="id_form-2-title"></td></tr> <tr><th><label for="id_form-2-pub_date">Pub date:</label></th><td><input type="text" name="form-2-pub_date" id="id_form-2-pub_date"></td></tr> <tr><th><label for="id_form-2-ORDER">Order:</label></th><td><input type="number" name="form-2-ORDER" id="id_form-2-ORDER"></td></tr>
यह प्रत्येक फॉर्म में एक अतिरिक्त फ़ील्ड जोड़ता है।
इस नए फ़ील्ड का नाम
ORDER
और यह एक
forms.IntegerField
।
forms.IntegerField
।
प्रारंभिक डेटा से आए रूपों के लिए यह स्वचालित रूप से उन्हें एक संख्यात्मक मान असाइन करता है।
आइए देखें कि उपयोगकर्ता द्वारा इन मूल्यों को बदलने पर क्या होगा:
>>> data = { ... 'form-TOTAL_FORMS': '3', ... 'form-INITIAL_FORMS': '2', ... 'form-MAX_NUM_FORMS': '', ... 'form-0-title': 'Article #1', ... 'form-0-pub_date': '2008-05-10', ... 'form-0-ORDER': '2', ... 'form-1-title': 'Article #2', ... 'form-1-pub_date': '2008-05-11', ... 'form-1-ORDER': '1', ... 'form-2-title': 'Article #3', ... 'form-2-pub_date': '2008-05-01', ... 'form-2-ORDER': '0', ... } >>> formset = ArticleFormSet(data, initial=[ ... {'title': 'Article #1', 'pub_date': datetime.date(2008, 5, 10)}, ... {'title': 'Article #2', 'pub_date': datetime.date(2008, 5, 11)}, ... ]) >>> formset.is_valid() True >>> for form in formset.ordered_forms: ... print(form.cleaned_data) {'pub_date': datetime.date(2008, 5, 1), 'ORDER': 0, 'title': 'Article #3'} {'pub_date': datetime.date(2008, 5, 11), 'ORDER': 1, 'title': 'Article #2'} {'pub_date': datetime.date(2008, 5, 10), 'ORDER': 2, 'title': 'Article #1'}
can_delete
-
BaseFormSet.can_delete
डिफ़ॉल्ट:
False
डिलीट के लिए फॉर्म चुनने की क्षमता के साथ आप एक फॉर्मेट बनाते हैं:
>>> from django.forms import formset_factory >>> from myapp.forms import ArticleForm >>> ArticleFormSet = formset_factory(ArticleForm, can_delete=True) >>> formset = ArticleFormSet(initial=[ ... {'title': 'Article #1', 'pub_date': datetime.date(2008, 5, 10)}, ... {'title': 'Article #2', 'pub_date': datetime.date(2008, 5, 11)}, ... ]) >>> for form in formset: ... print(form.as_table()) <tr><th><label for="id_form-0-title">Title:</label></th><td><input type="text" name="form-0-title" value="Article #1" id="id_form-0-title"></td></tr> <tr><th><label for="id_form-0-pub_date">Pub date:</label></th><td><input type="text" name="form-0-pub_date" value="2008-05-10" id="id_form-0-pub_date"></td></tr> <tr><th><label for="id_form-0-DELETE">Delete:</label></th><td><input type="checkbox" name="form-0-DELETE" id="id_form-0-DELETE"></td></tr> <tr><th><label for="id_form-1-title">Title:</label></th><td><input type="text" name="form-1-title" value="Article #2" id="id_form-1-title"></td></tr> <tr><th><label for="id_form-1-pub_date">Pub date:</label></th><td><input type="text" name="form-1-pub_date" value="2008-05-11" id="id_form-1-pub_date"></td></tr> <tr><th><label for="id_form-1-DELETE">Delete:</label></th><td><input type="checkbox" name="form-1-DELETE" id="id_form-1-DELETE"></td></tr> <tr><th><label for="id_form-2-title">Title:</label></th><td><input type="text" name="form-2-title" id="id_form-2-title"></td></tr> <tr><th><label for="id_form-2-pub_date">Pub date:</label></th><td><input type="text" name="form-2-pub_date" id="id_form-2-pub_date"></td></tr> <tr><th><label for="id_form-2-DELETE">Delete:</label></th><td><input type="checkbox" name="form-2-DELETE" id="id_form-2-DELETE"></td></tr>
can_order
तरह
can_order
यह
DELETE
नाम के प्रत्येक फॉर्म में एक नया फ़ील्ड जोड़ता है और एक
forms.BooleanField
।
forms.BooleanField
।
जब डेटा किसी भी हटाए गए फ़ील्ड को चिह्नित करने के माध्यम से आता है, तो आप उन्हें
deleted_forms
एक्सेस कर सकते हैं:
>>> data = { ... 'form-TOTAL_FORMS': '3', ... 'form-INITIAL_FORMS': '2', ... 'form-MAX_NUM_FORMS': '', ... 'form-0-title': 'Article #1', ... 'form-0-pub_date': '2008-05-10', ... 'form-0-DELETE': 'on', ... 'form-1-title': 'Article #2', ... 'form-1-pub_date': '2008-05-11', ... 'form-1-DELETE': '', ... 'form-2-title': '', ... 'form-2-pub_date': '', ... 'form-2-DELETE': '', ... } >>> formset = ArticleFormSet(data, initial=[ ... {'title': 'Article #1', 'pub_date': datetime.date(2008, 5, 10)}, ... {'title': 'Article #2', 'pub_date': datetime.date(2008, 5, 11)}, ... ]) >>> [form.cleaned_data for form in formset.deleted_forms] [{'DELETE': True, 'pub_date': datetime.date(2008, 5, 10), 'title': 'Article #1'}]
यदि आप एक
ModelFormSet
का उपयोग कर रहे हैं, तो जब आप
formset.save()
कॉल करते हैं, तो हटाए गए प्रपत्रों के मॉडल उदाहरण हटा दिए जाएंगे।
यदि आप
formset.save(commit=False)
, तो ऑब्जेक्ट स्वचालित रूप से हटाए नहीं जाएंगे।
आपको प्रत्येक
formset.deleted_objects
पर
delete()
को कॉल करना होगा। वास्तव में उन्हें डिलीट करने के लिए:
>>> instances = formset.save(commit=False) >>> for obj in formset.deleted_objects: ... obj.delete()
दूसरी ओर, यदि आप एक सादे
FormSet
का उपयोग कर रहे हैं, तो यह आपके ऊपर है कि आप अपने
formset.deleted_forms
की
save()
विधि में, शायद
formset.deleted_forms
को संभाल
formset.deleted_forms
, क्योंकि किसी फॉर्म को डिलीट करने का कोई सामान्य अर्थ नहीं है।
एक फॉर्मेट में अतिरिक्त फ़ील्ड जोड़ना
यदि आपको फॉर्मेट में अतिरिक्त फ़ील्ड जोड़ने की आवश्यकता है तो इसे आसानी से पूरा किया जा सकता है।
फॉर्मसेट बेस क्लास एक
add_fields
विधि प्रदान करता है।
आप अपने स्वयं के फ़ील्ड को जोड़ने के लिए इस विधि को ओवरराइड कर सकते हैं या यहां तक कि डिफ़ॉल्ट फ़ील्ड / ऑर्डर और विलोपन फ़ील्ड की विशेषताओं को फिर से परिभाषित कर सकते हैं:
>>> from django.forms import BaseFormSet >>> from django.forms import formset_factory >>> from myapp.forms import ArticleForm >>> class BaseArticleFormSet(BaseFormSet): ... def add_fields(self, form, index): ... super().add_fields(form, index) ... form.fields["my_field"] = forms.CharField() >>> ArticleFormSet = formset_factory(ArticleForm, formset=BaseArticleFormSet) >>> formset = ArticleFormSet() >>> for form in formset: ... print(form.as_table()) <tr><th><label for="id_form-0-title">Title:</label></th><td><input type="text" name="form-0-title" id="id_form-0-title"></td></tr> <tr><th><label for="id_form-0-pub_date">Pub date:</label></th><td><input type="text" name="form-0-pub_date" id="id_form-0-pub_date"></td></tr> <tr><th><label for="id_form-0-my_field">My field:</label></th><td><input type="text" name="form-0-my_field" id="id_form-0-my_field"></td></tr>
फॉरमेट के लिए कस्टम पैरामीटर पास करना
कभी-कभी आपका फॉर्म क्लास कस्टम पैरामीटर लेता है, जैसे
MyArticleForm
।
आप इस पैरामीटर को तब पास कर सकते हैं जब फॉर्मेट को तत्काल किया जा रहा हो:
>>> from django.forms import BaseFormSet >>> from django.forms import formset_factory >>> from myapp.forms import ArticleForm >>> class MyArticleForm(ArticleForm): ... def __init__(self, *args, user, **kwargs): ... self.user = user ... super().__init__(*args, **kwargs) >>> ArticleFormSet = formset_factory(MyArticleForm) >>> formset = ArticleFormSet(form_kwargs={'user': request.user})
form_kwargs
विशिष्ट प्रपत्र उदाहरण पर भी निर्भर हो सकता है।
get_form_kwargs
बेस क्लास एक
get_form_kwargs
विधि प्रदान करता है।
विधि एकल तर्क लेती है - फॉर्मेट में फॉर्म का सूचकांक।
अनुक्रमणिका
empty_form
लिए
None
:
>>> from django.forms import BaseFormSet >>> from django.forms import formset_factory >>> class BaseArticleFormSet(BaseFormSet): ... def get_form_kwargs(self, index): ... kwargs = super().get_form_kwargs(index) ... kwargs['custom_kwarg'] = index ... return kwargs
एक फॉर्मेट के उपसर्ग को अनुकूलित करना
प्रदान किए गए HTML में, फ़ॉर्मेट्स में प्रत्येक फ़ील्ड के नाम पर एक उपसर्ग शामिल होता है।
डिफ़ॉल्ट रूप से, उपसर्ग
'form'
, लेकिन इसे फॉर्मेट के
prefix
तर्क का उपयोग करके अनुकूलित किया जा सकता है।
उदाहरण के लिए, डिफ़ॉल्ट मामले में, आप देख सकते हैं:
<label for="id_form-0-title">Title:</label> <input type="text" name="form-0-title" id="id_form-0-title">
लेकिन
ArticleFormset(prefix='article')
जो बन जाता है:
<label for="id_article-0-title">Title:</label> <input type="text" name="article-0-title" id="id_article-0-title">
यदि आप एक दृश्य में एक से अधिक फॉर्मेट का उपयोग करना चाहते हैं तो यह उपयोगी है।
विचारों और टेम्पलेट्स में एक फॉर्मेट का उपयोग करना
एक दृश्य के अंदर एक फ़ॉर्मेट का उपयोग करना उतना ही आसान है जितना कि एक नियमित रूप से उपयोग करना। केवल एक चीज जिसे आप जानना चाहते हैं, वह टेम्पलेट के अंदर प्रबंधन फ़ॉर्म का उपयोग करना सुनिश्चित कर रहा है। आइए एक नमूना दृश्य देखें:
from django.forms import formset_factory from django.shortcuts import render from myapp.forms import ArticleForm def manage_articles(request): ArticleFormSet = formset_factory(ArticleForm) if request.method == 'POST': formset = ArticleFormSet(request.POST, request.FILES) if formset.is_valid(): # do something with the formset.cleaned_data pass else: formset = ArticleFormSet() return render(request, 'manage_articles.html', {'formset': formset})
manage_articles.html
टेम्पलेट इस तरह दिख सकता है:
<form method="post"> {{ formset.management_form }} <table> {% for form in formset %} {{ form }} {% endfor %} </table> </form>
हालाँकि, फॉर्मेट को प्रबंधन फ़ॉर्म से निपटने की अनुमति देकर ऊपर के लिए एक छोटा शॉर्टकट है:
<form method="post"> <table> {{ formset }} </table> </form>
ऊपर के
as_table
क्लास पर
as_table
मेथड कहते हुए समाप्त होता है।
मैन्युअल रूप से प्रदान किया गया
can_delete
और
can_order
यदि आप मैन्युअल रूप से टेम्प्लेट में फ़ील्ड रेंडर करते हैं, तो आप
{{ form.DELETE }}
साथ
can_delete
पैरामीटर रेंडर कर सकते हैं:
<form method="post"> {{ formset.management_form }} {% for form in formset %} <ul> <li>{{ form.title }}</li> <li>{{ form.pub_date }}</li> {% if formset.can_delete %} <li>{{ form.DELETE }}</li> {% endif %} </ul> {% endfor %} </form>
इसी तरह, यदि
can_order=True
ऑर्डर करने की क्षमता है (
can_order=True
), तो इसे
{{ form.ORDER }}
साथ रेंडर करना संभव है।
एक दृश्य में एक से अधिक फॉर्मेट का उपयोग करना
यदि आप चाहें तो एक दृश्य में एक से अधिक फॉर्मेट का उपयोग करने में सक्षम हैं। फ़ॉर्मेट अपने व्यवहार का अधिकांश रूप रूपों से उधार लेता है। इसके साथ आपने कहा कि आप किसी दिए गए मान के साथ उपसर्ग फॉर्मसेट फॉर्म फ़ील्ड नामों के लिए उपसर्ग का उपयोग करने में सक्षम हैं, एक से अधिक फॉर्मेट को बिना नाम के टकराव के एक दृश्य में भेजने की अनुमति देता है। आइए देखें कि यह कैसे पूरा किया जा सकता है:
from django.forms import formset_factory from django.shortcuts import render from myapp.forms import ArticleForm, BookForm def manage_articles(request): ArticleFormSet = formset_factory(ArticleForm) BookFormSet = formset_factory(BookForm) if request.method == 'POST': article_formset = ArticleFormSet(request.POST, request.FILES, prefix='articles') book_formset = BookFormSet(request.POST, request.FILES, prefix='books') if article_formset.is_valid() and book_formset.is_valid(): # do something with the cleaned_data on the formsets. pass else: article_formset = ArticleFormSet(prefix='articles') book_formset = BookFormSet(prefix='books') return render(request, 'manage_articles.html', { 'article_formset': article_formset, 'book_formset': book_formset, })
फिर आप सामान्य रूप से फॉर्मेट्स को प्रस्तुत करेंगे।
यह इंगित करना महत्वपूर्ण है कि आपको POST और गैर-POST दोनों मामलों में
prefix
पास करने की आवश्यकता है ताकि यह सही तरीके से प्रस्तुत और संसाधित हो।
प्रत्येक फॉर्मेट का
prefix
डिफ़ॉल्ट
form
prefix
को प्रतिस्थापित करता है जो प्रत्येक फ़ील्ड के
name
और
id
HTML विशेषताओं में जोड़ा जाता है।