如何在Django管理后台中过滤filter_horizontal?
我想找到一种方法,可以在过滤后的查询结果基础上使用filter_horizontal。
我尝试过用自定义管理器来实现:
在models.py文件中:
class AvailEquipManager(models.Manager):
def get_query_set(self):
return super(AvailEquipManager, self).get_query_set().filter(id=3)
class Equipment(models.Model):
description = models.CharField(max_length=50)
manufacturer = models.ForeignKey(Manufacturer)
[...]
objects = models.Manager()
avail = AvailEquipManager()
def __unicode__(self):
return u"%s" % (self.description)
在admin.py文件中:
class SystemAdmin(admin.ModelAdmin):
filter_horizontal = ('equipment',) # this works but obviously shows all entries
#filter_horizontal = ('avail',) # this does not work
所以我的问题是,如何让filter_horizontal的左侧只显示特定的项目呢?
3 个回答
1
在ModelAdmin中,formfield_for_foreignkey
这个方法可以处理这个问题:
下面是一个使用System
和指向Equipment
的外键的例子:
def formfield_for_foreignkey(self, db_field, request, **kwargs): if db_field.name == 'equipment': system = System.objects.get(id=request.resolver_match.args[0]) kwargs["queryset"] = system.equipment_set.all() return super().formfield_for_foreignkey(db_field, request, **kwargs)
5
这是个老问题,不过还是来聊聊吧:
根据你的具体需求,可能在equipment
这个关系字段上设置limit_choices_to
属性会更简单。这种方法适用于ForeignKey
字段和ManyToManyField
字段。
根据Django文档,这个属性的作用是:
在使用
ModelForm
或后台管理界面渲染这个字段时,限制可选项的数量。
举个简单的例子,假设你有一个System
模型,其中有一个equipment
的多对多字段:
class Equipment(models.Model):
available = models.BooleanField(default=True)
class System(models.Model):
equipment = models.ManyToManyField(to=Equipment,
limit_choices_to={'available': True})
class SystemAdmin(admin.ModelAdmin):
filter_horizontal = ['equipment']
这个例子使用了一个available
标志,但也可以使用更复杂的查询。
30
我找到了解决办法,是通过调整一个不同问题的答案,这个答案我在Google Groups上看到的。
这个方法适用于一个自定义的ModelForm,具体步骤如下:
首先,创建一个新的forms.py文件:
from django import forms
from models import Equipment
class EquipmentModelForm(forms.ModelForm):
class Meta:
model = Equipment
def __init__(self, *args, **kwargs):
forms.ModelForm.__init__(self, *args, **kwargs)
self.fields['equipment'].queryset = Equipment.avail.all()
然后在admin.py文件中:
class SystemAdmin(admin.ModelAdmin):
form = EquipmentModelForm
filter_horizontal = ('equipment',)
希望这个方法能对其他人有所帮助。