sql - requete - django update model



En utilisant django comment puis-je combiner deux requêtes de modèles séparés en une seule requête? (2)

Dans mon cas spécifique, j'ai deux sortes de «messages» dont j'ai besoin pour me remettre en question et paginer.

Oublions les détails, et disons juste que le premier type est dans un modèle appelé Msg1 et l'autre s'appelle Msg2

Les champs de ces deux modèles sont complètement différents, les seuls champs communs aux deux modèles sont "date" et "title" (et bien sûr, id).

Je peux obtenir Msg1.objects.all() et Msg2.objects.all() mais puis-je combiner ces deux requêtes dans une requête, le trier par date et le paginer?

J'ai besoin de préserver la nature paresseuse de la requête.

La solution triviale consiste à list(query) deux requêtes et à les combiner dans une liste python. mais c'est inefficace pour des raisons évidentes.

J'ai regardé à travers les références django sur les modèles et dp-api, mais il ne semble pas qu'il y ait un moyen de combiner des requêtes de différents modèles / tables en une seule.

https://code.i-harness.com


"combiner ces deux requêtes en une requête, le trier par date, et le paginer?"

  1. C'est le syndicat SQL. Quittez l'ORM Django et utilisez une union SQL. Ce n'est pas génialement rapide car SQL doit créer un résultat temporaire, qu'il trie.

  2. Créez le résultat temporaire, qui peut être trié. Étant donné qu'une liste a une méthode de tri, vous devrez fusionner les deux résultats en une seule liste.

  3. Ecrivez un algorithme de fusion qui accepte deux ensembles de requêtes, en paginant les résultats.

Modifier. Voici un algorithme de fusion.

def merge( qs1, qs2 ):
    iqs1= iter(qs1)
    iqs2= iter(qs2)
    k1= iqs1.next()
    k2= iqs2.next()
    k1_data, k2_data = True, True
    while k1_data or k2_data:
        if not k2_data:
            yield k1
            try:
                k1= iqs1.next()
            except StopIteration:
                k1_data= False
        elif not k1_data:
            yield k2
            try:
                k2= iqs2.next()
            except StopIteration:
                k2_data= False
        elif k1.key <= k2.key:
            yield k1
            try:
                k1= iqs1.next()
            except StopIteration:
                k1_data= False
        elif k2.key < k1.key: # or define __cmp__.
            yield k2
            try:
                k2= iqs2.next()
            except StopIteration:
                k2_data= False
        else:
            raise Exception( "Wow..." )

Vous pouvez plier en pagination:

def paginate( qs1, qs2, start=0, size=20 ):
    count= 0
    for row in merge( qs1, qs2 ):
        if start <= count < start+size:
            yield row
        count += 1
        if count == start+size:
            break

Je suggère que vous utilisiez l'héritage du modèle .

Créez un modèle de base contenant la date et le titre. Sous-classe Msg1 et Msg2 désactiver comme décrit. Faites toutes vos requêtes (pour remplir une page) en utilisant le modèle de base, puis passez au type dérivé au dernier moment.

Ce qui est vraiment génial avec l'héritage, c'est que django vous permet ensuite d'utiliser le modèle de base dans des clés étrangères d'autres modèles, ce qui vous permet de rendre votre application plus flexible. Sous le capot, il ne s'agit que d'une table pour le modèle de base avec une table par sous-modèle contenant des clés un-à-un.





django-models