Django - вызов одного метода класса из другого в представлении на основе классов - PullRequest
0 голосов
/ 12 июня 2018

У меня есть метод внутри представления, основанного на классах 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?

Это очень расстраивает, любая помощь очень ценится

PS: ЯВызовите get_player_stats как вызов ajax, определив путь URL, как показано ниже:

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

Затем я вызываю его, используя $ .ajax с url: '/score/get_player_stats'

1 Ответ

0 голосов
/ 12 июня 2018

Я вижу здесь 2 проблемы:

  1. Неправильные представления о class-based views в django
  2. Неправильные представления о object- и class- методах в python

Давайте посмотрим более подробно.

1.Представления на основе классов Django

Это должно звучать странно (особенно для новичков), но class-based view в django не означает, что вы привязываете методы objects / classes к url -байтам.

Более того:

  • django.urls.path могут использовать только функции fn(request, *args, **kwargs)

  • Pythonic it's better explicite для self -парам делает 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 -методов, вызывает их, когда они существуют, и вызывает исключения, когда их не существует.

Итак, вы можете видеть, что «человек не просто привязывает методы представления классов к URL-маршрутам в django».

Это инструмент, который вряд ли можно рекомендовать для общего пользования.в случаях, когда это негибкость желательна.

2.object-, class-, static- методы

ОК.Теперь вторая проблема.

Можем ли мы вызывать из class-based view методы других методов?

Да, мы можем, но с некоторыми ограничениями.

Давайте рассмотрим демо one-file в django 2.0.(Для 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. Если вы действительно хотите использовать ООП: вы можете сделать это «способом django» - создайте HOF, которые будут генерировать реальные функции представлений во время выполнения.Посмотрите на django.views.generic исходный код для вдохновения

...

Я надеюсь, что все должно проясниться, но вопросы, критика, исправления - милости просим!

...