我可以在django admin中创建list_filter,只显示引用的ForeignKeys吗?

m00*_*000 56 django django-admin

我有一个django应用程序,它有两个这样的模型:

class MyModel(models.Model):
    name = models.CharField()
    country = models.ForeignKey('Country')

class Country(models.Model):
    code2 = models.CharField(max_length=2, primary_key=True)
    name = models.CharField()
Run Code Online (Sandbox Code Playgroud)

管理类MyModel看起来像这样:

class MyModelAdmin(admin.ModelAdmin):
    list_display = ('name', 'country',)
    list_filter = ('country',)
admin.site.register(models.MyModel, MyModelAdmin)
Run Code Online (Sandbox Code Playgroud)

Country表包含约250个国家.某些MyModel实例实际上只引用了少数几个国家.

问题是django admin 的列表过滤器列出了过滤器面板中的所有国家/地区.列出所有国家(而不仅仅是那些被实例引用的国家)在这种情况下几乎无法实现列表过滤器的目的.

是否有一些只显示MyModel列表过滤器中作为选项引用的国家/地区?(我使用Django 1.3.)

Ala*_*air 78

从Django 1.8开始,有一个内置的RelatedOnlyFieldListFilter,可用于显示相关国家/地区.

class MyModelAdmin(admin.ModelAdmin):
    list_display = ('name', 'country',)
    list_filter = (
        ('country', admin.RelatedOnlyFieldListFilter),
    )
Run Code Online (Sandbox Code Playgroud)

对于Django 1.4-1.7,list_filter允许您使用的子类SimpleListFilter.应该可以创建一个列出所需值的简单列表过滤器.

如果你不能从Django 1.3升级,你需要使用内部的,没有文档的FilterSpecapi.Django Admin中的Stack Overflow问题自定义过滤器应该指向正确的方向.


dar*_*low 32

我知道问题是关于Django 1.3但是你很快就提到升级到1.4.对于那些正在寻找1.4解决方案的人,但是发现这个条目的人,我决定展示使用SimpleListFilter(可用的Django 1.4)来仅显示引用的(相关的,使用过的)外键值的完整示例

from django.contrib.admin import SimpleListFilter

# admin.py
class CountryFilter(SimpleListFilter):
    title = 'country' # or use _('country') for translated title
    parameter_name = 'country'

    def lookups(self, request, model_admin):
        countries = set([c.country for c in model_admin.model.objects.all()])
        return [(c.id, c.name) for c in countries]
        # You can also use hardcoded model name like "Country" instead of 
        # "model_admin.model" if this is not direct foreign key filter

    def queryset(self, request, queryset):
        if self.value():
            return queryset.filter(country__id__exact=self.value())
        else:
            return queryset

# Example setup and usage

# models.py
from django.db import models

class Country(models.Model):
    name = models.CharField(max_length=64)

class City(models.Model):
    name = models.CharField(max_length=64)
    country = models.ForeignKey(Country)

# admin.py
from django.contrib.admin import ModelAdmin

class CityAdmin(ModelAdmin):
    list_filter = (CountryFilter,)

admin.site.register(City, CityAdmin)
Run Code Online (Sandbox Code Playgroud)

在示例中,您可以看到两个模型 - 城市和国家.城市有外国关键.如果您使用常规list_filter =('country'),您将拥有选择器中的所有国家/地区.但是,此代码段仅过滤相关国家/地区 - 与城市至少有一种关系的国家/地区.

这里开始的想法.非常感谢作者.改进了类名,以便更清晰地使用model_admin.model而不是硬编码的模型名称.

Django Snippets中也提供了示例:http: //djangosnippets.org/snippets/2885/


and*_*abs 22

从Django 1.8开始,有: admin.RelatedOnlyFieldListFilter

示例用法是:

class BookAdmin(admin.ModelAdmin):
    list_filter = (
        ('author', admin.RelatedOnlyFieldListFilter),
    )
Run Code Online (Sandbox Code Playgroud)


小智 5

我会在darklow的代码中更改查找,如下所示:

def lookups(self, request, model_admin):
    users = User.objects.filter(id__in = model_admin.model.objects.all().values_list('user_id', flat = True).distinct())
    return [(user.id, unicode(user)) for user in users]
Run Code Online (Sandbox Code Playgroud)

这对数据库来说要好得多;)