Django: रूपों का उपयोग कर एक टेम्पलेट में कई मॉडल [बंद]


114

मैं एक समर्थन टिकट ट्रैकिंग ऐप बना रहा हूं और कुछ मॉडल हैं जो मैं एक पृष्ठ से बनाना चाहता हूं। टिकट एक विदेशी के माध्यम से एक ग्राहक के हैं। नोट्स एक विदेश यात्रा के माध्यम से भी टिकट से संबंधित हैं। मैं एक ग्राहक (यह एक पूरी अलग परियोजना) का चयन करने या एक नया ग्राहक बनाने, फिर एक टिकट बनाने और अंत में नए टिकट को सौंपा गया नोट बनाने का विकल्प रखना चाहता हूं।

चूंकि मैं Django के लिए काफी नया हूं, इसलिए मैं हर बार नए फीचर्स की कोशिश कर रहा हूं। मैंने ModelForms के साथ खेला है, लेकिन मैं कुछ क्षेत्रों को छिपाना चाहता हूं और कुछ जटिल सत्यापन करना चाहता हूं। ऐसा लगता है कि मैं जिस स्तर के नियंत्रण की तलाश कर रहा हूं, उसे थकाऊ, हाथ से कोडित टेम्पलेट पृष्ठ के साथ फ़ॉर्मेट या हाथ से सब कुछ करने की आवश्यकता है, जिससे मैं बचने की कोशिश कर रहा हूं।

वहाँ कुछ सुंदर सुविधा मुझे याद आ रही है? क्या किसी के पास फॉर्मेट्स का उपयोग करने के लिए एक अच्छा संदर्भ या उदाहरण है? मैंने उनके लिए एपीआई डॉक्स पर एक पूरा सप्ताहांत बिताया और मैं अब भी क्लूलेस हूं। क्या यह एक डिज़ाइन का मुद्दा है अगर मैं सब कुछ तोड़कर हाथ से कोड करूँ?


सबसे पहले आपको अपने ग्राहक फ़ॉर्म को मान्य करना चाहिए और यदि यह मान्य था, तो request.POST (new_data = request.POST.copy) ()) से एक प्रति बनाएँ और फिर ग्राहक आईडी (मान्य ग्राहक फ़ॉर्म से) प्राप्त करें और new_ata को अपडेट करने के साथ, बनाएं। ग्राहक आइडी विदेशी क्षेत्र के लिए एक मूल्य है (शायद आपके मॉडल में ग्राहक)। और अंत में अपने दूसरे फॉर्म (टिकट) को मान्य करने के लिए new_data पर विचार करें
Negar37

जवाबों:


87

यह वास्तव में ModelForms के साथ लागू करने के लिए बहुत मुश्किल नहीं है । तो मान लें कि आपके पास फ़ॉर्म ए, बी और सी हैं। आप प्रत्येक फॉर्म और पेज का प्रिंट आउट लेते हैं और अब आपको POST को संभालने की आवश्यकता है।

if request.POST():
    a_valid = formA.is_valid()
    b_valid = formB.is_valid()
    c_valid = formC.is_valid()
    # we do this since 'and' short circuits and we want to check to whole page for form errors
    if a_valid and b_valid and c_valid:
        a = formA.save()
        b = formB.save(commit=False)
        c = formC.save(commit=False)
        b.foreignkeytoA = a
        b.save()
        c.foreignkeytoB = b
        c.save()

कस्टम सत्यापन के लिए यहां डॉक्स दिए गए हैं।


2
btw, मुझे नहीं लगता कि आपके द्वारा बताई गई समस्या के लिए फॉर्मेट अच्छा समाधान है। मैंने हमेशा एक मॉडल के कई उदाहरणों का प्रतिनिधित्व करने के लिए उनका उपयोग किया। जैसे कि आपके पास एक आवेदक फॉर्म है और आप चाहते हैं कि 3 संदर्भ आपके लिए एक फॉर्मेट बनाएं जिसमें संदर्भ मॉडल के 3 उदाहरण हैं।
जेसन क्रिस्टा

