Django Group.objects проблема с патчем обезьяны - у объекта 'NoneType' нет атрибута '_meta' - PullRequest
0 голосов
/ 26 сентября 2018

Я младший разработчик, и я пытаюсь установить патч django.contrib.auth.models Менеджер группы.(Python 2.7.15, Django 1.8)

Вот мой код:

class DefaultGroupManager(models.Manager):
    def get_queryset(self):
        tests = Test.objects.values()
        tests_ids = [test['virtual_group_id'] for test in tests]
        return super(DefaultGroupManager, self).get_queryset().exclude(id__in=tests_ids)


Group.objects = DefaultGroupManager()

Затем я открываю оболочку python для проверки:

python manage.py shell

из django.contrib.auth.models import Group

t = Group.objects.all ()

Сразу после этой команды я получаюошибка:

  File "<console>", line 1, in <module>
  File "/home/adrian/Dokumenty/Pycharm Projects/backend/venv/local/lib/python2.7/site-packages/django/db/models/manager.py", line 228, in all
    return self.get_queryset()
  File "/home/adrian/Dokumenty/Pycharm Projects/backend/registration/models.py", line 13, in get_queryset
    return super(DefaultGroupManager, self).get_queryset().exclude(id__in=tests_ids)
  File "/home/adrian/Dokumenty/Pycharm Projects/backend/venv/local/lib/python2.7/site-packages/django/db/models/query.py", line 686, in exclude
    return self._filter_or_exclude(True, *args, **kwargs)
  File "/home/adrian/Dokumenty/Pycharm Projects/backend/venv/local/lib/python2.7/site-packages/django/db/models/query.py", line 695, in _filter_or_exclude
    clone.query.add_q(~Q(*args, **kwargs))
  File "/home/adrian/Dokumenty/Pycharm Projects/backend/venv/local/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1310, in add_q
    clause, require_inner = self._add_q(where_part, self.used_aliases)
  File "/home/adrian/Dokumenty/Pycharm Projects/backend/venv/local/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1338, in _add_q
    allow_joins=allow_joins, split_subq=split_subq,
  File "/home/adrian/Dokumenty/Pycharm Projects/backend/venv/local/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1150, in build_filter
    lookups, parts, reffed_expression = self.solve_lookup_type(arg)
  File "/home/adrian/Dokumenty/Pycharm Projects/backend/venv/local/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1036, in solve_lookup_type
    _, field, _, lookup_parts = self.names_to_path(lookup_splitted, self.get_meta())
  File "/home/adrian/Dokumenty/Pycharm Projects/backend/venv/local/lib/python2.7/site-packages/django/db/models/sql/query.py", line 246, in get_meta
    return self.model._meta
AttributeError: 'NoneType' object has no attribute '_meta'

Понятия не имею, что не так: (

Буду признателен за любую помощь!

Ответы [ 2 ]

0 голосов
/ 26 сентября 2018

Вы должны не патч обезьяны, подобный этому: Django имеет некоторую логику при создании класса, которая будет "вставлять" дополнительные данные в поля, менеджеров и т. Д.

Просто исправляя обезьяны, вы пропускаете эти шаги.У менеджера, однако, есть метод contribute_to_class, так что вы можете сделать это, как обезьяна:

dgm = DefaultGroupManager()
dgm.contribute_to_class(Group, 'objects')
Group.objects = dgm

При этом, на мой взгляд, это обычно приводит к большим неприятностям, если вы перезаписываете менеджер .objects, поскольку большая часть кода Django предполагает, что с Group.objects вы получаете все объекты.Более того, все еще возможно, что многие инструменты Django будут извлекать все Group с, поскольку они могут работать с Model._base_manager [Django-doc] .

Таким образом, хотя он (вероятно) не нарушает какие-либо контракты, это, вероятно, приведет к большему количеству проблем, чем стоит.

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

0 голосов
/ 26 сентября 2018

Менеджеру необходимо установить атрибут model.Обычно это делается во время импорта метаклассом Модели, но так как вы обойдете его, вы должны установить его самостоятельно:

class DefaultGroupManager(models.Manager):
    model = Group

    def get_queryset(self):
        # this avoids a useless db query + python loop
        tests_ids = Test.objects.values_list('virtual_group_id', flat=True)
        return super(DefaultGroupManager, self).get_queryset().exclude(id__in=tests_ids)

РЕДАКТИРОВАТЬ: глупо, есть другие шаги, необходимые для правильной инициализации менеджера, которые частично реализованы в Manager.contribute_to_class, а частично нет (извините, у вас нет времени на дальнейшее изучение этого вопроса, но вы можете просто прочитать исходный код Django, чтобы узнать) ... IOW, чтобы сделать это (вроде) "работа", которая вам понадобится:

# You also want to inherit from GroupManager, some code
# relies on extra stuff defined here

from django.contrib.auth.models import GroupManager

class DefaultGroupManager(GroupManager):    
    def get_queryset(self):
        tests_ids = Test.objects.values_list('virtual_group_id', flat=True)
        return super(DefaultGroupManager, self).get_queryset().exclude(id__in=tests_ids)


manager = DefaultManager()
manager.contribute_to_class(Group, "objects")
Group._meta.managers_map["objects"] = manager

НО : в лучшем случае это хрупко (на самом деле я даже не могу гарантировать, что она работает на Django> 1.10.x), и может работать не так, как вы ожидаете, для всех ситуаций .

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