如何解决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 举报,一经查实,本站将立刻删除。