使用 get_queryset 在 CreateView 中过滤模型

Posted

技术标签:

【中文标题】使用 get_queryset 在 CreateView 中过滤模型【英文标题】:Filtering a model in a CreateView with get_queryset 【发布时间】:2014-07-25 08:26:58 【问题描述】:

我正在尝试使用 get_queryset() 过滤模型,它似乎在视图中有效,但在模板中无效。

我的看法:

class FolderCreate(CreateView):
    fields = ['name', 'parent']
    template_name = 'Form/folder_create.html'

    def get_queryset(self):
        folders = Folder.objects.filter(owner=self.request.user) 
        print folders # ==> return [<Folder: Folder>, <Folder: Another folder>]
        return folders

    def form_valid(self, form):
        self.object = form.save(commit=False)
        self.object.owner = self.request.user
        return super(FolderCreate, self).form_valid(form)

    def get_initial(self):
        if self.request.method == 'GET':
            foldersUrl = self.request.META['HTTP_REFERER'].split('/')
            foldersUrl.pop()
            folder = urllib2.unquote(foldersUrl[-1])

            try:
                return 'parent' : Folder.objects.get(name=folder, owner=self.request.user)
            except Folder.DoesNotExist:
                pass

如您所见,文件夹在 get_queryset() 中返回两个与会话用户相关的对象:“文件夹”和“另一个文件夹”

幸运的是,我的模板的组合框获取了所有文件夹,没有任何过滤。

有什么想法吗?

【问题讨论】:

这是你的实际缩进,还是复制粘贴错误? 不抱歉,这是复制粘贴错误,所有函数都在类中。 缩进现已修复。 【参考方案1】:

这里的问题是 get_queryset 没有在 CreateView 中使用,因为它用于过滤返回的模型以在列表或详细视图中显示。您想要完全不同的东西:您想要过滤表单字段中可用的选项。

为此,您需要创建一个接受 user kwarg 的自定义 ModelForm 并相应地过滤查询集:

class FolderForm(forms.ModelForm):
    class Meta:
       model = Folder
       fields = ['name', 'parent']

    def __init__(self, *args, **kwargs):
       user = kwargs.pop('user')
       super(FolderForm, self).__init__(*args, **kwargs)
       self.fields['parent'].queryset = Folder.objects.filter(user=user)

然后更改您的视图以使用该表单并传入用户参数:

class FolderCreate(CreateView):
    template_name = 'Form/folder_create.html'
    form_class = FolderForm

    def get_form_kwargs(self):
        kwargs = super(FolderCreate, self).get_form_kwargs()
        kwargs['user'] = self.request.user
        return kwargs

【讨论】:

谢谢,这是完美的。所以 get_queryset 不能用于填充我的组合框过滤模型。 奇怪的是,CreateView 在某些情况下确实会调用 get_queryset()。特别是为了在需要知道模型时在 self.model 中未指定模型时计算模型。虽然查询集在 CreateView 中意义不大,但它依赖于 ModelFormMixin 的 get_form_class() 方法。

以上是关于使用 get_queryset 在 CreateView 中过滤模型的主要内容,如果未能解决你的问题,请参考以下文章

使用 get_queryset 的 Django ListView 分页

使用 get_queryset() 方法或设置查询集变量?

为什么在具有OneToOneField的模型上使用我的get_queryset不起作用

Django get_object ,get_queryset方法

无法在没有 `.queryset` 属性或覆盖 `.get_queryset()` 方法的视图上应用 DjangoModelPermissions

Django ReadOnlyModelViewSet:get_querySet 被 pk 过滤