【问题标题】:Django DetailView additional checks based on objectDjango DetailView 基于对象的额外检查
【发布时间】:2018-07-10 22:43:04
【问题描述】:

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

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

我将此检查添加到get 方法中,我手动调用get_object(),然后进行检查,但最后我也调用super().get(),它也调用get_object(),这使得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().get 看起来像这样,我不想重写这些行。 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)

【问题讨论】:

  • 有必要打电话给super()吗?有什么理由不能只添加行来获取上下文并呈现响应?
  • @Joseph 我可以,但我不想从 DetailView 重写代码。我的感觉是应该在 get_object 和 get 之间有另一种方法可以让我做一些检查。

标签: django django-generic-views detailview


【解决方案1】:

我认为这样更简洁 - 存储 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

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

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)

【讨论】:

    猜你喜欢
    • 2013-08-17
    • 2021-04-24
    • 2017-03-09
    • 1970-01-01
    • 1970-01-01
    • 2013-03-25
    • 2020-08-31
    • 2016-11-09
    • 2019-07-16
    相关资源
    最近更新 更多