Fetching inherited model objects in django

后端 未结 4 803
南方客
南方客 2021-01-02 15:50

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 particul

相关标签:
4条回答
  • 2021-01-02 16:18

    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.

    0 讨论(0)
  • 2021-01-02 16:20

    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)
    
    0 讨论(0)
  • 2021-01-02 16:21

    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.

    0 讨论(0)
  • 2021-01-02 16:23

    This question was answered here.

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

    0 讨论(0)
提交回复
热议问题