我有一个这样的模型:
class Test(models.Model):
is_private = models.BooleanField(default=False)
我有这样的观点:
class TestDetaiView(View):
def get(self, request, pk):
return render(request, 'test.html', {'story': Story.objects.get(pk=pk)}
现在,我想要做的是:如果test是私有的,则应用vary_on_cookie
装饰器,否则使用cache_page
装饰器。
怎么做?
答案 0 :(得分:2)
这里的关键问题是你想在运行时选择装饰器,但通常的装饰器语法是在类声明时触发的。幸运的是,装饰器只是常规的Python callables,因此如果需要,可以在运行时应用它们。
有许多不同的方法可以构建它。下面我创建了一个自定义装饰器,因为这将允许您在多个CBV中重复使用相同的代码。 (当然,这可以进一步推广。)
请注意,正如the documentation中所讨论的,在CBV中应用Django装饰器的正确位置是dispatch()
方法;并且您需要使用method_decorator
来使Django的内置装饰器适合与类一起使用。
def test_decorator(dispatch_wrapped):
def dispatch_wrapper(self, request, *args, **kwargs):
# presumably you're filtering on something in request or the url
is_private = Test.objects.get(...).is_private
decorator = vary_on_cookie if is_private else cache_page(60 * 15)
dispatch_decorated = method_decorator(decorator)(dispatch_wrapped)
return dispatch_decorated(self, request, *args, **kwargs)
return dispatch_wrapper
class TestDetaiView(View):
@test_decorator
def dispatch(self, *args, **kwargs):
# any custom dispatch code, or just...
super().dispatch(*args, **kwargs)
如果这令人困惑,可能有助于阅读有关装饰器以及它们如何定义和使用的更多信息。
答案 1 :(得分:0)