【发布时间】:2011-02-02 06:50:09
【问题描述】:
与this question 类似,但我希望能够拥有返回混合对象主体的查询集:
>>> Product.objects.all()
[<SimpleProduct: ...>, <OtherProduct: ...>, <BlueProduct: ...>, ...]
我发现我不能只将 Product.Meta.abstract 设置为 true 或将不同对象的查询集或在一起。很好,但是这些都是公共类的子类,所以如果我将它们的超类保留为非抽象类,我应该很高兴,只要我能让它的管理器返回正确类的对象。 django 中的查询代码完成了它的工作,只是调用 Product()。听起来很简单,除了当我覆盖 Product.__new__ 时它会爆炸,我猜是因为模型中的 __metaclass__... 这是非 django 代码,它的行为与我想要的差不多:
class Top(object):
_counter = 0
def __init__(self, arg):
Top._counter += 1
print "Top#__init__(%s) called %d times" % (arg, Top._counter)
class A(Top):
def __new__(cls, *args, **kwargs):
if cls is A and len(args) > 0:
if args[0] is B.fav:
return B(*args, **kwargs)
elif args[0] is C.fav:
return C(*args, **kwargs)
else:
print "PRETENDING TO BE ABSTRACT"
return None # or raise?
else:
return super(A).__new__(cls, *args, **kwargs)
class B(A):
fav = 1
class C(A):
fav = 2
A(0) # => None
A(1) # => <B object>
A(2) # => <C object>
但是如果我从django.db.models.Model 继承而不是object 则失败:
File "/home/martin/beehive/apps/hello_world/models.py", line 50, in <module>
A(0)
TypeError: unbound method __new__() must be called with A instance as first argument (got ModelBase instance instead)
这是一个非常糟糕的回溯;我也无法在调试器中进入我的__new__ 代码框架。我已经尝试过super(A, cls)、Top、super(A, A) 以及以上所有方法,并结合将cls 作为__new__ 的第一个参数传递给__new__,但都无济于事。为什么这踢我这么狠?我是否必须弄清楚 django 的元类才能解决此问题,还是有更好的方法来实现我的目标?
【问题讨论】:
-
试图解开谜题很诱人,但直觉告诉我你做错了。这对 Django 可怜的小 ORM 来说简直就是折磨。
标签: python django django-models django-queryset metaclass