Python 具有集成查询集的子类django模型

Python 具有集成查询集的子类django模型,python,django,django-models,django-queryset,metaclass,Python,Django,Django Models,Django Queryset,Metaclass,与中类似,但我希望能够拥有返回混合对象体的查询集: >>> Product.objects.all() [<SimpleProduct: ...>, <OtherProduct: ...>, <BlueProduct: ...>, ...] 但是如果我从django.db.models.Model而不是object继承,那就失败了: File "/home/martin/beehive/apps/hello_world/models.py"

与中类似,但我希望能够拥有返回混合对象体的查询集:

>>> Product.objects.all()
[<SimpleProduct: ...>, <OtherProduct: ...>, <BlueProduct: ...>, ...]
但是如果我从
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)
文件“/home/martin/beehive/apps/hello\u world/models.py”,第50行,在
A(0)
TypeError:必须以实例作为第一个参数调用未绑定的方法\uuuuu new\uuuuuu()(改为获取ModelBase实例)
这是一个非常糟糕的回溯;我也无法在调试器中进入我的
\uuuuu new\uuuu
代码的框架。我尝试了各种各样的
super(A,cls)
Top
super(A,A)
,以及以上所有方法,并将
cls
作为
\uuu new\uuuu
的第一个参数传入,但都没有效果。为什么这么用力踢我?我必须找出django的元类才能解决这个问题,还是有更好的方法来实现我的目标?

好的,这很有效:

棘手的是这一点

class A(Top):
    pass

def newA(cls, *args, **kwargs):
    # [all that code you wrote for A.__new__]

A.__new__ = staticmethod(newA)
现在,关于Python如何绑定
\uuuuu new\uuuuu
,我可能不太了解,但其要点是:django的
ModelBase
元类创建一个新的类对象,而不是使用传递给它的
\uuuuuuu new\uuuuuuuu
的对象;把它叫做素数。然后它将
A
的类定义中的所有属性粘贴到
A_prime
上,但是
\uuu new\uu
没有正确地重新绑定

然后,当您计算
A(1)
时,
A
实际上是
A_prime
这里,python调用
(A_prime,1)
,它不匹配,然后爆炸

因此,解决方案是在定义了
素数
之后定义你的
\uuuuuu new\uuuuuu

也许这是django.db.models.base.ModelBase.add_to_class
中的一个bug,也许是Python中的一个bug,我不知道


现在,当我在前面提到“this works”时,我的意思是这与当前SVN版本的Django中的最小对象构造测试用例是隔离的。我不知道它是否真的可以作为一个模型使用,或者在QuerySet中是否有用。如果你真的在生产代码中使用了它,我会为pdxpython做一个公开的闪电演讲,让他们嘲笑你,直到你给我们买了所有的无麸质比萨饼。

基本上你要做的是返回不同的子类,同时查询一个共享基类。也就是说:您需要叶类。检查此代码段以获取解决方案:


还要确保查看Django的Contenttypes框架上的文档:一开始可能会有点混乱,但Contenttypes将解决在Django的ORM中使用非抽象基类时可能会遇到的其他问题。

只需在
\uuu new\uu
方法之前粘贴@staticmethod即可

@staticmethod
def __new__(cls, *args, **kwargs):
    print args, kwargs
    return super(License, cls).__new__(cls, *args, **kwargs)
您想要其中一个:



还有一些缺点,即额外的查询。

我最近发现的另一种方法是:

尝试解决这个难题很有诱惑力,但直觉告诉我你做错了。这对Django可怜的小ORM来说就像是一种折磨。好吧,这让我得到了所需的子类化行为,但它会打破我所有的关系吗!然后,我的任何对象都不能与其他模型关联。我将进一步研究它,看看是否可以修复该方面。snippet链接已断开。
@staticmethod
def __new__(cls, *args, **kwargs):
    print args, kwargs
    return super(License, cls).__new__(cls, *args, **kwargs)