1
ध्यान दें कि, जिस तरह से आप इसे करते हैं, .is_valid () कॉल कम परिचालित नहीं है। यदि आप इसे शॉर्ट सर्किट करना चाहते हैं, तो आपको .is_valid () फ़ंक्शन को 'और' तक कॉल करने में विलंब करना होगा।
रेयान

66

मैं अभी एक दिन पहले उसी स्थिति में था, और यहाँ मेरे 2 सेंट हैं:

1) मुझे यकीनन यहां एकल रूप में कई मॉडल प्रविष्टि का सबसे छोटा और सबसे संक्षिप्त प्रदर्शन मिला: http://collingrady.wordpress.com/2008/02/18/editing-multiple-objects-in-django-with-newforms/

संक्षेप में: प्रत्येक मॉडल के लिए एक फॉर्म बनाएं, उन दोनों को टेम्प्लेट में सबमिट करें <form>, prefixकीरग का उपयोग करके और व्यू हैंडल को मान्यता दें। यदि निर्भरता है, तो सुनिश्चित करें कि आप "माता-पिता" मॉडल को निर्भर होने से पहले सहेजते हैं, और "बच्चे" मॉडल को बचाने से पहले विदेशी कुंजी के लिए माता-पिता की आईडी का उपयोग करें। लिंक में डेमो है।

2) हो सकता है कि ऐसा करने में फॉर्मेट्स को पीटा जा सकता है, लेकिन जहां तक ​​मैंने डिलीट किया है, फॉर्मेट्स मुख्य रूप से उसी मॉडल के गुणकों में प्रवेश करने के लिए हैं, जो विदेशी कुंजी द्वारा दूसरे मॉडल / मॉडल से वैकल्पिक रूप से बंधे हो सकते हैं। हालाँकि, एक से अधिक मॉडल के डेटा में प्रवेश करने के लिए कोई डिफ़ॉल्ट विकल्प नहीं है और ऐसा नहीं है कि फॉर्मेट का अर्थ क्या है।


26

मुझे हाल ही में कुछ समस्या हुई थी और यह पता लगा कि यह कैसे करना है। मान लें कि आपके पास तीन कक्षाएं हैं, प्राथमिक, बी, सी और उस बी, सी में प्राथमिक के लिए एक विदेशी कुंजी है

    class PrimaryForm(ModelForm):
        class Meta:
            model = Primary

    class BForm(ModelForm):
        class Meta:
            model = B
            exclude = ('primary',)

    class CForm(ModelForm):
         class Meta:
            model = C
            exclude = ('primary',)

    def generateView(request):
        if request.method == 'POST': # If the form has been submitted...
            primary_form = PrimaryForm(request.POST, prefix = "primary")
            b_form = BForm(request.POST, prefix = "b")
            c_form = CForm(request.POST, prefix = "c")
            if primary_form.is_valid() and b_form.is_valid() and c_form.is_valid(): # All validation rules pass
                    print "all validation passed"
                    primary = primary_form.save()
                    b_form.cleaned_data["primary"] = primary
                    b = b_form.save()
                    c_form.cleaned_data["primary"] = primary
                    c = c_form.save()
                    return HttpResponseRedirect("/viewer/%s/" % (primary.name))
            else:
                    print "failed"

        else:
            primary_form = PrimaryForm(prefix = "primary")
            b_form = BForm(prefix = "b")
            c_form = Form(prefix = "c")
     return render_to_response('multi_model.html', {
     'primary_form': primary_form,
     'b_form': b_form,
     'c_form': c_form,
      })

इस पद्धति से आपको एक ही पृष्ठ पर तीनों वस्तुओं को बनाने के साथ-साथ आपको जो भी सत्यापन की आवश्यकता होती है, करने की अनुमति मिल सकती है। मैंने एक ही पृष्ठ पर कई बी, सी ऑब्जेक्ट की पीढ़ी की अनुमति देने के लिए जावास्क्रिप्ट और छिपे हुए फ़ील्ड का भी उपयोग किया है।


