首页 > 解决方案 > 为什么基于 FormView (CBV) 的视图在上下文中没有 URL 参数?

问题描述

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

网址.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,我不会收到这个关键错误(但我在 POST 表单数据时遇到问题),所以我知道代码基本上没问题。我的理解是 FormView 类应该以与 TemplateView 类相同的方式填充上下文。

知道为什么 FormView 会有这种行为,我怎样才能让它工作?

标签: django

解决方案


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

TemplateView中,get()方法传递kwargsget_context_data方法,因此您可以使用context['pk']。该FormView get()方法在没有传递任何 kwargs 的情况下调用get_context_data(),因此这是行不通的。


推荐阅读