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

如何显示外键子项的Django管理员更改列表视图?,django,django-admin,changelist,Django,Django Admin,Changelist,我正在开发一个应用程序,它的继承人是Campaign>Category>Account。理想情况下,我希望用户能够单击“活动管理列表”视图中的链接,并转到类似“/admin/myapp/campaign/2/accounts/”的url,该url将显示一个django管理视图,其中包含所有方便的变更列表便利设施,但经过筛选后仅显示指定活动类别中的帐户(即Account.object.filter)(category_campaign_id=2))(注意,分类本身我很乐意在这个帐户列表视图中充当“

我正在开发一个应用程序,它的继承人是Campaign>Category>Account。理想情况下,我希望用户能够单击“活动管理列表”视图中的链接,并转到类似“/admin/myapp/campaign/2/accounts/”的url,该url将显示一个django管理视图,其中包含所有方便的变更列表便利设施,但经过筛选后仅显示指定活动类别中的帐户(即Account.object.filter)(category_campaign_id=2))(注意,分类本身我很乐意在这个帐户列表视图中充当“过滤器”)

我似乎找不到任何参考来模仿这个项目,点击进入国外关键子项列表的方法,这在许多其他框架中很常见

有可能吗?在django范式中有“更好”的方法吗


感谢您的帮助!

如果我理解正确,您希望将自定义字段()添加到您的活动管理员更改列表视图中

您的自定义字段将是一个链接,该链接获取更改列表中每个类别的category.id,并生成指向所需的过滤链接,在您的情况下,该链接似乎是帐户更改列表:

admin/yourproject/account/?category__id__exact=<category.id>
不过,这取决于您的数据模型


如果你想创建一个永久的、经过过滤的变更列表视图来满足你的需要,你可以看看这篇文章:

这是一个有趣的问题,所以我开发了一个示例应用程序来解决它

# 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)
#models.py
从django.db导入模型
班级活动(models.Model):
name=models.CharField(最大长度=20)
def ___; unicode(自):
返回unicode(self.name)
类别(models.Model):
活动=型号。外键(活动)
name=models.CharField(最大长度=20)
def ___; unicode(自):
返回unicode(self.name)
类别帐户(models.Model):
类别=型号。外键(类别)
name=models.CharField(最大长度=20)
def ___; unicode(自):
返回unicode(self.name)
#管理员
从django.contrib导入管理
从模型导入活动、类别、帐户
类活动管理员(admin.ModelAdmin):
列表显示=('name','related_accounts',)
def相关账户(自身、obj):
从django.core导入URL解析程序
url=urlResolver.reverse(“管理员:\帐户\变更列表”)
lookup=u“类别\活动\精确”
text=u“查看帐户”
返回u”“%(url,查找,obj.pk,文本)
相关的\u帐户。允许\u标记=真
管理员站点注册(活动,活动管理员)
管理站点注册(类别)
类AccountAdmin(admin.ModelAdmin):
列表显示=('category','name')
列表过滤器=('category\u campaign',)
管理员.站点.注册(帐户,帐户管理员)
您需要替换为帐户ModelAdmin所在的应用程序的名称


注意:AccountAdmin上的列表过滤器是必需的,因为Django 1.2.4、Django 1.1.3和Django 1.3 beta 1引入了通过管理员中的URL参数进行任意过滤的保护。

这些都是很好的解决方案。我不知道按URL自动过滤的范例。我发现了另一个允许使用自定义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
来自consensio.models导入帐户
从django.contrib导入管理
从django.conf.url.defaults导入模式,包括url
类AccountAdmin(admin.ModelAdmin):
活动标识=0;
def活动帐户列表(自我、请求、活动id、额外上下文=无):
'''
首先创建您的changelist\u视图包装器,它将获取额外的
模式匹配
'''
self.campaign\u id=int(campaign\u id)
返回self.changelist\u视图(请求、额外上下文)
def get_URL(自):
'''
添加url模式以获取外键
'''
url=super(AccountAdmin,self).get_url()
我的URL=模式(“”,
(r“^bycampaign/(?P\d+/$”,self.admin\u site.admin\u视图(self.campaign\u帐户列表))
)
返回我的URL+URL
def查询集(自我,请求):
'''
根据附加参数if set筛选查询集
'''
qs=super(AccountAdmin,self).queryset(请求)
如果(self.campaign_id>0):
qs=qs.filter(类别\活动\ id=self.campaign\ id)
返回qs

另外,您还需要将URL链接合并到CampaignAdmin的列表视图中…

其他解决方案不注意您已经应用的过滤器。它们是查询字符串的一部分,我也想保留它们

首先,您需要获取请求的引用,您可以像我一样包装
changelist\u视图
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
class AccountAdmin(ModelAdmin):
模型=帐户
列表\显示=('pk','campaign\变更列表')
# ...
def查询集(自我,请求):
self.\u get\u params=request.get
返回super(AccountAdmin,self).queryset(请求)
def活动_变更列表(自身、obj):
url=反向('管理员:您的应用程序\帐户\变更列表')
querystring=self.\u get\u params.copy()
querystring['campaign\uuuuu id\uuuuuu exact']=obj.campaign.pk
返回u“”。格式为(
url,querystring.urlencode(),obj.campaign)
活动\u changelist.allow\u tags=True

类似的东西会在变更列表行中为您提供一个过滤器。非常有用。:-

酷。非常感谢。我唯一要添加到等式中的是一种从管理员列表中删除“帐户”的方法,这样它的列表视图只能通过活动列表中的链接访问。有什么想法吗?
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
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