3
इस उदाहरण में, आप मॉडल B और C के लिए प्राथमिक मॉडल को इंगित करने के लिए विदेशी कुंजी कैसे सेट कर रहे हैं?
यूजर

मेरे पास केवल दो मॉडल हैं जिन्हें मैं उसी रूप में दिखाना चाहता हूं। लेकिन मुझे बहिष्करण = ('प्राथमिक') कथन नहीं मिलता है। प्राथमिक क्या है? यदि 2 मॉडल CustomerConfig और अनुबंध हैं। अनुबंध के पास CustomerConfig की विदेशी कुंजी है। जैसे कि customer_config = model.ForeignKey ('CustomerPartnerConfiguration') 'प्राथमिक' क्या है?
पिचब्लैक 408

10

MultiModelForm से django-betterformsक्या में वर्णन किया गया करने के लिए एक सुविधाजनक आवरण है Gnudiff का जवाब । यह ModelFormएक एकल वर्ग में नियमित रूप से लपेटता है जो पारदर्शी रूप से (मूल उपयोग के लिए कम से कम) एकल रूप में उपयोग किया जाता है। मैंने नीचे उनके डॉक्स से एक उदाहरण कॉपी किया है।

# forms.py
from django import forms
from django.contrib.auth import get_user_model
from betterforms.multiform import MultiModelForm
from .models import UserProfile

User = get_user_model()

class UserEditForm(forms.ModelForm):
    class Meta:
        fields = ('email',)

class UserProfileForm(forms.ModelForm):
    class Meta:
        fields = ('favorite_color',)

class UserEditMultiForm(MultiModelForm):
    form_classes = {
        'user': UserEditForm,
        'profile': UserProfileForm,
    }

# views.py
from django.views.generic import UpdateView
from django.core.urlresolvers import reverse_lazy
from django.shortcuts import redirect
from django.contrib.auth import get_user_model
from .forms import UserEditMultiForm

User = get_user_model()

class UserSignupView(UpdateView):
    model = User
    form_class = UserEditMultiForm
    success_url = reverse_lazy('home')

    def get_form_kwargs(self):
        kwargs = super(UserSignupView, self).get_form_kwargs()
        kwargs.update(instance={
            'user': self.object,
            'profile': self.object.profile,
        })
        return kwargs

बस देखा django-betterformsऔर अपने जवाब से पहले आने से पहले इसका MultiModelForm वर्ग। उनका समाधान वास्तविक अच्छा लगता है, लेकिन ऐसा लगता है कि इसे थोड़ी देर में अपडेट नहीं किया गया है। क्या आप अभी भी इस @jozxyqk का उपयोग कर रहे हैं? काई समस्या?
ENCHANCE

@enchance कुछ साल हो गए हैं। वापस तो मुझे यह सुविधाजनक और आसपास बेहतर विकल्पों में से एक लगा। यदि आप इसके साथ बहुत अधिक फैंसी नहीं हैं, तो यह कुछ समय बचाता है। मैं कल्पना कर सकता हूं कि जब आप कस्टमाइज़ करना शुरू करना चाहते हैं और गैर-तुच्छ रूप करना चाहते हैं तो अपने आप को रोल करना आसान होगा। आसानी से रूपों और संदर्भों को विचारों में मिलाना पहली विशेषता है जो मुझे लगता है कि मुझे डेजैंगो में याद आती है।
jozxyqk

उत्तर के लिए धन्यवाद आदमी। मैं सिर्फ इस पर विचार करने के लिए विचार कर रहा हूं और शायद रास्ते में कुछ चीजों को अपडेट कर सकता हूं। मैंने अब तक जो देखा है, वह ठीक काम कर रहा है। आप सही कह रहे हैं, यह बहुत बड़ा समय है।
ENCHANCE

