【问题标题】:Django: correct use of class-based View inheritance?Django:正确使用基于类的视图继承?
【发布时间】:2015-12-04 14:54:15
【问题描述】:

我希望几乎我的 Django 项目中的每个视图都可以计算,例如,time_on_mars。这个变量需要放入每个模板上下文中,所以每个模板都可以绘制time_on_mars。我还希望每个视图都能够根据需要使用该变量,也许可以计算is_it_nighttime_on_mars 或其他任何东西。我想使用继承或其他一些机制来做到这一点,所以当我提供比火星时间更多的东西时,我不会重复自己。

这是对基于类的视图的适当使用吗?我想我会创建一个基类视图,在它的get和post方法中,计算火星上的当前时间,然后调用子类方法'doGet'或'doPost',截取结果,将火星时间放入结果中, 并继续。看起来很乏味。

装饰师?有没有办法可以将time_on_mars 放入视图的闭包上下文中?

pythonic(djangonic?)的方法是什么?

编辑:我喜欢上下文处理器的想法,但我改变了主意 - 而不是 every 视图,我希望 大多数 视图来获得这个。特别是如果在火星上计算时间很昂贵......

编辑 2:问题描述不充分!澄清一下:

我有很多这样做的视图:

def some_view(request):
   w,x,y,z = provision_wxyz()
   ... some biz logic, maybe compute a,b,c using w,x,y,z ...
   return render(request, 'some_template.html', { 'a':a, 'b':b, 'c':c, 'w':w, 'x':x, 'y':y, 'z':z })

...我想抽象出第一步 (w,x,y,z=),并将 w,x,y,z 添加到模板上下文中。上下文处理器不起作用,因为在 some_view 业务逻辑中,我想访问 w,x,y,z。我不喜欢在 TemplateView 上为 CLA 执行混合策略,因为同样,它不允许我访问 some_view 中的 w、x、y 和 z(或任何与 some_view 等效的东西),我想要,好吧,在某处做一堆业务逻辑,而 TemplateView 似乎没有给我这个?

【问题讨论】:

  • 这是context processors的工作。
  • 我可以使用我的自定义请求上下文在我的视图本身(不仅仅是模板)中生成的变量吗?
  • 没有。如果你想要它,自定义基类(或 mixin)是你最好的选择。
  • 基于类的视图也不能解决问题——如何确保所有子类都向渲染上下文添加适当的变量?这太不可思议了,我一定是错过了什么。
  • 我不明白为什么这不是一个解决方案。您可以通过在您的类中定义 get_context_data 来确保将您的值添加到由超类创建的字典中。

标签: python django django-class-based-views


【解决方案1】:

您绝对可以为此使用 CBV。它对利用 python 多重继承的 Mixins 很有用。这是我刚刚写的一个快速而肮脏的例子。

class MarsMixin(object):
    time_on_mars = 5

    def get_time_on_mars(self):
        """
        Does what it takes to return a time on mars be it calculation
        or returning a property set on the object. Should return a property
        from the object if it is a constant. Should calcualte in the method
        if it is going to be dynanic
        """
        return self.time_on_mars

    def get_context_data(self, **kwargs):
        context = super(MarsMixin, self).get_context_data(**kwargs)
        context['time_on_mars'] = self.get_time_on_mars()
        return context


class HomeView(MarsMixin, TemplateView):
    template_name = 'home/index.html'

最大的注意是 mixin 继承自 object。另一种是你从HomeView中的mixin继承,它列在TemplateView之前。

【讨论】:

    【解决方案2】:

    我认为您仍然可以使用上下文处理器,可以提供帮助的提示是在您要进行计算的 URL 前添加前缀,例如它们将以“/mars/...”开头。您也可以使用其他类型的前缀。

    这样你可以检查上下文处理器方法:

    def go_to_mars(request):
        if request.path.startswith('/mars/'):
            return {'time_on_mars': calculate_time_on_mars()}
        return {}
    

    【讨论】:

      猜你喜欢
      • 2012-10-27
      • 1970-01-01
      • 2019-07-30
      • 1970-01-01
      • 1970-01-01
      • 2022-07-02
      • 2023-04-08
      • 2019-01-28
      • 2021-06-26
      相关资源
      最近更新 更多