微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Django:如何将我的基于函数的视图重新创建为基于类的通用编辑视图

如何解决Django:如何将我的基于函数的视图重新创建为基于类的通用编辑视图

我有一个基于函数的视图,该视图当前正在成功运行。但是,我想学习如何使用通用的UpdateView类来创建此函数的等效的基于类的视图版本-尽管我认为解决方案(无论它是什么)也将与CreateView完全相同。

我知道一般如何创建和使用基于类的视图,但是基于函数的视图中有一行我无法使用到相应的UpdateView中-就像一般的基于类的视图一样,目前尚不清楚我需要重写哪种方法来插入所需的功能

我不能移植到CBV的特定任务,可以说是一行覆盖了将用于显示特定字段的查询集,该查询集被定义为另一种模型的ForeignKey在我的数据库中。

首先,基于工作功能的视图,突出显示了我在CVB版本中无法使用的特定代码段:

@login_required
def update_details(request,pk):
    """update details of an existing record"""
    umd_object = UserMovieDetail.objects.select_related('movie').get(pk=pk)

    movie = umd_object.movie

    if umd_object.user != request.user:
        raise Http404

    if request.method != 'POST':
        form = UserMovieDetailForm(instance=umd_object)

        # this is the single line of code I can't get working in UpdateView version:

        form.fields['user_guess'].queryset = User.objects.filter(related_game_rounds=movie.game_round)

    else:
        form = UserMovieDetailForm(instance=umd_object,data=request.POST)
        if form.is_valid():
            form.save()

            return redirect(movie)

    context = {'form': form,'object': umd_object }
    return render(request,'movies/update_details.html',context)

对于此行,我可以成功地在UpdateView中重新创建此基于功能的视图的每个部分除外(为清晰起见,从上方复制):

    form.fields['user_guess'].queryset = User.objects.filter(related_game_rounds=movie.game_round)

此行的作用:ForeignKey的认Form字段为 ModelChoiceField 认情况下,它显示相关Model的所有对象。上面的代码重写了该行为,并说:我只希望表单显示此过滤的对象集。只要我使用的是基于函数的视图,它就可以正常工作。

侧面注释:我知道可以通过修改forms.py文件中的ModelForm本身来实现此结果。这个问题的目的是更好地了解如何使用内置的基于通用类的视图,使它们能够重新创建我已经可以使用基于函数的视图实现的功能。因此,请不要回答“为什么不直接以表单本身的形式来回答我”的问题-我已经知道了这个选项,而这并不是我要尝试解决的问题。

现在使用 UpdateView (同样,我认为 CreateView 也是一样)。首先,它看起来基本上是这样的:

class UpdateDetailsView(LoginrequiredMixin,UpdateView):
    model = UserMovieDetail
    template_name = 'movies/update_details.html'
    form_class = UserMovieDetailForm

    login_url = 'login' # used by LoginrequiredMixin

    # what method do I override here,to include that specific line of code,which needs
    # to occur in the GET portion of the view?    

    def get_success_url(self):
        return reverse('movies:movie',kwargs={'pk': self.object.movie.pk,'slug': self.object.movie.slug })

以上是我基于函数的视图的有效创建,复制了所有行为,除了,那是一条重要的行,该行过滤了表单中特定字段的ModelChoiceField显示的结果。>

如何使该行代码在此UpdateView中起作用?我已经查看了基于类的经典视图网站上UpdateView内置的方法,然后尝试(通过纯粹的猜测)覆盖了 get_form_class 方法,但是我没有用,我基本上是在黑暗中拍摄。

请注意,由于我要重新创建的功能与表单的ModelChoiceField中项目的显示有关,因此所需的行为适用于视图的GET部分,而不是POST。因此,我需要能够在第一次呈现表单之前覆盖表单字段,就像我在基于函数的视图中所做的一样。我在哪里以及如何在UpdateView中做到这一点?

解决方法

首先,从功能视图中的raise Http404看与表格无关的笔记,我了解您要允许用户仅访问自己的电影。对于基于类的视图,您可以覆盖get_queryset方法:

class UpdateDetailsView(LoginRequiredMixin,UpdateView):
    def get_queryset(self):
        return UserMovieDetail.objects \
            .filter(user=request.user) \
            .select_related('movie')

现在让我们转到自定义表单。

选项1-.get_form()

您可以覆盖UpdateView的get_form方法:

class UpdateDetailsView(LoginRequiredMixin,UpdateView):
    form_class = UserMovieDetailForm

    def get_form(self,form_class=None):
        form = super().get_form(form_class)
        # add your customizations here
        round = self.object.movie.game_round
        form.fields['user_guess'].queryset = \
            User.objects.filter(related_game_rounds=round)
        return form

选项2-将自定义项移至表单类和.get_form_kwargs()

您可能希望将自定义逻辑从视图移动到表单。为此,您可以覆盖表单的__init__方法。如果自定义逻辑需要其他信息(例如,queryset取决于当前用户),那么您还可以覆盖get_form_kwargs方法以将其他参数传递给以下形式:

# views.py
class UpdateDetailsView(LoginRequiredMixin,UpdateView):
    form_class = UserMovieDetailForm

    def get_form_kwargs(self):
        kwargs = super().get_form_kwargs()
        kwargs.update({'current_user': self.request.user})
        return kwargs


# forms.py
class UserMovieDetailForm(forms.ModelForm):
    def __init__(self,*args,**kwargs):
        self.current_user = kwargs.pop('current_user')
        super().__init__(*args,**kwargs)
        # add your customizations here
        self.fields['user_guess'].queryset = ...

P.S。通常,https://ccbv.co.uk/

是理解django类视图的重要资源。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。