是否可以将filter_horizontal
用于具有中间表的ManyToManyField
字段,例如没有中间表的字段?
e.g:
class A(models.Model):
f1 = models.ManyToManyField(B)
f2 = models.ManyToManyField(C, through='T')
class B(models.Model):
pass
class C(models.Model):
pass
class T(models.Model):
a = models.ForeignKey(A)
c = models.ForeignKey(C)
class AAdmin(admin.ModelAdmin):
filter_horizontal = ('f1', 'f2', )
答案 0 :(得分:1)
如果您有多个具有中间表的字段,则无法显示常规,过滤器水平或过滤器垂直窗口小部件。原因是中间表可能具有无法在这些小部件中显示的额外字段。
可以将相关模型显示为内联。有关详细信息,请参阅working with many-to-many intermediary models上的文档。
答案 1 :(得分:0)
窗口小部件的名称为 FilteredSelectMultiple ,您必须在管理视图中覆盖 formfield_for_manytomany 方法。这是我用过的。 我有一个公司模型,其中有许多课程,而会员是中间模型。
class Company(models.Model):
courses = models.ManyToManyField('courses.Course', through='Member', related_name='companies')
class Member(models.Model):
user = models.OneToOneField(get_user_model(),
related_name="%(app_label)s_%(class)s",
on_delete=models.CASCADE,
)
organization = TenantForeignKey(
Company, related_name="organization_users", on_delete=models.CASCADE)
这是我的管理员视图
class CompanyAdmin(admin.ModelAdmin):
def formfield_for_manytomany(self, db_field, request, **kwargs):
db = kwargs.get('using')
if db_field.name == 'courses':
kwargs['widget'] = FilteredSelectMultiple(
db_field.verbose_name, is_stacked=False
)
else:
return super().formfield_for_manytomany(db_field, request, **kwargs)
if 'queryset' not in kwargs:
queryset = Course.objects.filter(is_active=True)
if queryset is not None:
kwargs['queryset'] = queryset
form_field = db_field.formfield(**kwargs)
msg = 'Hold down “Control”, or “Command” on a Mac, to select more than one.'
help_text = form_field.help_text
form_field.help_text = (
format_lazy('{} {}', help_text, msg) if help_text else msg
)
return form_field