5

वर्तमान में मेरे पास वर्कअराउंड फंक्शनल है (यह मेरी यूनिट टेस्ट पास करता है)। यह मेरी राय का एक अच्छा समाधान है जब आप केवल अन्य मॉडलों से सीमित संख्या में फ़ील्ड जोड़ना चाहते हैं।

क्या मुझसे कोई चूक हो रही है ?

class UserProfileForm(ModelForm):
    def __init__(self, instance=None, *args, **kwargs):
        # Add these fields from the user object
        _fields = ('first_name', 'last_name', 'email',)
        # Retrieve initial (current) data from the user object
        _initial = model_to_dict(instance.user, _fields) if instance is not None else {}
        # Pass the initial data to the base
        super(UserProfileForm, self).__init__(initial=_initial, instance=instance, *args, **kwargs)
        # Retrieve the fields from the user model and update the fields with it
        self.fields.update(fields_for_model(User, _fields))

    class Meta:
        model = UserProfile
        exclude = ('user',)

    def save(self, *args, **kwargs):
        u = self.instance.user
        u.first_name = self.cleaned_data['first_name']
        u.last_name = self.cleaned_data['last_name']
        u.email = self.cleaned_data['email']
        u.save()
        profile = super(UserProfileForm, self).save(*args,**kwargs)
        return profile

3

"मैं कुछ क्षेत्रों को छिपाना चाहता हूं और कुछ जटिल सत्यापन करना चाहता हूं।"

मैं अंतर्निहित व्यवस्थापक इंटरफ़ेस के साथ शुरू करता हूं।

  1. वांछित क्षेत्रों को दिखाने के लिए ModelForm का निर्माण करें।

  2. फॉर्म के भीतर सत्यापन नियमों के साथ प्रपत्र बढ़ाएँ। आमतौर पर यह एक cleanविधि है।

    सुनिश्चित करें कि यह हिस्सा यथोचित काम करता है।

एक बार यह पूरा हो जाने के बाद, आप बिल्ट-इन एडमिन इंटरफेस से दूर जा सकते हैं।

फिर आप एक वेब पेज पर कई, आंशिक रूप से संबंधित रूपों के साथ बेवकूफ बना सकते हैं। यह एक पृष्ठ पर सभी रूपों को प्रस्तुत करने के लिए टेम्पलेट सामग्री का एक गुच्छा है।

फिर आपको विभिन्न फॉर्म चीजों को पढ़ने और मान्य करने और विभिन्न ऑब्जेक्ट सेव () करने के लिए व्यू फ़ंक्शन लिखना होगा।

"क्या यह एक डिज़ाइन मुद्दा है अगर मैं टूट गया और हाथ-कोड सब कुछ?" नहीं, यह बहुत अधिक लाभ नहीं होने के लिए बहुत समय है।


मैं नहीं जानता कि कैसे, इसलिए यह मत करो
orokusaki

1
@orokusaki: और क्या आप चाहेंगे? यह एक समाधान का वर्णन करने के लिए लगता है। और क्या कहा जाना चाहिए? सवाल अस्पष्ट है, इसलिए वास्तविक कोड प्रदान करना कठिन है। शिकायत के बजाय, कृपया सुधार के लिए एक सुझाव प्रदान करें। आपकी क्या सलाह है?
S.Lott

1

Django प्रलेखन के अनुसार, इनलाइन फॉर्मेट्स इस उद्देश्य के लिए हैं: "इनलाइन फॉर्मेट्स मॉडल फॉर्मेट्स के शीर्ष पर एक छोटी सी अमूर्त परत है। ये एक विदेशी कुंजी के माध्यम से संबंधित वस्तुओं के साथ काम करने के मामले को सरल बनाते हैं"।

Https://docs.djangoproject.com/en/dev/topics/forms/modelforms/#inline-formsets देखें

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.