在django中获取继承的模型对象

时间:2011-03-02 23:57:23

标签: python django inheritance model

我有一个django应用程序,其中包含以下模型:

对象 A 是一个简单的对象,它从带有几个字段的Model扩展,比方说,一个特定的字段是一个名为“NAME”的字段和一个整数字段叫做“ORDER” A 是抽象的,这意味着数据库中没有 A 对象,而是...

对象 B C A 的特化,这意味着它们从 A 继承而且还添加了其他一些领域。

现在假设我需要字段 NAME 的所有对象以“Z”开头,按 ORDER 字段排序,但是我对于这些对象,也想要所有 B C 特定字段。现在我看到两种方法:

a)分别针对 B C 对象执行查询并获取两个列表,合并它们,手动订购并使用它。

b)查询以#strong>“Z”开头的名称的 A 对象“ORDER”,并使用结果查询 B C 对象带来所有剩余数据。

这两种方法听起来都非常低效,在我必须自己订购的第一种方法中,在第二种方法中,我必须多次查询数据库。

我是否缺少一种神奇的方法来获取所有 B C 对象,只需一个方法进行排序?或者至少比上面提到的更有效的方法呢?

提前致谢!

布鲁诺

4 个答案:

答案 0 :(得分:6)

如果A具体,您可以使用select_related在一个查询中执行此操作。

from django.db import connection
q = A.objects.filter(NAME__istartswith='z').order_by('ORDER').select_related('b', 'c')
for obj in q:
   obj = obj.b or obj.c or obj
   print repr(obj), obj.__dict__ # (to prove the subclass-specific attributes exist)
print "query count:", len(connection.queries)

答案 1 :(得分:1)

here回答了这个问题。

使用InheritanceManager项目中的django-model-utils

答案 2 :(得分:0)

使用“b”方法查询将允许您“引入”所有剩余数据,而无需单独查询B和C模型。您可以使用“点小写模型名称”关系。

http://docs.djangoproject.com/en/dev/topics/db/models/#multi-table-inheritance

for object in A.objects.filter(NAME__istartswith='z').order_by('ORDER'):
    if object.b:
        // do something
        pass
    elif object.c:
        // do something
        pass

您可能需要尝试除DoesNotExist异常外。我的django有点生疏了。祝好运。

答案 3 :(得分:0)

只要你在B和C上订购两个查询,就可以很容易地合并它们,而不必花费昂贵的手段:

# first define a couple of helper functions 

def next_or(iterable, other):
    try:
        return iterable.next(), None
    except StopIteration:
        return None, other

def merge(x,y,func=lambda a,b: a<=b):
    ''' merges a pair of sorted iterables '''
    xs = iter(x)
    ys = iter(y)
    a,r = next_or(xs,ys)
    b,r = next_or(ys,xs)
    while r is None:
        if func(a,b):
            yield a
            a,r = next_or(xs,ys)
        else:
            yield b
            b,r = next_or(ys,xs)
    else:
        if a is not None:
            yield a
        else:
            yield b
    for o in r:
        yield o

# now get your objects & then merge them

b_qs = B.objects.filter(NAME__startswith='Z').order_by('ORDER')
c_qs = C.objects.filter(NAME__startswith='Z').order_by('ORDER')

for obj in merge(b_qs,c_qs,lambda a,b: a.ORDER <= b.ORDER):
    print repr(obj), obj.__dict__

这种技术的优点是它适用于抽象基类。