这个问题, ,除了我希望能够拥有返回混合物体的QuerySet:

>>> Product.objects.all()
[<SimpleProduct: ...>, <OtherProduct: ...>, <BlueProduct: ...>, ...]

我发现我不能只是设置 Product.Meta.abstract 对或以其他方式或否则或将不同对象的查询集。很好,但是这些都是普通班的子类,因此,如果我将他们的超级阶级留为非抽象,我应该很高兴,只要我能让它的经理返回适当的班级的对象。 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__, ,无济于事。为什么这会让我这么努力?我是否必须弄清楚Django的元素才能解决此问题,或者有更好的方法可以完成我的目标?

有帮助吗?

解决方案

基本上,您要做的是在查询共享基础类的同时返回不同的儿童课程。也就是说:您想要叶子类。检查此片段是否有解决方案: http://www.djangosnippets.org/snippets/1034/

另请确保在Django的ContentTypes框架上查看文档: http://docs.djangoproject.com/en/dev/ref/contrib/contenttypes/ 一开始可能会有些混乱,但是ContentTypes将解决与Django ORM一起使用非抽象基类时可能会遇到的其他问题。

其他提示

好的,这有效: https://gist.github.com/348872

棘手的是这个。

class A(Top):
    pass

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

A.__new__ = staticmethod(newA)

现在,关于Python如何绑定的事情 __new__ 我也许不太明白,但是要点是:django的 ModelBase Metaclass创建一个新的类对象,而不是使用传递给其的一个对象 __new__;打电话 A_prime. 。然后它粘贴您在类定义中的所有属性 AA_prime, , 但 __new__ 无法正确绑定。

然后,当您评估 A(1), A 实际上是 A_prime 在这里,python打电话 <A.__new__>(A_prime, 1), ,它不匹配,并且会爆炸。

因此,解决方案是定义您的 __new__ A_prime 已定义。

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

现在,当我早些时候说“这起作用”时,我的意思是 这与当前SVN版本的Django中的最小对象施工测试用例隔离起作用. 。我不知道它实际上是作为模型起作用还是在QuerySet中有用。如果您实际上在生产代码中使用此信息,我将对PDXPYTHON进行公开闪电演讲,并让他们嘲笑您,直到您购买所有无麸质比萨饼。

只需在@staticmethod上 __new__ 方法。

@staticmethod
def __new__(cls, *args, **kwargs):
    print args, kwargs
    return super(License, cls).__new__(cls, *args, **kwargs)
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top