就像这个问题中的情况一样,但我希望能够有查询集返回混合对象:
>>> Product.objects.all()
[<SimpleProduct: ...>, <OtherProduct: ...>, <BlueProduct: ...>, ...]
我发现不能仅将Product.Meta.abstract
设置为true,或者将不同对象的查询集合并到一起。但这些都是共同类的子类,所以如果我将它们的超类保留为非抽象类,只要我能让其管理器返回正确类的对象,就应该很满意了。Django中的查询代码执行其功能,只需调用Product()。听起来很容易,但当我重写Product.__new__
时,它会崩溃,我猜测是由于Model中的__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__
函数,但都无济于事。这是什么原因?我必须学习Django元类才能解决问题吗?还是有更好的方法实现我的目标?