具有集成查询的子类django模型 [英] Subclassed django models with integrated querysets

查看:120
本文介绍了具有集成查询的子类django模型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

像在这个问题,除了我想要能够拥有返回混合物体的查询器:

Like in this question, except I want to be able to have querysets that return a mixed body of objects:

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

我想到我不能只设置 Product.Meta.abstract 为true或以其他方式将OR组合在一起,查找不同对象的查询。好的,但这些都是一个普通类的子类,所以如果我把他们的超类作为非抽象的,我应该很高兴,只要我能让它的经理返回正确的类的对象。 django中的查询代码执行其操作,只需调用Product()。听起来很简单,除非它覆盖了 Product .__ new __ ,我猜是因为 __ metaclass __ 模型...这里的非django代码的行为几乎是我想要的:

I figured out that I can't just set Product.Meta.abstract to true or otherwise just OR together querysets of differing objects. Fine, but these are all subclasses of a common class, so if I leave their superclass as non-abstract I should be happy, so long as I can get its manager to return objects of the proper class. The query code in django does its thing, and just makes calls to Product(). Sounds easy enough, except it blows up when I override Product.__new__, I'm guessing because of the __metaclass__ in Model... Here's non-django code that behaves pretty much how I want it:

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 而不是对象

But that fails if I inherit from django.db.models.Model instead of 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)顶部 super(A,A ),并且所有上述结合传递 cls 作为 __ new __ ,都无济于事。为什么这么踢我这么难?我必须弄清楚django的元类才能解决这个问题,还是有更好的方法来完成目标?

Which is a notably crappy backtrace; I can't step into the frame of my __new__ code in the debugger, either. I have variously tried super(A, cls), Top, super(A, A), and all of the above in combination with passing cls in as the first argument to __new__, all to no avail. Why is this kicking me so hard? Do I have to figure out django's metaclasses to be able to fix this or is there a better way to accomplish my ends?

推荐答案

基本上你想要做的是返回不同的子类,同时查询一个共享的基类。那就是:你想要叶子类。检查此代码段以获取解决方案: http://www.djangosnippets.org/snippets/1034/

Basically what you're trying to do is to return the different child classes, while querying a shared base class. That is: you want the leaf classes. Check this snippet for a solution: http://www.djangosnippets.org/snippets/1034/

还要查看Django的Contenttypes框架上的文档: http://docs.djangoproject.com/en/dev/ref/contrib/contenttypes/ 起初可能有点混乱,但Contenttypes会解决在Django的ORM中使用非抽象基类时可能遇到的其他问题。

Also be sure to check out the docs on Django's Contenttypes framework: http://docs.djangoproject.com/en/dev/ref/contrib/contenttypes/ It can be a bit confusing at first, but Contenttypes will solve additional problems you'll probably face when using non-abstract base classes with Django's ORM.

这篇关于具有集成查询的子类django模型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