Django Group.objects 猴子补丁问题 - 'NoneType' 对象没有属性 '_meta'
Django Group.objects monkey patch problem - 'NoneType' object has no attribute '_meta'
我是初级开发人员,我正在尝试猴子补丁 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()
然后我打开pythonshell测试一下:
python manage.py shell
from 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'
我不知道怎么了:(
如有任何帮助,我将不胜感激!
经理需要设置 model
属性。这通常由 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 使它(有点)"work" 你需要:
# 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 上工作),并且 might not work as you expect for all situations .
你不应该不那样的猴子补丁:Django 在 class 的构造中有一些逻辑,它将 "inject" 中的额外数据领域、经理等
通过简单的猴子修补,您可以省略这些步骤。然而,经理有一个 contribute_to_class
方法,所以你可以像猴子一样修补它:
dgm = DefaultGroupManager()
dgm.contribute_to_class(Group, 'objects')
Group.objects = dgm
也就是说,在我看来,如果您覆盖 .objects
管理器,通常会导致很多麻烦,因为很多 Django 代码会假设使用 Group.objects
,您会得到 所有 个对象。此外,许多 Django 工具仍然有可能获取 all Group
s,因为这些可能与 Model._base_manager
[Django-doc].
一起使用
所以虽然它(可能)没有违反任何合同,但它可能会导致比其价值更多的麻烦。
如果您 运行 进行测试,通常您会在 孤立的 环境中进行测试。此外集成测试,通常也在单独的数据库上 运行。
我是初级开发人员,我正在尝试猴子补丁 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()
然后我打开pythonshell测试一下:
python manage.py shell
from 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'
我不知道怎么了:(
如有任何帮助,我将不胜感激!
经理需要设置 model
属性。这通常由 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 使它(有点)"work" 你需要:
# 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 上工作),并且 might not work as you expect for all situations .
你不应该不那样的猴子补丁:Django 在 class 的构造中有一些逻辑,它将 "inject" 中的额外数据领域、经理等
通过简单的猴子修补,您可以省略这些步骤。然而,经理有一个 contribute_to_class
方法,所以你可以像猴子一样修补它:
dgm = DefaultGroupManager()
dgm.contribute_to_class(Group, 'objects')
Group.objects = dgm
也就是说,在我看来,如果您覆盖 .objects
管理器,通常会导致很多麻烦,因为很多 Django 代码会假设使用 Group.objects
,您会得到 所有 个对象。此外,许多 Django 工具仍然有可能获取 all Group
s,因为这些可能与 Model._base_manager
[Django-doc].
所以虽然它(可能)没有违反任何合同,但它可能会导致比其价值更多的麻烦。
如果您 运行 进行测试,通常您会在 孤立的 环境中进行测试。此外集成测试,通常也在单独的数据库上 运行。