2010-06-27 35 views
7

Tôi đang cố gắng tìm ra cách để hiển thị RelativeInline sau đây chỉ khi Person.is_member là True.Điều kiện nội tuyến trong quản trị Django?

admin.py hiện tại:

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) 

Các gợi ý duy nhất mà tôi đã có thể tìm thấy là tôi có thể có thể ghi đè lên get_formset, nhưng tôi không thể tìm thấy một ví dụ điển hình, vì vậy nỗ lực yếu ớt của tôi không hoạt động.

Dưới đây là thất bại của tôi:

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) 

Không có lỗi được tạo ra bởi mã này, nhưng không có nội tuyến xuất hiện bất kể có hay không Person.is_member là True hoặc False.


Cập nhật: Một người bạn đề nghị tôi thử thay đổi:

inlines = [RelativeInline,] 

tới:

self.inlines = [RelativeInline,] 

nhưng vô ích. Tôi cũng đã thử:

PersonAdmin.inlines = [RelativeInline,] 

nhưng kết quả là như nhau - không có lỗi, không có nội tuyến.

Trả lời

1

Tôi quyết định thay đổi toàn bộ mô hình và giải quyết vấn đề của mình theo một cách khác. Thay vì có một quản trị duy nhất cho tất cả những người với một inline có điều kiện, tôi quyết định:

  1. Override các queryset để lọc cho các thành viên chỉ và giữ RelativeInline với quản trị cho mô hình
  2. này Tạo một mô hình proxy và ghi đè truy vấn của nó để lọc cho những người không phải là thành viên. Quản trị viên cho mô hình này không bao gồm RelativeInline.

Cuối cùng, tôi nghĩ đây là một cách tiếp cận rõ ràng hơn. Bây giờ các thành viên có thể được duy trì, và người thân (không phải thành viên) có thể được thêm vào nội tuyến. NonMemberAdmin cho phép chỉnh sửa không phải thành viên.

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

giải pháp ban đầu của bạn là khá chặt chẽ. Nếu bạn nhìn vào django/contrib/admin/options.py xung quanh dòng 290 bạn sẽ thấy rằng các lớp nội tuyến được khởi tạo khi mô hình quản trị được khởi tạo, sau đó danh sách inlines bị bỏ qua. Vì vậy, thiết lập danh sách này sau trong get_formsets() không có hiệu lực.

Tuy nhiên, bạn chính xác rằng get_formsets() là điều cần ghi đè để làm cho nội tuyến của bạn có điều kiện. Các phiên bản nội tuyến được chứa trong self.inline_instances, do đó, để vô hiệu hóa chúng dựa trên đối tượng (ví dụ:nói rằng tôi muốn để ẩn một inline cụ thể về "add" theo mẫu) bạn muốn ghi đè lên nó thích:

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

cập nhật cho năm 2014 và django 1.6: 'cho nội tuyến trong self.get_inline_instances (yêu cầu, obj):' – imposeren

0

Tôi nhận ra câu hỏi này là một chút cũ và codebase đã thay đổi một chút; có một điểm sạch hơn để ghi đè mọi thứ lúc này: get_inline_instances. Bạn có thể làm điều này:

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 
Các vấn đề liên quan