2010-06-27 2 views
7

Я пытаюсь выяснить способ отображения следующей RelativeInline, только если Person.is_member имеет значение True.Условный встроенный администратор Django?

Текущий admin.py:

class RelativeInline(admin.TabularInline): 
    model = Relative 
    fk_name = 'member' 

class PersonAdmin(admin.ModelAdmin): 
    inlines = [RelativeInline,] 
    ordering = ('first_name',) 
    list_filter = ('is_member',) 
    search_fields = ('first_name', 'last_name',) 
    date_hierarchy = 'member_date' 
    list_display = ('first_name', 'last_name', 'is_member', 'member_date', 'photo') 

admin.site.register(Person, PersonAdmin) 

Единственный намек я был в состоянии найти то, что я мог бы переопределить get_formset, но я не мог найти хороший пример, так что моя слабая попытка не работает.

Вот моя неудачная попытка:

class RelativeInline(admin.TabularInline): 
    model = Relative 
    fk_name = 'member' 

class PersonAdmin(admin.ModelAdmin): 
    ordering = ('first_name',) 
    list_filter = ('is_member',) 
    search_fields = ('first_name', 'last_name',) 
    date_hierarchy = 'member_date' 
    list_display = ('first_name', 'last_name', 'is_member', 'member_date', 'photo') 

    def get_formset(self, request, obj=None, **kwargs): 
     if obj.is_member: 
      inlines = [RelativeInline,] 
     return super(PersonAdmin, self).get_formset(request, obj, **kwargs) 

admin.site.register(Person, PersonAdmin) 

Там нет ошибок, порожденных этим кодом, но ни рядный не появляется, независимо от того, или нет Person.is_member является истинным или ложным.


Update: Друг предложил мне попробовать изменения:

inlines = [RelativeInline,] 

к:

self.inlines = [RelativeInline,] 

, но безрезультатно. Я также пробовал:

PersonAdmin.inlines = [RelativeInline,] 

но результат был тот же - без ошибок, нет встроенного.

ответ

1

Я решил изменить всю парадигму и решить свою проблему по-другому. Вместо того, чтобы один админы для всех лиц с условным рядным, я решил:

  1. Override QuerySet для фильтрации только для членов и держать RelativeInline с администратором для этой модели
  2. Создания модели прокси и переопределить его запрос для фильтрации для нечленов. Администратор для этой модели не включает RelativeInline.

В конце концов, я думаю, что это более чистый подход. Теперь члены могут поддерживаться, а родственники (нечлены) могут быть добавлены в строку. NonMemberAdmin позволяет редактировать нечленов.

models.py:

class Person(models.Model): 
    first_name = models.CharField(max_length=50) 
    last_name = models.CharField(max_length=50) 
    is_member = models.BooleanField() 
    is_active = models.BooleanField(default=True) 

    class Meta: 
     verbose_name_plural = 'Members' 
     ordering = ('first_name', 'last_name') 

class PersonProxy(Person): 
    class Meta: 
     proxy = True 
     verbose_name_plural = 'Non-Members' 

class Relationship(models.Model): 
    name = models.CharField(max_length=50) 

class Relative(models.Model): 
    member = models.ForeignKey(Person, related_name='relative_member') 
    relative = models.ForeignKey(Person, related_name='relative_relative') 
    relationship = models.ForeignKey(Relationship) 

admin.py:

class RelativeInline(admin.TabularInline): 
    model = Relative 
    fk_name = 'member' 


class MemberAdmin(admin.ModelAdmin): 
    inlines = [RelativeInline,] 
    ordering = ('first_name',) 
    # list_filter = ('is_member',) 
    search_fields = ('first_name', 'last_name',) 
    # date_hierarchy = 'member_date' 
    list_display = ('first_name', 'last_name', 'member_date') 

    def queryset(self, request): 
     return (super(MemberAdmin, self).queryset(request) 
       .filter(is_member=True, is_active=True)) 


class NonMemberAdmin(admin.ModelAdmin): 
    ordering = ('first_name',) 
    search_fields = ('first_name', 'last_name',) 
    list_display = ('first_name', 'last_name') 

    def queryset(self, request): 
     return (super(NonMemberAdmin, self).queryset(request) 
       .filter(is_member=False, is_active=True)) 


admin.site.register(Person, MemberAdmin) 
admin.site.register(PersonProxy, NonMemberAdmin) 
3

Ваше оригинальное решение было довольно близко. Если вы посмотрите в django/contrib/admin/options.py вокруг строки 290, вы увидите, что встроенные классы создаются при создании экземпляра модели, после чего список inlines игнорируется. Поэтому установка этого списка позже в get_formsets() не влияет.

Однако вы правы, что get_formsets() - это то, что нужно переопределить, чтобы сделать ваши строки строгими. Внутренние экземпляры содержатся в self.inline_instances, поэтому их можно отключить на основе объекта (например,сказать, что я хочу, чтобы скрыть определенный инлайн на «добавить» форму) вы бы переопределить это нравится:

class MyAdmin(models.ModelAdmin): 

    inlines = [MyInline, SomeOtherInline] 

    def get_formsets(self, request, obj=None): 
     for inline in self.inline_instances: 
      if isinstance(inline, MyInline) and obj is None: 
       continue 
      yield inline.get_formset(request, obj) 
+1

обновление для 2014 и Джанго 1.6: 'для встроенного в self.get_inline_instances (запрос, объект):' – imposeren

0

Я понимаю, что этот вопрос немного старый и кодовые немного изменился; есть более чистая точка, чтобы переопределить ситуацию сейчас: get_inline_instances. Вы можете сделать это:

class PersonAdmin(models.ModelAdmin): 

inlines = [RelativeInline,] 

def get_inline_instances(self, request, obj=None): 
    to_return = super(MyAdmin, self).get_inline_instances(request, obj) 
    #filter out the RelativeInlines if obj.is_member is false 
    if not obj or not obj.is_member: 
     to_return = [x for x in to_return if not isinstance(x,RelativeInline)] 
    return to_return 
Смежные вопросы