2012-07-25 10 views
18

मेरे पास एक Django मॉडल फ़ील्ड है जिसे मैं इनलाइन करना चाहता हूं। क्षेत्र कई से अधिक रिश्तों है। तो "परियोजनाएं" और "उपयोगकर्ता प्रोफाइल" हैं। प्रत्येक उपयोगकर्ता प्रोफ़ाइल किसी भी परियोजना का चयन कर सकते हैं।Django व्यवस्थापक इंटरफ़ेस: इनलाइन के साथ क्षैतिज_फिल्टर का उपयोग करना कईToMany फ़ील्ड

वर्तमान में, मुझे "टैब्यूलर" इनलाइन दृश्य काम मिल गया है। क्या "क्षैतिज फ़िल्टर" रखने का कोई तरीका है ताकि मैं आसानी से उपयोगकर्ता प्रोफ़ाइल से परियोजनाओं को जोड़ और निकाल सकूं?

कृपया उदाहरण के लिए संलग्न तस्वीर देखें।

class UserProfile(models.Model): 
    user = models.OneToOneField(User, unique=True) 
    projects = models.ManyToManyField(Project, blank=True, help_text="Select the projects that this user is currently working on.") 

और एक परियोजना के लिए मॉडल कोड:

class Project(models.Model): 
    name = models.CharField(max_length=100, unique=True) 
    application_identifier = models.CharField(max_length=100) 
    type = models.IntegerField(choices=ProjectType) 
    account = models.ForeignKey(Account) 
    principle_investigator = models.ForeignKey(User) 
    active = models.BooleanField() 

और दृश्य के लिए व्यवस्थापक कोड:

class UserProfileInline(admin.TabularInline): 
    model = UserProfile.projects.through 
    extra = 0 
    verbose_name = 'user' 
    verbose_name_plural = 'users' 

class ProjectAdmin(admin.ModelAdmin): 
    list_display = ('name', 'application_identifier', 'type', 'account', 'active') 
    search_fields = ('name', 'application_identifier', 'account__name') 
    list_filter = ('type', 'active') 
    inlines = [UserProfileInline,] 
admin.site.register(Project, ProjectAdmin) 

उत्तर

35
enter image description here

यहाँ उपयोगकर्ता प्रोफ़ाइल के लिए मॉडल कोड है

समस्या इनलाइन होने से नहीं है; यह सामान्य रूप से ModelForm के काम से है। वे केवल मॉडल पर वास्तविक फ़ील्ड के लिए फॉर्म फ़ील्ड बनाते हैं, संबंधित प्रबंधक विशेषताओं से नहीं। हालांकि, आप इस कार्यक्षमता को फॉर्म में जोड़ सकते हैं:

from django.contrib.admin.widgets import FilteredSelectMultiple 

class ProjectAdminForm(forms.ModelForm): 
    class Meta: 
     model = Project 

    userprofiles = forms.ModelMultipleChoiceField(
     queryset=UserProfile.objects.all(), 
     required=False, 
     widget=FilteredSelectMultiple(
      verbose_name='User Profiles', 
      is_stacked=False 
     ) 
    ) 

    def __init__(self, *args, **kwargs): 
     super(ProjectAdminForm, self).__init__(*args, **kwargs) 
      if self.instance.pk: 
       self.fields['userprofiles'].initial = self.instance.userprofile_set.all() 

    def save(self, commit=True): 
     project = super(ProjectAdminForm, self).save(commit=False) 
     if commit: 
      project.save() 

     if project.pk: 
      project.userprofile_set = self.cleaned_data['userprofiles'] 
      self.save_m2m() 

     return project 

class ProjectAdmin(admin.ModelAdmin): 
    form = ProjectAdminForm 
    ... 

शायद थोड़ी पैदल यात्रा संभवतः क्रम में है। सबसे पहले, हम userprofiles फॉर्म फ़ील्ड को परिभाषित करते हैं। यह ModelMultipleChoiceField का उपयोग करेगा, जो डिफ़ॉल्ट रूप से एक से अधिक चयन बॉक्स में परिणाम देगा। चूंकि यह मॉडल पर वास्तविक क्षेत्र नहीं है, इसलिए हम इसे filter_horizontal पर नहीं जोड़ सकते हैं, इसलिए हम इसे केवल उसी विजेट, FilteredSelectMultiple का उपयोग करने के लिए कहें, यह उपयोग करेगा यदि यह filter_horizontal में सूचीबद्ध था।

हमने शुरुआत में पूरे UserProfile सेट के रूप में क्वेरीसेट सेट किया है, आप इसे यहां फ़िल्टर नहीं कर सकते हैं, फिर भी, क्योंकि कक्षा परिभाषा के इस चरण में, फॉर्म को तत्काल नहीं किया गया है और इस प्रकार यह instance सेट नहीं है अभी तक। नतीजतन, हम __init__ ओवरराइड करते हैं ताकि हम फ़िल्टर किए गए क्वेरीसेट को फ़ील्ड के प्रारंभिक मान के रूप में सेट कर सकें।

अंत में, हम save विधि को ओवरराइड करते हैं, ताकि हम संबंधित प्रबंधक की सामग्री को उसी के रूप में सेट कर सकें जो फ़ॉर्म के POST डेटा में था, और आप कर चुके हैं।

+0

धन्यवाद क्रिस! यह पहली बार मैंने कोशिश की एक आकर्षण की तरह काम किया! –

+0

धन्यवाद, आप आदमी हैं। – whooot

+0

ग्रेट समाधान, मेरे लिए बहुत अच्छा काम किया। – Blackeagle52

1

अपने साथ कई रिश्तों से निपटने के दौरान एक मामूली वृद्धि। कोई भी विकल्प से खुद को बाहर करना चाह सकता है:

if self.instance.pk: 
     self.fields['field_being_added'].queryset = self.fields['field_being_added'].queryset.exclude(pk=self.instance.pk) 
     self.fields['field_being_added'].initial = """Corresponding result queryset"""