Django Admin 根据另一个字段过滤 ForeignKey 下拉列表 [英] Django Admin filtering ForeignKey dropdown based on another field

查看:23
本文介绍了Django Admin 根据另一个字段过滤 ForeignKey 下拉列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有 3 个模型:

class FileType(models.Model):
    name=models.CharField(max_length=128)

class ManagedFile(models.Model):
    type = models.ForeignKey(FileType)
    content = models.FileField(upload_to=path_maker)

class Tag(models.Model):
    type = models.ForeignKey(FileType)
    m_file = models.ForeignKey(ManagedFile)

    def clean(self):
        if self.m_file is None:
            return
        if self.type != self.m_file.type:
            raise ValidationError("File type does not match Tag type")

当为标签选择 m_file 时,m_files 类型必须与标签类型匹配.这一切都很好,但是 Tag.m_file 的管理员下拉菜单显示所有类型的文件,无论标签的类型如何.这让用户感到困惑.

When select an m_file for a tag, the m_files type MUST match the Tags type. This is all well and good, but the admin drop down for Tag.m_file shows files of all types, regardless of the Tag's type. This is Confusing to users.

在我看来,有很多方法可以静态过滤下拉列表.因此,如果我想说我们永远不会让用户在下拉列表中看到 Type.pk=1,我可以做到.但似乎没有办法过滤 m_file.Type == Self.Type

There seem to me a number of ways to filter the drop down statically. So if I wanted to say that we will never let the user see Type.pk=1 in the dropdown, I can to that. But there does not seem to be a way to filter on m_file.Type == Self.Type

推荐答案

动态创建管理表单类实际上非常容易.像这样的东西应该可以工作:

It is actually quite easy to create your admin form classes dynamically. Something like this should work:

def tagform_factory(filetype):
    class TagForm(forms.ModelForm):
        m_file = forms.ModelChoiceField(
            queryset=ManagedFile.objects.filter(type=filetype)
        )
    return TagForm


class TagAdmin(admin.ModelAdmin):

    def get_form(self, request, obj=None, **kwargs):
        if obj is not None and obj.type is not None:
            kwargs['form'] = tagform_factory(obj.type)
        return super(TagAdmin, self).get_form(request, obj, **kwargs)

请注意,get_form 方法负责构建表单class,而不是表单instance.它的名字很糟糕,恕我直言.

Note that the get_form method is responsible for building the form class, not the form instance. It is badly named, IMHO.

但是,您仍然需要决定如何处理用于添加新标签的表单,而不是编辑现有标签.在这种情况下,您还没有可以限制下拉列表的类型.也许这里实际上潜伏着一个数据建模问题?你真的需要 Tag 模型上的 type 字段吗?也许它应该被删除?

However, you still need to decide what to do for forms that are used to add new tags, rather than edit existing ones. In that case you do not yet have a type to which you can restrict the dropdown. Maybe there is actually a data modeling problem lurking here? Do you really need the type field on the Tag model? Maybe it should just be removed?

这篇关于Django Admin 根据另一个字段过滤 ForeignKey 下拉列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