我有一个小实用程序模块django-delegate,它允许您在QuerySet子类上定义方法,然后通过@delegate
装饰将这些方法定义“委托”到相应的Manager子类。
看起来像这样,如果我可以引用我自己的README:
from delegate import DelegateManager, delegate
class CustomQuerySet(models.query.QuerySet):
@delegate
def qs_method(self, some_value):
return self.filter(some_param__icontains=some_value)
def dont_delegate_me(self):
return self.filter(some_other_param="something else")
class CustomManager(DelegateManager):
__queryset__ = CustomQuerySet
class SomeModel(models.Model):
objects = CustomManager()
...该设置允许在模型的管理器引用上进行方法链接,而不需要任何运行时调度,如此†:
>>> SomeModel.objects.custom_query().another_custom_query()
在幕后,该模块通过在Manager子类DelegateManager上使用元类工作 - 并且在Django变为1.6之前一直没有问题。现在,当使用使用DelegateManager的模型导入应用程序时,我得到其中一个令人发狂的深奥元类相关的showstopper TypeErrors:
>>> from tika import models as tika
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "/Users/fish/Praxa/TESSAR/instance/tika/models.py", line 4, in <module>
from delegate import DelegateManager, delegate
File "/Users/fish/Praxa/TESSAR/local/lib/python2.7/site-packages/delegate/__init__.py", line 108, in <module>
class DelegateManager(models.Manager):
File "/Users/fish/Praxa/TESSAR/local/lib/python2.7/site-packages/delegate/__init__.py", line 105, in __new__
cls, name, bases, attrs)
TypeError: Error when calling the metaclass bases
metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases
>>>
TL,DR: Django与管理器相关的管道版本1.5和1.6之间发生的事情可能导致这种情况发生?
† - 注意,我明白我可以通过以下方式解决这个问题:a)阅读Django源差异的无穷无尽的kLOC,或者b)在其中一个中完成大致相同的事情其他方式可以接近django-delegate地址的概念性想法;主要是我对导致这个Manager元类情况的任何内容感兴趣。谢谢你,我的同伴Djangonauts
答案 0 :(得分:3)
为了弃用get_query_set
而使用get_queryset
(#15363),django.db.models.manager.Manager
现在是django.db.models.manager.RenameManagerMethods
的实例,django.utils.deprecation.RenameMethodsBase
的子类}}
由于delegate.DelegateSupervisor
不是django.db.models.manager.RenameManagerMethods
的(非严格)子类,因此Python无法解析正确的delegate.DelegateManager
元类。
要解决此问题,您应确保delegate.DelegateSupervisor
是type(django.db.models.manager.Manager)
的子类,而不是type
。这适用于Django 1.5和1.6。我在您的存储库上创建了一个PR以解决此问题。
顺便说一下,你可能想看一下Django 1.7 release note。 Django内置了代理替代方案。