Django DetailView基于对象的附加检查

时间:2018-01-31 18:02:43

标签: django django-generic-views detailview

应该覆盖哪个方法来添加额外的检查并相应地重定向?

即。我的产品页面有一个DetailView,如果该产品未发布(品牌有更多产品),我想重定向到品牌页面。

我将此检查添加到get方法,我手动调用get_object()然后进行检查,但最后我还调用super().get()调用get_object() 1}}这也使SQL运行两次。

我发现的解决方案是覆盖get_object()方法,如下所示。

def get_object(self, queryset=None):
    if not hasattr(self, 'object') or not self.object:
        self.object = super().get_object(queryset=queryset)
    return self.object

这感觉不对,在不触发get_object两次的情况下进行检查的最佳方式是什么?

我调用get_object两次的代码如下所示:没有上面的hack。

def get(self, request, *args, **kwargs):
    product = self.get_object()
    if not product.published:
        if product.brand and #more products from brand exists#
            return redirect(reverse('brand',
                                    args=(product.brand.slug,)))
        else:
            return redirect(reverse('pages:home'))

    return super().get(request, *args, **kwargs)

仅供参考super()。看起来像这样,我不想重写这些行。 https://ccbv.co.uk/projects/Django/1.10/django.views.generic.detail/DetailView/#get

def get(self, request, *args, **kwargs):
    self.object = self.get_object()
    context = self.get_context_data(object=self.object)
    return self.render_to_response(context)

1 个答案:

答案 0 :(得分:0)

我认为这更清晰 - 存储super().get(...)调用的响应,该调用也将填充self.object,然后在必要时重定向,或者返回super().get(...)调用中存储的响应:

def get(self, request, *args, **kwargs):
    super_response = super().get(request, *args, **kwargs)
    if not self.object.published:
        if self.object.brand and #more products from brand exists#
            return redirect(reverse('brand',
                                    args=(self.object.brand.slug,)))
        else:
            return redirect(reverse('pages:home'))
    return super_response

请注意,这确实会产生为未发布的对象创建有效响应的开销。为了避免这种情况,只需避免超级呼叫 - 是的,这意味着从超类中复制两行代码'方法:

def get(self, request, *args, **kwargs):
    self.object = self.get_object()
    if not self.object.published:
        if self.object.brand and #more products from brand exists#
            return redirect(reverse('brand',
                                    args=(self.object.brand.slug,)))
        else:
            return redirect(reverse('pages:home'))

    context = self.get_context_data(object=self.object)
    return self.render_to_response(context)