持久化 Django FormView 数据

Persist Django FormView Data

我有一个 FormView,它生成一个对象的评论(它通常与之相关),然后将它链接到该对象并在表单完成时保存它。

我遇到的问题是我无法保留要连接的对象的数据。这意味着我需要 'look it up' 用于上下文(模板渲染)以进行有效处理(进行链接)和成功(生成适当反转的 url。

是否有更好的方法将评论绑定到对象?或者更好的是,有没有办法保留我丢失的表单数据?

编辑:抱歉,登录装饰器正在派遣中。我删除了那个方法,因为 SO 抱怨代码太多而且我认为它不相关......我一定错过了 decoratot

class ReviewCreate(FormView):
    template_name = 'food/item_add_review.html'
    form_class = ReviewForm
    review_item = None


    def get_context_data(self, **kwargs):
        context = super(ReviewCreate, self).get_context_data(**kwargs)

        item_modelname = self.kwargs.get('model')
        item_model = apps.get_model('food',item_modelname)
        review_item = get_object_or_404(item_model,pk=self.kwargs.get('pk'))

        context['item'] = review_item

        return context

    def form_valid(self, form):
        item_modelname = self.kwargs.get('model')
        item_model = apps.get_model('food',item_modelname)
        review_item = get_object_or_404(item_model,pk=self.kwargs.get('pk'))

        r = form.save(commit=False)

        r.content_object=review_item
        r.save()

        return super(ReviewCreate, self).form_valid(form)

    def get_success_url(self): 
        item_modelname = self.kwargs.get('model')
        item_model = apps.get_model('food',item_modelname)
        review_item = get_object_or_404(item_model,pk=self.kwargs.get('pk'))

        return reverse( 'pkitem', kwargs = {'pk': review_item.id, 'model':item_modelname},)

视图是一个对象,所以你只需将你的值分配给实例变量,即 "to self" (this is thread-safe)。像这样:

class ReviewCreate(FormView):
    template_name = 'food/item_add_review.html'
    form_class = ReviewForm

    @method_decorator(login_required)  # Use a class level mixin instead
    def get_context_data(self, **kwargs):
        return super(
            ReviewCreate, 
            self
        ).get_context_data(
            item=self.review_item,
            **kwargs
        )

    def lookup_review_item(self):
        self.item_modelname = self.kwargs.get('model')
        item_model = apps.get_model('food', self.item_modelname)
        self.review_item = get_object_or_404(
            item_model, 
            pk=self.kwargs.get('pk')
        )

    def dispatch(self, request, *args, **kwargs):
        # lookup performed here to be set for both GET and POST
        self.lookup_review_item()
        return super(ReviewCreate, self).dispatch(request, *args, **kwargs)

    def form_valid(self, form):
        r = form.save(commit=False)
        r.content_object=self.review_item
        r.save()
        return super(ReviewCreate, self).form_valid(form)

    def get_success_url(self):
        return reverse(
            'pkitem', 
            kwargs = {
                'pk': self.review_item.id, 
                'model': self.item_modelname
            },
        )

get_context_data 应该总是 return 上下文字典。与它一起使用 login_required 装饰器是没有意义的,因为这意味着它可能 return 一个重定向响应。

最好修饰 dispatch 方法。在您的 dispatch 中,您可以在实例上设置属性。

class ReviewCreate(FormView):

    @method_decorator(login_required)
    def dispatch(self, request, *args, **kwargs):
        self.item_modelname = self.kwargs.get('model')
        self.item_model = apps.get_model('food',item_modelname)
        self.review_item = get_object_or_404(item_model,pk=self.kwargs.get('pk'))
        return super(ReviewCreate, self).dispatch(request, *args, **kwargs)

然后,在你的其他方法中,你可以访问属性,例如:

    def get_context_data(self, **kwargs):
        context = super(ReviewCreate, self).get_context_data(**kwargs)
        context['item'] = self.review_item
        return context

FormView 的默认 form_valid() 方法重定向到成功 url 并重新初始化表单。您可以通过覆盖 form_valid():

使表单数据持久化
def form_valid(self, form):
    return super(YourFormView, self).get(form)

这将重定向到您的成功 url,其中包含包含已发布数据的(有界)表单。表单已添加到上下文中,因此您可以根据需要在模板或视图中使用数据。

(Django 版本 1.11.7)