如何显示Django管理员更改列表外国儿童的视图?

时间:2011-04-14 11:13:36

标签: django django-admin changelist

我正在使用广告系列的模型层次结构>分类>帐户。理想情况下,我希望用户能够点击广告系列管理列表视图中的链接,然后转到“/ admin / myapp / campaign / 2 / accounts /”这样的网址,这将显示所有的django管理员视图方便的ChangeList设施,但过滤后只显示指定广告系列中的类别中的帐户(即Account.object.filter(category_ campaign _id = 2))。 (注意,类别本身我很高兴在此帐户列表视图中“过滤”)。

我似乎无法找到任何模仿这个项目的方法 - click-go-to-to-for-foriegn-key-children方法,这在许多其他框架中很常见。

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

感谢您的帮助!

4 个答案:

答案 0 :(得分:4)

这是一个有趣的问题,所以我掀起了一个示例应用来解决它。

# 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)

您需要使用帐户模型管理员所在的应用名称替换。

注意:自Django 1.2.4,Django 1.1.3和Django 1.3 beta 1以来,AccountAdmin上的list_filter是必需的,它通过admin中的URL参数引入了对任意过滤的保护。

答案 1 :(得分:1)

如果我理解正确,您希望在CampaignAdmin change_list视图中添加自定义字段(a callable in your ModelAdmin's list_display)。

您的自定义字段将是一个链接,其中包含change_list中每个类别的category.id,并生成指向所需的已过滤admin view的链接,这似乎是您案例中的account-change_list:< / p>

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

然后将其添加到admin的list_display选项中:

list_display = ('account_link', ...) 

但这取决于您的数据模型。

如果您想创建一个适合您需求的永久性,已过滤的change_list视图,您可以查看以下文章:http://lincolnloop.com/blog/2011/jan/11/custom-filters-django-admin/

答案 2 :(得分:1)

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

首先,你需要获得对请求的引用,你可以像我一样包装changelist_viewqueryset来做到这一点:

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

类似的东西会在更改列表行中提供一个过滤器。真有帮助。 : - )

答案 3 :(得分:0)

这些都是很好的解决方案。我不知道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的列表视图中......