Как я могу показать Django Admin Список изменений Вид дочерних элементов внешнего ключа? - PullRequest
4 голосов
/ 14 апреля 2011

Я работаю над приложением с моделью иерархии Campaign> Category> Account. В идеале я хотел бы, чтобы пользователи могли щелкать ссылку в представлении списка администраторов кампании и переходить по URL-адресу, например «/ admin / myapp / campaign / 2 / accounts /», где будет отображаться представление администратора django со всеми удобные функции ChangeList, но которые фильтруются для отображения только учетных записей в категориях в указанной кампании (т. е. Account.object.filter (category_ campaign _id = 2)). (Обратите внимание, сами категории, я рад быть просто «фильтрами» в этом представлении списка учетных записей).

Кажется, я не могу найти какой-либо ссылки на способ, имитирующий этот подход "элемент-щелчок-идет-список-из-за-ключа-детей", который распространен во многих других средах.

Возможно ли это? Есть ли "лучший" подход в парадигме Джанго?

спасибо за любую помощь!

Ответы [ 4 ]

4 голосов
/ 14 апреля 2011

Это был интересный вопрос, поэтому я взялся за пример приложения, чтобы разобраться.

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

Примечание: list_filter на AccountAdmin требуется начиная с Django 1.2.4, Django 1.1.3 и Django 1.3 beta 1, которые предоставили защиту от произвольной фильтрации через параметр URL в админке.

1 голос
/ 04 февраля 2013

Другие решения не обращают внимания на фильтры, которые вы уже применили.Они являются частью строки запроса, и я также хотел сохранить их.

Сначала вам нужно получить ссылку на запрос, вы можете сделать это, обернув 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

И что-то подобное даст вам фильтр внутри строк списка изменений.Действительно полезно.: -)

1 голос
/ 14 апреля 2011

Если я вас правильно понимаю, вы хотите добавить настраиваемое поле (, которое можно вызвать в list_display вашего ModelAdmin ) в ваше представление CampaignAdmin change_list.

Ваше настраиваемое поле будет ссылкой, которая берет category.id каждой категории в вашем change_list и генерирует ссылку на желаемое, отфильтрованное представление администратора , которое похоже на учетную запись-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/

0 голосов
/ 16 апреля 2011

Это хорошие решения.Я не знал об автофильтре по 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

И, кроме того, вам нужно будет включить URL-ссылку в представление списка CampaignAdmin ...

...