Django - 在基于类的视图中从另一个方法调用一个类方法

时间:2018-06-11 21:59:39

标签: python django django-views

我在基于django类的视图中有一个方法,如名为get_player_stats。从这个方法我想在同一个类中调用另一个方法,但我无法。代码如下:

class ScoreView(TemplateView):

   def get_player_stats(request):
       player_id = request.GET.get(player_id, None)
       # compute  player stats

       #here I want to call like below:
       self.get_team_stats(player_id)

   def get_team_stats(self, player_id):
      #compute team stats

当我运行它时,它会显示name 'self' is not defined

如果我尝试def get_player_stats(self, request):,则会显示missing 1 required positional argument: 'request'

如果我尝试def get_player_stats(request, self):,则会显示missing 1 required positional argument: 'self'

如何从get_team_stats致电get_player_stats

这非常令人沮丧,非常感谢任何帮助

P.S:我通过定义如下的URL路径将get_player_stats称为ajax调用:

url('score/get_player_stats', views.ScoreView.get_player_stats)

然后我使用$ .ajax和url: '/score/get_player_stats'

调用它

1 个答案:

答案 0 :(得分:4)

我在这里看到2个问题:

  1. class-based views
  2. django的误解
  3. object-
  4. class-python方法的误解

    让我们更详细地看一下。

    1。 Django基于类的视图

    一定听起来很奇怪(特别是对于新手)但是django中的class-based view并不意味着你将objects / classes的方法绑定到url - 路线。

    更多:

    • django.urls.path只能使用fn(request, *args, **kwargs)

    • 的功能
    • it's better explicite的Pythonic self - param使object-methods无法使用views(至少没有“特殊魔法”)。

    那么class-based views的含义是什么?

    https://github.com/django/django/blob/2bc014750adb093131f77e4c20bc17ba64b75cac/django/views/generic/base.py#L48

    事实上它非常简单:

    1. class-based view公开了类方法as_view
    2. as_view是高阶函数,不会直接用于path / url次调用。
    3. as_view在运行时构造实际的视图函数
    4. 生成的函数也不是很复杂。粗略地说,它寻找存在已定义的get / post / put / head - 方法,在它们存在时调用它们,并在不存在时引发异常。
    5. 所以你可以看到“人们不会简单地将类视图的方法绑定到django中的url-routes”。

      这种工具几乎不适用于一般情况,在需要这种不灵活性的情况下效果很好。

      2。 object-class-static-方法

      行。现在第二个问题。

      我们可以使用class-based view其他方法的方法调用吗?

      是的,我们可以但有一些限制。

      让我们看一下django 2.0中的one-file demo。 (对于1.11 - %s/path/url/g

      from django.urls import path    
      from django.http import HttpResponse
      from django.utils.decorators import classonlymethod
      
      
      # CASE 1: normal function - OK
      def just_a_fun(request, **kwargs):
          context = kwargs if kwargs else {"method": "just a function"}
          return HttpResponse('method = %(method)s' % context)
      
      
      class ViewClass(object):
          def get(self, request, **kwargs):
              return just_a_fun(request, **kwargs)
      
          # CASE 2: Object method - FAIL, not possible to use in `django.url.path`-calls
          def om_view(self, request):
              return self.get(request, **{"method": "object method"})
      
          # CASE 3: class method - OK
          @classmethod
          def cm_view(cls, request):
              return cls.get(cls, request, **{"method": "class method"})
      
          # CASE 4: static method - FAIL, not possible to call `cls.get` or `self.get`
          @staticmethod
          def sm_view(request):
              self = None  # This is a problem with static methods
              return self.get(self, request, **{"method": "static method"})
      
          # CASE 5: HOF-view, similar to django.views.generic.View.as_view - OK
          @classonlymethod
          def as_view(cls, **initkwargs):
              def view(request, **kwargs):
                  self = cls(**initkwargs)  # Object construction
                  self.request = request
                  self.kwargs = kwargs
                  return self.get(request, **{"method": "HOF as_view"})
      
              return view
      
      
      urlpatterns = [
          path("just-a-fun", just_a_fun),  # OK
          path("object-method",
               ViewClass.om_view),  # Problem: redundant `self` for `path`
          path("class-method", ViewClass.cm_view),  # OK
          path('static-method',
               ViewClass.sm_view),  # Problem: not possible to call `get`
          path('hof-view', ViewClass.as_view()),  # OK. 
      ]
      

      要点:

      1. 普通功能最好
      2. 对象方法不可用(至少没有一些“特殊魔法”)
      3. 班级方法:没有问题。但请记住,类方法只能使用其他类方法
      4. 静态方法:可以在path / url调用中使用,但不能使用其他类方法
      5. 如果你真的想要使用OOP:你可以用“django方式”来创建它 - 创建将在运行时生成实际视图函数的HOF。查看django.views.generic源代码以获取灵感
      6. ...

        我希望必须澄清事情,但问题,批评,更正 - 欢迎你!