如何显示外键子项的Django Admin更改列表视图?

| 我正在使用“广告系列”>“类别”>“帐户”的模型层次结构的应用程序。理想情况下,我希望用户能够单击广告系列管理员列表视图中的链接,并转到\“ / admin / myapp / campaign / 2 / accounts / \”这样的网址,它将显示django管理员视图具有所有方便的ChangeList便利设施,但经过过滤后仅显示指定广告系列中类别中的帐户(即Account.object.filter(category_campaign_id = 2))。 (请注意,类别本身很高兴能够在此帐户列表视图中成为“过滤器”)。 我似乎找不到任何模仿这种在许多其他框架中很常见的模仿“项-键-外键-子项列表”方法的方法的参考。 可能吗? Django范例中是否有“更好”的方法? 谢谢你的帮助!     
已邀请:
这是一个有趣的问题,所以我整理了一个示例应用程序来弄清楚。
# models.py
from django.db import models

class Campaign(models.Model):
    name = models.CharField(max_length=20)

    def __unicode__(self):
        return unicode(self.name)

class Category(models.Model):
    campaign = models.ForeignKey(Campaign)
    name = models.CharField(max_length=20)

    def __unicode__(self):
        return unicode(self.name)

class Account(models.Model):
    category = models.ForeignKey(Category)
    name = models.CharField(max_length=20)

    def __unicode__(self):
        return unicode(self.name)

# admin.py
from django.contrib import admin
from models import Campaign, Category, Account

class CampaignAdmin(admin.ModelAdmin):
    list_display = (\'name\', \'related_accounts\', )

    def related_accounts(self, obj):
        from django.core import urlresolvers
        url = urlresolvers.reverse(\"admin:<yourapp>_account_changelist\")
        lookup = u\"category__campaign__exact\"
        text = u\"View Accounts\"
        return u\"<a href=\'%s?%s=%d\'>%s</a>\" % (url, lookup, obj.pk, text)
    related_accounts.allow_tags = True
admin.site.register(Campaign, CampaignAdmin)
admin.site.register(Category)

class AccountAdmin(admin.ModelAdmin):
    list_display = (\'category\', \'name\')
    list_filter = (\'category__campaign\',)
admin.site.register(Account, AccountAdmin)
您需要用Account ModelAdmin所在的应用名称替换。 注意:自Django 1.2.4,Django 1.1.3和Django 1.3 beta 1起,AccountAdmin上的list_filter是必需的,后者引入了防止通过admin中的URL参数进行任意过滤的保护。     
如果我对您的理解正确,那么您想在CampaignAdmin change_list视图中添加一个自定义字段(在ModelAdmin的list_display中可调用)。 您的自定义字段将是一个链接,该链接采用change_list中每个类别的category.id并生成指向所需的经过过滤的管理视图的链接,在您的情况下,该视图似乎是account-change_list:
admin/yourproject/account/?category__id__exact=<category.id>
假设类别是Campaign-Model上的一个字段,则可以将以下方法添加到CampaignAdmin中:
def account_link(self, obj):
    return \'<a href=\"/admin/yourproject/account/?category__id__exact=%s\">Accounts</a>\' % (obj.category.id)

account_link.allow_tags = True
然后将其添加到管理员的list_display选项中:
list_display = (\'account_link\', ...) 
不过,这取决于您的数据模型。 如果要创建适合您需要的经过过滤的永久性change_list视图,可以查看以下文章:http://lincolnloop.com/blog/2011/jan/11/custom-filters-django-admin/     
其他解决方案不关注您已经应用的过滤器。它们是查询字符串的一部分,我也想保留它们。 首先,您需要获得对该请求的引用,可以像我一样通过包装
changelist_view
queryset
来做到这一点:
class AccountAdmin(ModelAdmin):
    model = Account
    list_display = (\'pk\', \'campaign_changelist\')

    # ...

    def queryset(self, request):
        self._get_params = request.GET
        return super(AccountAdmin, self).queryset(request)

    def campaign_changelist(self, obj):
        url = reverse(\'admin:yourapp_account_changelist\')
        querystring = self._get_params.copy()
        querystring[\'campaign__id__exact\'] = obj.campaign.pk
        return u\'<a href=\"{0}?{1}\">{2}</a>\'.format(
            url, querystring.urlencode(), obj.campaign)
    campaign_changelist.allow_tags = True
那样的话,您可以在变更列表行中使用过滤器。真的很有帮助。 :-)     
这些是好的解决方案。我不知道通过url范式进行自动筛选。这是我发现的另一个方法,它允许您使用自定义网址方案:
from consensio.models import Account
from django.contrib import admin        
from django.conf.urls.defaults import patterns, include, url

class AccountAdmin(admin.ModelAdmin):
    campaign_id = 0;

    def campaign_account_list(self, request, campaign_id, extra_context=None):
        \'\'\'
        First create your changelist_view wrapper which grabs the extra
        pattern matches
        \'\'\'
        self.campaign_id = int(campaign_id)
        return self.changelist_view(request, extra_context)

    def get_urls(self):
        \'\'\'
        Add your url patterns to get the foreign key
        \'\'\'
        urls = super(AccountAdmin, self).get_urls()
        my_urls = patterns(\'\',
            (r\'^bycampaign/(?P<campaign_id>\\d+)/$\', self.admin_site.admin_view(self.campaign_account_list))
        )
        return my_urls + urls

    def queryset(self, request):
        \'\'\'
        Filter the query set based on the additional param if set
        \'\'\'
        qs = super(AccountAdmin, self).queryset(request)
        if (self.campaign_id > 0):
            qs = qs.filter(category__campaign__id = self.campaign_id)
        return qs
另外,您还需要将URL链接合并到CampaignAdmin的列表视图中...     

要回复问题请先登录注册