2011-11-28 9 views
12

को बचाने यही सवाल this one के लिए इसी तरह लग सकता है, लेकिन इसकी नहीं ...अवहेलना Django InlineModelAdmin

मैं एक मॉडल संरचना है की तरह:

class Customer(models.Model): 
    .... 

class CustomerCompany(models.Model): 
    customer = models.ForeignKey(Customer) 
    type = models.SmallIntegerField(....) 

मैं InlineModels उपयोग कर रहा हूँ, और के दो प्रकार के CustomerCampany.type। इसलिए मैं CustomerCompany के लिए दो अलग अलग इनलाइन को परिभाषित करने और ओवरराइड OV InlineModelAdmin.queryset

class CustomerAdmin(admin.ModelAdmin): 
    inlines=[CustomerCompanyType1Inline, CustomerCompanyType2Inline] 


class CustomerCompanyType1Inline(admin.TabularInline): 
    model = CustomerCompany 
    def queryset(self, request): 
     return super(CustomerCompanyType1Inline, self).queryset(request).filter(type=1) 

class CustomerCompanyType2Inline(admin.TabularInline): 
    model = CustomerCompany 
    def queryset(self, request): 
     return super(CustomerCompanyType2Inline, self).queryset(request).filter(type=2) 

सभी अच्छा और यहां तक ​​अच्छा है, लेकिन InlineModelAdmin के लिए नए रिकॉर्ड जोड़ने के लिए, मैं अभी भी AdminForm पर CustomerCompany की type क्षेत्र प्रदर्शित करने के लिए की जरूरत है, के बाद से मैं एक InlineModelAdmin की save विधि ओवरराइड नहीं कर सकते की तरह:

class CustomerCompanyType2Inline(admin.TabularInline): 
    model = CustomerCompany 
    def queryset(self, request): 
     return super(CustomerCompanyType2Inline, self).queryset(request).filter(type=2) 
    #Following override do not work 
    def save_model(self, request, obj, form, change): 
     obj.type=2 
     obj.save() 

एक संकेत का उपयोग करना भी एक समाधान मेरी संकेत के बाद से sender ही 012 हो जाएगा नहीं है, तो मैं पहचान नहीं कर सकता जो InlineModelAdmin इसे भेजने और type क्या होना चाहिए ...

वहाँ एक रास्ता मुझे सेट type क्षेत्र से पहले बचाने देंगे है?

उत्तर

23

अलासडेयर का जवाब गलत नहीं है, लेकिन इसमें कुछ गंभीर मुद्दे हैं जो समस्याएं पैदा कर सकते हैं। सबसे पहले, वेरिएबल नाम के रूप में form का उपयोग करके फ़ॉर्मेट के माध्यम से लूप करके, आप वास्तव में form के लिए विधि में पारित मान को ओवरराइड करते हैं। यह एक बड़ा सौदा नहीं है, लेकिन चूंकि आप फॉर्मेट से सीधे बिना प्रतिबद्ध किए बचत कर सकते हैं, इसलिए इसे बेहतर तरीके से करना बेहतर है। दूसरा, सभी महत्वपूर्ण formset.save_m2m() उत्तर से बाहर छोड़ा गया था। वास्तविक Django docs की सलाह देते हैं निम्नलिखित:

def save_formset(self, request, form, formset, change): 
    instances = formset.save(commit=False) 
    for instance in instances: 
     # Do something with `instance` 
     instance.save() 
    formset.save_m2m() 
समस्या आप में चलाने के लिए जा रहे है कि save_formset विधि inlines बजाय माता पिता ModelAdmin चलते रहना चाहिए, और वहाँ से, वहाँ कोई रास्ता नहीं है जो इनलाइन पता करने के लिए है

वास्तव में उपयोग किया जा रहा है। यदि आपके पास दो "प्रकार" के साथ ओबीजे है और सभी फ़ील्ड समान हैं, तो आपको प्रॉक्सी मॉडल का उपयोग करना चाहिए और आप वास्तव में उचित प्रकार को स्वचालित प्रकार सेट करने के लिए प्रत्येक की बचत विधि को ओवरराइड कर सकते हैं।

class CustomerCompanyType1(CustomerCompany): 
    class Meta: 
     proxy = True 

    def save(self, *args, **kwargs): 
     self.type = 1 
     super(CustomerCompanyType1, self).save(*args, **kwargs) 

class CustomerCompanyType2(CustomerCompany): 
    class Meta: 
     proxy = True 

    def save(self, *args, **kwargs): 
     self.type = 2 
     super(CustomerCompanyType2, self).save(*args, **kwargs) 

फिर, आपको अपनी इनलाइनों के साथ कुछ भी विशेष करने की आवश्यकता नहीं है। बस अपने मौजूदा इनलाइन व्यवस्थापक वर्गों को उनके उचित प्रॉक्सी मॉडल का उपयोग करने के लिए बदलें, और सब कुछ स्वयं को हल कर देगा।

+0

+1 अच्छा दृष्टिकोण प्रॉक्सी मॉडल का उपयोग करने के लिए।मैंने आपके द्वारा वर्णित सबसे स्पष्ट गलतियों को ठीक करने के लिए अपना उत्तर अपडेट किया। यह अभी भी काम करने की समस्या को छोड़ देता है जो फ़ॉर्मेट का प्रतिनिधित्व करता है। – Alasdair

+0

दरअसल, प्रॉक्सी मॉडल दृष्टिकोण 'save_formset' को ओवरराइड करने की आवश्यकता को हटा देता है। प्रॉक्सी स्वयं ने 'सेव' विधियों को ओवरराइड कर दिया है जो सही प्रकार के रूप में सहेजने के बारे में जानते हैं। तो, फिर आप इसके बारे में चिंता किए बिना इनलाइन का उपयोग करें। –

+0

मेरी टिप्पणी स्पष्ट नहीं थी - मैं इस बात से सहमत था कि 'save_formset' ('save_m2m' आदि) में समस्याओं को ठीक करने के बाद भी, अभी भी उस समस्या का मुद्दा था जिसे आप सहेज रहे हैं। मुझे समझ में आया कि प्रॉक्सी मॉडल दृष्टिकोण से बचा जाता है :) – Alasdair

5

save_formset विधि है जिसे आप ओवरराइड कर सकते हैं। आपको काम करना होगा कि formset किसी भी तरह का प्रतिनिधित्व करता है।

def save_formset(self, request, form, formset, change): 
    instances = formset.save(commit=False) 
    for instance in instances: 
     # Do something with `instance` 
     instance.save() 
    formset.save_m2m() 
0

save_formset का उपयोग करने के लिए अन्य उत्तरों सही हैं। वे यह जांचने का एक तरीका खो रहे हैं कि वर्तमान में कौन सा मॉडल सहेजा गया है। ऐसा करने के लिए, आप बस कर सकते हैं:

if formset.model == CustomerCompany: 
    # actions for specific model 

कौन सा तरह save_formset समारोह देखो बनाना होगा: (यह मानते हुए आप न केवल विशिष्ट मॉडल (रों) को बचाने के लिए ओवरराइड करना चाहते)

def save_formset(self, request, form, formset, change): 

    # if it's not the model we want to change 
    # just call the default function 
    if formset.model != CustomerCompany: 
     return super(CustomerAdmin, self).save_formset(request, form, formset, change) 

    # if it is, do our custom stuff 
    instances = formset.save(commit=False) 
    for instance in instances: 
     instance.type = 2 
     instance.save() 
    formset.save_m2m() 
संबंधित मुद्दे