Recuperando objetos de modelo heredados en django

Tengo una aplicación django con el siguiente modelo:

El objeto A es un objeto simple que se extiende desde el modelo con algunos campos, y digamos, uno en particular es un campo de caracteres llamado “NOMBRE” y un campo de números enteros llamado “ORDEN” . A es abstracto, lo que significa que no hay objetos A en la base de datos, sino que …

Los objetos B y C son especializaciones de A , lo que significa que heredan de A y agregan algunos otros campos.

Ahora suponga que necesito todos los objetos cuyo campo NOMBRE comience con la letra “Z” , ordenados por el campo ORDEN , pero quiero todos los campos específicos de B y C también para esos objetos. Ahora veo 2 enfoques:

a) Haga las consultas individualmente para los objetos B y C y obtenga dos listas, combínelas, ordene manualmente y trabaje con eso.

b) Consulta los objetos A para nombres que comiencen con “Z” ordenados por “ORDEN” y con el resultado consulta los objetos B y C para traer todos los datos restantes.

Ambos enfoques suenan altamente ineficientes, en el primero tengo que ordenarlos yo mismo, en el segundo tengo que consultar la base de datos varias veces.

¿Hay alguna forma mágica en la que no esté buscando todos los objetos B y C , ordenados en un solo método? ¿O al menos una forma más eficiente de hacer esto que las dos mencionadas?

¡Gracias por adelantado!

Bruno

Si A puede ser concreto, puede hacerlo todo en una consulta utilizando 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) 

Consultar utilizando su método “b” le permitirá “traer” todos los datos restantes sin consultar sus modelos B y C por separado. Puede utilizar la relación “punto nombre de minúscula”.

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 

Es posible que deba probar y exceptuar las excepciones de DoesNotExist. Estoy un poco oxidado con mi django. Buena suerte.

Mientras ordene ambas consultas en B y C, es bastante fácil fusionarlas sin tener que hacer un recurso costoso:

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

La ventaja de esta técnica es que funciona con una clase base abstracta.

Esta pregunta fue respondida aquí .

Use el Administrador de herencia del proyecto django-model-utils .