为什么基于FormView(CBV)的视图在上下文中没有URL参数?

时间:2019-04-24 20:26:32

标签: django

我有一个基于类的视图,该视图需要接受表单提交。我正在尝试使用URL路径内的主键(例如/ main / video / play / 135)自动填充某些表单字段。基于类的视图基于FormView,如果使用TemplateView,我拥有的代码可使pk在上下文中可用,但这对于处理表单并不是特别好。

urls.py

app_name = 'main'
urlpatterns = [
    #path('', views.index, name='index'),
    path('video/<int:pk>', views.VideoDetailView.as_view(), name='detail'),
    path('video/preview/<int:pk>', views.VideoPreview.as_view(), name='preview'),
    path('player', views.PlayerListView.as_view(), name='player_list'),
    path('video/play/<int:pk>/', views.VideoPlayView.as_view(), name='play'),
    path('', views.VideoListView.as_view(), name="video_list")
]

views.py中的相关类:

class VideoPlayView(FormView):

    template_name = "main/video_play.html"
    form_class = VideoPlayForm
    initial = {}
    http_method_names = ['get', 'post']

    def get_initial(self, **kwargs):
        initial = super().get_initial()
        #initial['video'] = pk
        initial['watch_date'] = datetime.date.today()
        return initial

    def get_context_data(self, **kwargs):
        kc = kwargs.copy()
        context = super().get_context_data(**kwargs)
        video = Video.objects.get(context['pk'])
        context['video'] = video
        context['test'] = kc
        self.initial['video'] = video.pk
        context['viewers'] = Viewer.objects.all()
        context['players'] = Player.objects.filter(ready=True)
        return context

    def form_valid(self, form):
        return HttpResponse("Done")

我在此行遇到关键错误:

video = Video.objects.get(context['pk'])

在错误页面上查看调试信息表明该上下文中没有存储pk值。

如果我使用FormMixin将基类更改为TemplateView,则不会收到此关键错误(但是在发布表单数据时确实存在问题),因此我知道代码基本上是可以的。我的理解是FormView类应该以与TemplateView类相同的方式填充上下文。

您知道为什么FormView会以这种方式工作,以及如何使它正常工作吗?

1 个答案:

答案 0 :(得分:2)

如果您想从网址中获取pk,则self.kwargs['pk']将在所有Django通用基于类的视图中使用。

TemplateView中,get()方法将kwargs传递给get_context_data方法,因此您可以使用context['pk']FormView get()方法调用get_context_data()而不传递任何kwarg,因此将无法正常工作。