【问题标题】:Django - Calling one class method from another in Class Based ViewDjango - 在基于类的视图中从另一个类方法调用一个类方法
【发布时间】:2018-06-11 21:59:39
【问题描述】:

我在基于 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_player_stats 拨打get_team_stats

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

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

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

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

【问题讨论】:

  • 这不是你如何定义事物,而是你如何调用事物。
  • @WillemVanOnsem - 我对 django 很陌生。能否请您详细说明一下?
  • 你在哪里打电话 get_player_stats? (不是get_team_stats)?
  • 我建议将get_player_stats 逻辑提取到外部辅助模块函数中,然后从两个视图中调用它。
  • @UndefinedVariable:我认为您使用 TemplateView 的方式错误。基于类的视图的想法是您可以声明templatequeryset 等。但想法是您可以简单地调用任意函数。见这里:docs.djangoproject.com/en/2.0/ref/class-based-views/base/…

标签: python django django-views


【解决方案1】:

我在这里看到 2 个问题:

  1. django中对class-based views的误解
  2. 关于python 中的object-class- 方法的误解

让我们更详细地了解一下。

1。 Django 基于类的视图

听起来一定很奇怪(尤其是对于新手来说),但是 django 中的class-based view 并不意味着您将objects/classes 的方法绑定到url-routes。

更多:

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

  • Pythonic it's better explicite for 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-方法的存在,当它们存在时调用它们,当它们不存在时引发异常。

所以你可以看到“一个不会简单地将class-view的方法绑定到django中的url-routes”。

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

2。 object-,class-, static- 方法

好的。现在是第二个问题。

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

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

让我们看看 django 2.0 中的one-file 演示。 (对于 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源代码获取灵感

...

我希望必须澄清问题,但问题、批评、更正 - 欢迎您!

【讨论】:

  • 谢谢,很有帮助!
  • @UndefinedVariable “它回答了我的难题”或“它让我深思”是否有帮助?我问你是因为我见过很多次:django 对于新人来说似乎很简单而且没有魔法,直到他/她偶然发现Model/Formmetaclass-magic
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多