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

发布于 2024-10-19 21:48:28 字数 963 浏览 3 评论 0原文

我有一个具有以下模型的 Django 应用程序:

对象 A 是一个从模型扩展而来的简单对象,具有几个字段,比方说,一个特定的字段是一个名为 "NAME"< 的 char 字段/strong> 和一个名为 “ORDER” 的整数字段。 A 是抽象的,意味着数据库中没有 A 对象,而是...

对象 BC > 是 A 的特化,这意味着它们继承自 A 并添加了一些其他字段。

现在假设我需要字段 NAME 以字母 "Z" 开头的所有对象,并按 ORDER 字段排序,但我想要所有这些对象也有 BC 特定字段。现在我看到两种方法:

a)分别对 BC 对象进行查询,并获取两个列表,合并它们,手动排序并使用它。

b) 查询A对象以查找以“Z”开头且按“ORDER”排序的名称,并使用结果查询B 和 C 对象带来所有剩余的数据。

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

我是否缺少一种神奇的方法来获取所有 BC 对象,并用一个方法排序?或者至少是比上述两种方法更有效的方法?

提前致谢!

布鲁诺

I have a django application with the following model:

Object A is a simple object extending from Model with a few fields, and let's say, a particular one is a char field called "NAME" and an Integer field called "ORDER". A is abstract, meaning there are no A objects in the database, but instead...

Objects B and C are specializations of A, meaning they inherit from A and they add some other fields.

Now suppose I need all the objects whose field NAME start with the letter "Z", ordered by the ORDER field, but I want all the B and C-specific fields too for those objects. Now I see 2 approaches:

a) Do the queries individually for B and C objects and fetch two lists, merge them, order manually and work with that.

b) Query A objects for names starting with "Z" ordered by "ORDER" and with the result query the B and C objects to bring all the remaining data.

Both approaches sound highly inefficient, in the first one I have to order them myself, in the second one I have to query the database multiple times.

Is there a magical way I'm missing to fetch all B and C objects, ordered in one single method? Or at least a more efficient way to do this than the both mentioned?

Thanks in Advance!

Bruno

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

望她远 2024-10-26 21:48:28

如果 A 可以具体化,那么您可以使用 select_lated 在一个查询中完成这一切。

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)

If A can be concrete, you can do this all in one query using 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)
魔法唧唧 2024-10-26 21:48:28

使用“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 有点生疏了。祝你好运。

Querying using your "b" method, will allow for you to "bring in" all the remaining data without querying your B and C models separately. You can use the "dot lowercase model name" relation.

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

You may need to try and except DoesNotExist exceptions. I'm a bit rusty with my django. Good Luck.

走过海棠暮 2024-10-26 21:48:28

此处回答了这个问题。

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

This question was answered here.

Use the InheritanceManager from the django-model-utils project.

南街女流氓 2024-10-26 21:48:28

只要您对 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__

这种技术的优点是它可以与抽象基类一起使用。

So long as you order both queries on B and C, it is fairly easy to merge them without having to do an expensive resort:

# 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__

The advantage of this technique is it works with an abstract base class.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文