如何自定义Django中使用主表主键的admin Inline字段的Queryset?

4 投票
2 回答
4433 浏览
提问于 2025-04-16 12:28

在Django中,自定义表单字段的查询集其实并不难。就像这样

假设我有以下这些模型:

#models.py

class Work(Model):
    name = models.CharfField(...)
    #some fields

class Gallery(Model):
    work = models.ForeignKey(Work)

class Photo(Model):
   gallery = models.ForeignKey(Gallery)

class StageOfWork(Model):
    work = models.ForeignKey(Work)
    gallery = models.ForeignKey(Gallery)
    #some fields

还有一个像这样的admin.py文件:

#admin.py

class StageOfWorkAdmin(admin.TabularInline):
    model = StageOfWork
    form = StageOfWorkForm
    extra = 1

class WorkAdmin(admin.ModelAdmin):
    inlines = [EtapaObraAdmin]

我遇到了一个问题:当我编辑一个工作(Work)时,有很多StageOfWorks的表单,这些StageOfWorks的表单里有一个画廊(Gallery)选择器。我需要自定义这个画廊的查询集,像这样:

class StageOfWorkForm(ModelForm):

    def __init__(self, *args, **kwargs):        
        super(StageOfWorkForm, self).__init__(*args, **kwargs)
        if 'instance' in kwargs:
             self.fields['gallery'].queryset = Gallery.objects.filter(work__id=self.instance.work.id)

但是,这个方法只在我编辑的表单中有效。我需要在init方法的上下文中获取工作ID,以便无论如何都能正确地获取查询集。

我该怎么做呢?

2 个回答

3

我没有做过完全一样的事情,但我做过类似的事。我用过一个叫Smart Selects的Django插件。你可以在这里找到它:https://github.com/digi604/django-smart-selects

我在后台管理中用这个插件做了一个过滤选择框,不过那是在一个普通的模型里,不是在内联模型中。不过这个插件很可能也能在内联模型中使用。我建议你至少去看看。

Hailey

4

我能做到这一点的唯一方法就是在创建表单类的时候,把你需要的数据传进去。

也就是说,在你的视图里:

def view(request):
    ...
    work = <whatever>
    form = StageOfWorkForm(work, request.POST)
    ...

然后,你的表单需要这个工作对象:

class StageOfWorkForm(ModelForm):
    def __init__(self, work, *args, **kwargs):
        super(StageOfWorkForm, self).__init__(*args, **kwargs)
        self.fields['gallery'].queryset = work.gallery_set.all()

撰写回答