2010-05-18 15 views
12

मैं निम्नलिखित मॉडल:Django व्यवस्थापक: कई करने वाली कई लिस्टबॉक्स पैरामीटर के माध्यम से एक साथ दिखाई नहीं देता

class Message(models.Model): 
    date = models.DateTimeField() 
    user = models.ForeignKey(User)  
    thread = models.ForeignKey('self', blank=True, null=True) 
    ... 

class Forum(models.Model): 
    name = models.CharField(max_length=24) 
    messages = models.ManyToManyField(Message, through="Message_forum", blank=True, null=True) 
    ... 

class Message_forum(models.Model): 
    message = models.ForeignKey(Message) 
    forum = models.ForeignKey(Forum) 
    status = models.IntegerField() 
    position = models.IntegerField(blank=True, null=True) 
    tags = models.ManyToManyField(Tag, blank=True, null=True) 

व्यवस्थापक साइट में, जब मैं जोड़ने के लिए जाना/एक मंच बदलने के लिए, मैं जैसा कि आप उम्मीद करेंगे संदेश संदेश सूची को न देखें। हालांकि, यह दिखाता है कि अगर मैं ManyToManyField घोषणा में 'through' पैरामीटर को हटा देता हूं। उसके साथ क्या है? मैंने admin.py में व्यवस्थापक साइट पर सभी तीन मॉडल (प्लस टैग) पंजीकृत किए हैं।

TIA

उत्तर

18

प्रलेखन कहते हैं:

जब आप एक ManyToManyField के माध्यम से तर्क का उपयोग एक मध्यस्थ के मॉडल निर्दिष्ट, व्यवस्थापक एक विजेट प्रदर्शित नहीं करेगा डिफ़ॉल्ट रूप से।

लेकिन शायद through विशेषता परिभाषित होने पर भी व्यवस्थापक परिवर्तन दृश्य में एम 2 एम फ़ील्ड प्रदर्शित करना संभव है।

class ForumAdminForm(forms.ModelForm): 
    mm = forms.ModelMultipleChoiceField(
     queryset=models.Message.objects.all(), 
     widget=FilteredSelectMultiple(_('ss'), False, attrs={'rows':'10'})) 

    def __init__(self, *args, **kwargs): 
     if 'instance' in kwargs: 
      initial = kwargs.setdefault('initial', {}) 
      initial['mm'] = [t.service.pk for t in kwargs['instance'].message_forum_set.all()] 

     forms.ModelForm.__init__(self, *args, **kwargs) 

    def save(self, commit=True): 
     instance = forms.ModelForm.save(self, commit) 

     old_save_m2m = self.save_m2m 
     def save_m2m(): 
      old_save_m2m() 

      messages = [s for s in self.cleaned_data['ss']] 
      for mf in instance.message_forum_set.all(): 
       if mf.service not in messages: 
        mf.delete() 
       else: 
        messages.remove(mf.service) 

      for message in messages: 
       Message_forum.objects.create(message=message, forum=instance) 

     self.save_m2m = save_m2m 

     return instance 

    class Meta: 
     model = models.Forum 

class ForumAdmin(admin.ModelAdmin): 
    form = ForumAdminForm 
+0

यह पूरी तरह से काम करता है, लेकिन कोड 'सेवा' में अमान्य संदर्भ हैं। – alex

10

the official documentation पर एक नज़र डालें:

+0

यह समाधान काफी सरल है, और मेरे लिए काम किया! –

+0

आपका लिंक टूटा हुआ है क्योंकि 1.6 के लिए प्रलेखन अब उनकी साइट पर उपलब्ध नहीं है। –

2

मैं @ Fedor के जवाब से बहुत कुछ सीखा है, लेकिन कुछ टिप्पणियों और सफाई अभी भी फायदेमंद हो सकता है।

class ForumAdminForm(forms.ModelForm): 
    messages = forms.ModelMultipleChoiceField(
        queryset=Message.objects.all(), 
        widget=FilteredSelectMultiple('Message', False)) 


    # Technically, you don't need to manually set initial here for ForumAdminForm 
    # However, you NEED to do the following for MessageAdminForm 
    def __init__(self, *args, **kwargs): 
     if 'instance' in kwargs: 
      # a record is being changed. building initial 
      initial = kwargs.setdefault('initial', {}) 
      initial['messages'] = [t.message.pk for t in kwargs['instance'].message_forum_set.all()] 
     super(ForumAdminForm, self).__init__(*args, **kwargs) 

    def save(self, commit=True): 
     if not self.is_valid(): 
      raise HttpResponseForbidden 
     instance = super(ForumAdminForm, self).save(self, commit) 
     def save_m2m_with_through(): 
      messages = [t for t in self.cleaned_data['messages'] 
      old_memberships = instance.message_forum_set.all() 
      for old in old_memberships: 
       if old.message not in messages: 
        # and old membership is cleaned by the user 
        old.delete() 
      for message in [x for x in messages not in map(lambda x: x.message, old_memberships)]:     
       membership = Member_forum(message=messsage, forum=instance) 
       # You may have to initialize status, position and tag for your need 
       membership.save() 
     if commit: 
      save_m2m_with_through() 
     else: 
      self.save_m2m = save_m2m_with_through 
     return instance 

    class Meta: 
     model = Forum 
     fields = {'name', 'messages') 

एक चेतावनी है: अगर आप में एक और कई-से-अनेक संबंध (कि के माध्यम से बिना है), super(ForumAdminForm, self).save(self, commit) सेट हो जाएगा मामले commit में self.save_m2m झूठी है। हालांकि, इसे कॉल करने से त्रुटि हो जाएगी, क्योंकि यह फ़ंक्शन भी कई से कई लोगों को बचाने की कोशिश करता है। आपको अन्य सभी से कई रिश्तों को मैन्युअल रूप से सहेजने की आवश्यकता हो सकती है, या अपवाद को पकड़ सकते हैं, या अन्यथा।

संबंधित मुद्दे