我有一个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 对象,只需一个方法进行排序?或者至少比上面提到的更有效的方法呢?
提前致谢!
布鲁诺
答案 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回答了这个问题。
答案 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__
这种技术的优点是它适用于抽象基类。