Aller au contenu

Filtrer et trier vos données

Vous pouvez filtrer les données en utilisant les méthodes suivantes (clause sql where).

  • filter(*args, **kwargs) -> QuerySet

  • exclude(*args, **kwargs) -> QuerySet

  • get(*args, **kwargs) -> modèle

  • get_or_none(*args, **kwargs) -> Optional[Model]

  • get_or_create(_defaults: Optional[Dict[str, Any]] = None, *args, **kwargs) -> Tuple[Model, bool]

  • all(*args, **kwargs) -> List[Optional[Model]]

  • Query Set Agent pour

    • QuerysetProxy.filter(*args, **kwargs) Méthodes
    • QuerysetProxy.exclude(*args, **kwargs) Méthode
    • QuerysetProxy.get(*args, **kwargs) Méthodes
    • QuerysetProxy.get_or_none(*args, **kwargs) Méthode
    • QuerysetProxy.get_or_create(_defaults: Optional[Dict[str, Any]] = None, *args, **kwargs) Méthodes
    • QuerysetProxy.all(*args, **kwargs) Méthodes

Et triez les données en utilisant la méthode suivante (clause ordre par sql).

  • order_by(columns:Union[List, str, OrderAction]) -> QuerySet
  • Query Set Agent pour
    • QuerysetProxy.order_by(columns:Union[List, str, OrderAction]) Méthodes

Filtrer par

Filtré par

filter(*args, **kwargs) -> QuerySet

Vous permet de filtrer par n'importe quel attribut/champ de modèle et d'obtenir des instances à l'aide de filtres sur les relations FK.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
Classe Album(modèle ormar):
    ormar_config = base_ormar_config.copy()

    id: int = ormar.Integer(primary_key=True)
    name: str = ormar.String(max_length=100)
    is_best_sell: bool = ormar. booléen (default=False)

Classe Track(modèle ormar):
    ormar_config = base_ormar_config.copy()

    id: int = ormar.Integer(primary_key=True)
    Album: Optional[Album] = ormar.ForeignKey(Album)
    name: str = ormar.String(max_length=100)
    position: int = ormar.Integer()
    play_count: int = ormar.Integer(nullable=True)


track = Track.objects.filter(name="The Bird").get()
# will return a track with name equal to "The Bird"

tracks = Track.objects.filter(album__name="Fantasy").all()
# will return all tracks where the columns album name ="Fantaisie"

Filtres de style Django

Vous pouvez modifier les opérandes de filtre en utilisant des suffixes de filtre spéciaux:

  • Exact-correspond exactement à la valeur, colonne sql = * peut être écrit comme un album__nom__exact ='Malibu'
  • iexact -correspond exactement à la colonne sql =(insensible à la casse)
    • peut être écrit comme album__name__iexact='malibu'
  • Contient la colonne- sql LIKE '%%' * peut être écrit comme un album__nom__contains ="Mal"
  • icons-colonne sql LIKE '%%'(insensible à la casse)* peut être écrit comme album__name__icons ='mal'
  • dans-sql column IN (<VALUE1>, <VALUE2>, ...)* peut être écrit comme album__name__in=['Malibu', 'Barclay']
  • isnull -la colonne sql est NULL (et la colonne sql est NOT NULL)
    • peut être écrit comme album__name__isnull=True (isnotnull album__name__isnull=False)
  • gt -colonne sql>(plus grand que)* peut être écrit comme position__gt=3
  • gte -colonne sql>=(supérieur ou égal à)* peut être écrit comme position__gte=3
  • lt -colonne sql <(inférieur à)* peut être écrit comme position__lt=3
  • lte -colonne sql <=(inférieur ou égal)* peut être écrit comme position__lte=3
  • startswith -colonne sql LIKE '%' (correspondance de début exacte) * peut être écrit comme album__name__startswith='Mal'
  • istartswith - sql colonne LIKE '%'(insensible à la casse)* peut être écrit comme album__name__istartswith='mal'
  • endswith -colonne sql LIKE '%'(Exact End Match)* peut être écrit comme album__nom__endswith ="ibu"
  • iendswith -colonne sql LIKE '%'(insensible à la casse)* peut être écrit comme album__nom__iendswith ="IBU"

Quelques samples:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# sql: (product.name = 'Test' AND product.rating >= 3.0 )
Produit. objets.filter(nom ='Test', rating__gte=3.0).get()

# sql: (product.name = 'Test' AND product.rating >= 3.0 )
#       OU (categories.name IN ('Toys', 'Books'))
Produit. objets.filter(
    Ormar. ou_(
        ormar.and_(nom ='Test', rating__gte=3.0),
        catégories__name__in=['Toys', 'Books'])
    ).get()
# note: pour en savoir plus sur et_ou_lire complexe filtres section below

Filtres de style Python

  • Exact-correspond exactement à la valeur, colonne sql =
    • On peut écrire Track.album.name == 'Malibu
  • iexact -correspond exactement à la colonne sql =(insensible à la casse)
    • peut être écrit Track.album.name.iexact('malibu')
  • contient la colonne- sql LIKE '%%' *peut être écrit comme Track.album.name % 'Mal') *peut être écrit comme Track.album.name.contains('Mal')
  • icontains -colonne sql LIKE '%%'(insensible à la casse)* peut être écrit comme Track.album.name.icontains('mal')
  • dans-sql column IN (<VALUE1>, <VALUE2>, ...)*peut être écrit comme Track.album.name << ['Malibu', 'Barclay']*peut être écrit comme Track.album.name.in_(['Malibu', 'Barclay'])
  • isnull -la colonne sql est NULL (et la colonne sql est NOT NULL)* Peut être écrit comme Track.album.name>> None * peut être écrit comme Track.album.name.isnull(True) * Peut être écrit comme non nul comme Track.album.name.isnull(False) * not null peut être écrit comme ~(Track.album.name >> None) * not null peut être écrit ~(Track.album.name.isnull(True))
  • gt -colonne sql>(plus grand que)* peut être écrit comme Track.album.name> 3
  • gte - sql colonne>=(supérieur ou égal à)* peut être écrit comme Track.album.name>= 3
  • lt - sql colonne <(en dessous)* peut être écrit comme Track.album.name < 3
  • lte - sql colonne <=(inférieur à égal)* peut être écrit comme Track.album.name <= 3
  • startswith - sql colonne LIKE '%'(correspondance de début exacte)* peut être écrit comme Track.album.name.startswith('Mal')
  • istartswith - sql colonne LIKE '%'(insensible à la casse)* peut être écrit comme Track.album.name.istartswith('mal')
  • endswith - sql colonne LIKE '%'(correspondance exacte de fin)* peut être écrit comme Track.album.name.endswith('ibu')
  • iendswith - sql colonne LIKE '%'(insensible à la casse)* peut être écrit comme Track.album.name.iendswith('IBU')

Quelques samples:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# sql: (product.name = 'Test' AND product.rating >= 3.0 )
Produit. objets.filter(
    (Product.name == 'Test') & (Product.rating >= 3.0)
).get()

# sql: (product.name = 'Test' AND product.rating >= 3.0 )
#       OU (categories.name IN ('Toys', 'Books'))
Produit. objets.filter(
        (Product.name == 'Test') & (Product.rating >= 3.0))|
        (Product.categories.name <<['Toys', 'Books'])
    .get() pour

!!!Remarque Toutes les méthodes qui ne renvoient pas de lignes renvoient explicitement une instance QuerySet afin que vous puissiez les lier ensemble.

1
2
3
Ainsi, les opérations comme `filter()`,`select_related()`,`limit()` et `offset()` etc. peuvent être chainées.

Quelque chose comme `Track.object.select_related("album").filter(album__name="Malibu").offset(1).limit(1).all()`

Attention!!!Notez que vous n'avez pas besoin de spécifier le caractère générique % dans les filtres contains et autres, il est ajouté pour vous. si vous incluez % dans la valeur de recherche, il sera échappé et traité comme un signe de pourcentage littéral dans le texte.

Exclusion de

exclude(*args, **kwargs) -> QuerySet

Fonctionne exactement de la même manière que le filtre, et tous les modificateurs (suffixes) sont les mêmes, mais renvoie la condition not.

Donc, si vous utilisez filter(name='John'), qui est égal à where name = 'John' en SQL, except(name='John') est égal à where name <> 'John'

Notez que toutes les conditions sont jointes, donc si vous passez plusieurs valeurs, cela devient l'union des conditions.

L'exclusion (nom ='John', âge>=35) devient where not (name='John' and age>=35)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
Classe Album(modèle ormar):
    ormar_config = base_ormar_config.copy()

    id: int = ormar.Integer(primary_key=True)
    nom: str = ormar.String(max_length=100)
    is_best_sell: bool = ormar. booléen (default=False)

Classe Track(modèle ormar):
    ormar_config = base_ormar_config.copy()

    id: int = ormar.Integer(primary_key=True)
    Album: Optional[Album] = ormar.ForeignKey(Album)
    name: str = ormar.String(max_length=100)
    position: int = ormar.Integer()
    play_count: int = ormar.Integer(nullable=True)


notes = await Track.objects.exclude(position_gt=3).all()
# returns tous les tracks avec position < 3

Filtres complexes (y compris OR)

Par défaut, les méthodes filter() et except() combinent les options de filtre fournies avec la condition AND, de sorte que filter(name="John", age__gt=30) se traduit par WHERE name = 'John' AND age > 30.

Parfois, il est utile d'interroger une base de données avec des conditions qui ne devraient pas être appliquées conjointement, comme WHERE name = 'John' OR age > 30, ou de construire une requête complexe where sur laquelle vous souhaitez avoir plus de contrôle-après tout,WHERE (name = 'John' OR age > 30) and city='New York' est complètement différent de WHERE name = 'John' OR (age > 30 and city='New York').

Pour construire des conditions OR et imbriquées, ormar fournit deux fonctions qui peuvent être utilisées dans filter() et except() dans QuerySet et QuerysetProxy.

!!!Notez que vous pouvez fournir ces méthodes dans toute autre méthode qui accepte*args (par exemple get() ou all()).

Les appels à or_et à_peuvent être imbriqués les uns dans les autres ou combinés avec des arguments de mots-clés. comme cela semble plus compliqué qu 'il ne l'est, regardons quelques exemples.

Étant donné un tel modèle d'exemple:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
base_ormar_config = ormar.ormarConfig(
    database=databases.Database(DATABASE_URL),
    metadata=sqlalchemy.MetaData(),
)


Auteur de classe (modèle ormar):
    ormar_config = base_ormar_config.copy()

    id: int = ormar.Integer(primary_key=True)
    nom: str = ormar.String(max_length=100)


Classe Book(modèle ormar):
    ormar_config = base_ormar_config.copy()

    id: int = ormar.Integer(primary_key=True)
    author: Optional[Author] = ormar.ForeignKey(Author)
    title: str = ormar.String(max_length=100)
    année: int = ormar.Integer(nullable=True)

Créons quelques exemples de données:

1
2
3
4
5
6
7
tolkien = await Author(nom ="J.R.R. Tolkien").save()
await Book(author=tolkien, title="The Hobbit", année =1933).save()
await Book(author=tolkien, title="Le Seigneur des Anneaux", année =1955).save()
await Book(author=tolkien, title="Le Silmarillion", année =1977).save()
sapkowski = await Author(nom ="Andrzej Sapkowski").save()
await Book(author=sapkowski, title="The Witcher", year=1990).save()
await Book(author=sapkowski, title="The Tower of Fools", année =2002).save()

Nous pouvons construire quelques exemples de requêtes complexes:

Choisissons un livre de Tolkien ou un livre écrit après 1970

sql: WHERE ( authors.name = 'J.R.R. Tolkien' OR books.year > 1970 )

Le style Django

1
2
3
4
5
6
Livres = (
    await Book.objects.select_related("author")
    .filter(ormar.or_(author__name="J.R.R. Tolkien", année__gt=1970))
    . tout ()
)
assert len(livres) == 5

Styles de Python

1
2
3
4
5
6
Livres = (
    await Book.objects.select_related("author")
    .filter((Book.author.name=="J.R.R. Tolkien")|(Année du livre> 1970)
    . tout ()
)
assert len(livres) == 5

Choisissons maintenant les livres écrits par Tolkien après 1960 ou avant 1940.

Sql: WHERE ( books.year > 1960 OR books.year < 1940 ) AND authors.name = 'J.R.R. Tolkien'

Le style Django

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# OPTION 1 - Split et dans un appel séparé
Livres = (
    await Book.objects.select_related("author")
    .filter(omar.or_(year__gt=1960, year__lt=1940))
    .filter(author__name="J.R.R. Tolkien")
    . tout ()
)
assert len(livres) == 2

# OPTION 2 -Tous en un
Livres = (
    await Book.objects.select_related("author")
    . filtre (
        Ormar. et_(
            ormar.or_(année__gt=1960, année__lt=1940),
            author__name="J.R.R. Tolkien",
        )
    )
    . tout ()
)

assert len(livres) == 2
assert books[0].title == "Le Hobbit"
assert books[1].title == "Le Silmarillion"

Styles de Python

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
Livres = (
    await Book.objects.select_related("author")
    .filter((Book.year > 1960))|(Livre. année < 1940)
    .filter(Book.author.name == "J.R.R. Tolkien")
    . tout ()
)
assert len(livres) == 2

# OPTION 2 -Tous en un
Livres = (
    await Book.objects.select_related("author")
    .filter(
        (
            (Année du livre> 1960)|(Année du livre < 1940)
        ) & (Book.author.name == "J.R.R. Tolkien")
    )
    . tout ()
)

assert len(livres) == 2
assert books[0].title == "Le Hobbit"
assert books[1].title == "Le Silmarillion"

Les livres de Sapkowski avant 2000 ou ceux de Tolkien après 1960

Sql: WHERE ( ( books.year > 1960 AND authors.name = 'J.R.R. Tolkien' ) OR ( books.year < 2000 AND authors.name = 'Andrzej Sapkowski' ) )

Le style Django

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
Livres = (
    await Book.objects.select_related("author")
    .filter(
        Ormar. ou_(
            ormar.and_(année__gt=1960, author__name="J.R.R. Tolkien"),
            ormar.and_(année__lt=2000, author__name="Andrzej Sapkowski"),
        )
    )
    . tout ()
)
assert len(livres) == 2

Styles de Python

1
2
3
4
5
6
7
8
9
Livres = (
    await Book.objects.select_related("author")
    .filter(    
        ((Book.year > 1960) & (Book.author.name == "J.R.R. Tolkien"))|
        ((Book.year < 2000) & (Book.author.name == "Andrzej Sapkowski"))
    )
    . tout ()
)
assert len(livres) == 2

Bien sûr, ces fonctions peuvent avoir plus de deux conditions, donc si nous voulons des livres contenant des « hobbits »:

Sql: WHERE ( ( books.year > 1960 AND authors.name = 'J.R.R. Tolkien' ) OR ( books.year < 2000 AND os0cec_authors.name = 'Andrzej Sapkowski' ) OR books.title LIKE '%hobbit%' )

Le style Django

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
Livres = (
    await Book.objects.select_related("author")
    . filtre (
        Ormar. ou_(
            ormar.and_(année__gt=1960, author__name="J.R.R. Tolkien"),
            ormar.and_(année__lt=2000, author__name="Andrzej Sapkowski"),
            title__icontains="hobbit",
        )
    )
    . tout ()
)

Styles de Python

1
2
3
4
5
6
7
8
9
Livres = (
    await Book.objects.select_related("author")
    .filter(    
        ((Book.year > 1960) & (Book.author.name == "J.R.R. Tolkien"))|
        ((Book.year < 2000) & (Book.author.name == "Andrzej Sapkowski"))|
        (Book.title. icons ("hobbit"))
    )
    . tout ()
)

Si vous le souhaitez ou si vous en avez besoin, vous pouvez imbriquer des conditions plus profondes selon vos besoins, par exemple en implémentant des requêtes telles que:

Sql:

1
2
3
WHERE ( ( (livres. année> 1960 OR livres. année < 1940 ))
ET authors.name ="J.R.R. Tolkien") OU
(Livres. année < 2000 ET authors.name = 'Andrzej Sapkowski' )

Vous pouvez structurer une requête comme suit:

Le style Django

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
Livres = (
    await Book.objects.select_related("author")
    . filtre (
        ormar. ou_(
            Ormar. et_(
                ormar.or_(année__gt=1960, année__lt=1940),
                author__name="J.R.R. Tolkien",
            ),
            ormar.and_(année__lt=2000, author__name="Andrzej Sapkowski"),
        )
    )
    . tout ()
)
assert len(livres) == 3
assert books[0].title == "Le Hobbit"
assert books[1].title == "The Silmarillion"
assert books[2].title == "The Witcher"

Styles de Python

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
Livres = (
    await Book.objects.select_related("author")
    .filter(        
        (
            (
            (Année du livre> 1960)|
            (Année du livre < 1940)
            ) &
            (Book.author.name == "J.R.R. Tolkien")
        ) |
        (
            (Book.year < 2000) &
            (Book.author.name == "Andrzej Sapkowski")
        )
    )
    . tout ()
)
assert len(livres) == 3
assert books[0].title == "Le Hobbit"
assert books[1].title == "The Silmarillion"
assert books[2].title == "The Witcher"

Maintenant, vous devriez déjà comprendre comment fonctionnent ormar.or_et ormar.and_, bien sûr, vous pouvez les lier à n'importe quelle autre méthode de l'ensemble de requêtes, donc dans l'exemple, une requête parfaitement valide pourrait ressembler à ceci:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
Livres = (
    await Book.objects.select_related("author")
    .filter(omar.or_(année__gt=1980, author__name="Andrzej Sapkowski"))
    .filter(title__startswith="The")
    Limité (1)
    .offset(1)
    .order_by(«-id »)
    . tout ()
)
assert len(livres) == 1
assert books[0].title == "The Witcher"

Il en va de même pour les liens et les imbrications de style python.

Le style Django

Notez qu 'avec le style django, vous ne pouvez pas fournir le même argument de mot-clé plusieurs fois, donc les requêtes comme filter(ormar.or_(name='Jack', name='John')) ne sont pas autorisées. si vous voulez vérifier plusieurs valeurs dans la même colonne, utilisez simplement l'opérateur in:filter(name__in=['Jack','John']).

Si un seul argument est passé à la fonction or_ou and_, il est simplement entouré de parenthèses et n'a aucun effet sur la requête réelle, donc au final les 3 requêtes sont identiques:

1
2
3
await Book.objects.filter(title ='The Hobbit').get()
await Book.objects.filter(ormar.or_(title ='The Hobbit')).get()
await Book.objects.filter(ormar.and_(title ='The Hobbit')).get()

Note!!!Notez que les requêtes or_et and_auront WHERE (title='The Hobbit'), mais les parenthèses sont redondantes et n'ont aucun effet réel.

Vous pouvez utiliser cette fonctionnalité si vous devez utiliser le même nom de champ deux fois. rappelez-vous que vous ne pouvez pas passer le même argument de mot-clé deux fois à une fonction, alors comment interroger WHERE (authors.name LIKE '%tolkien%') OR (authors.name LIKE '%sapkowski%')) dans l'exemple?

Vous ne pouvez pas faire ceci:

1
2
3
4
5
6
7
8
Livres = (
    await Book.objects.select_related("author")
        .filter(ormar.or_(
        author__name__icontains="tolkien",
        author__name__icontains="sapkowski" # you cannot use same keyword twice in or_!
    ))                                      # python erreur de syntaxe
        . tout ()
)

Mais voici ce que vous pouvez faire:

1
2
3
4
5
6
7
8
9
Livres = (
    await Book.objects.select_related("author")
        .filter(ormar.or_(
        ormar.and_(author__name__icontains="tolkien"), # one argument == juste écrit dans ()
        ormar.and_(author__name__icontains="sapkowski")
    ))
        . tout ()
)
assert len(livres) == 5

Styles de Python

Notez qu 'avec le style python, vous pouvez utiliser le même champ autant de fois que vous le souhaitez.

1
2
3
4
5
6
7
8
Livres = (
    await Book.objects.select_related("author")
        . filtre (
        (Book.author.name.icontains("tolkien"))|
        (Book.author.name.icontains("sapkowski"))
    ))                                      
        . tout ()
)

obtenir

obtenir ()*args, **kwargs) -> Modèles

Obtient la première ligne de la base de données qui répond aux critères de configuration de kwargs.

Lorsque des args et/ou des kwargs sont passés, c'est un raccourci équivalent à un appel à filter(*args, **kwargs).get()

!!!Tip Pour en savoir plus sur les filtres, allez à Filtres.

1
Pour en savoir plus sur `get` Aller à [lire/obtenir](../read/#get)

Acquisition ou non

Exactement comme get décrit ci-dessus, mais si aucun enregistrement de base de données correspondant à la condition n'est trouvé, None est renvoyé au lieu de lever une exception.

Obtenir ou créer

get_or_create(_defaults: Optional[Dict[str, Any]] = None, *args, **kwargs) -> Tuple[Model, bool]

Créer et obtenir une combinaison de méthodes.

Lorsque des args et/ou des kwargs sont passés, c'est l'équivalent d'un raccourci pour un appel. filter(*args, **kwargs).get_or_create()

!!!Tip Pour en savoir plus sur les filtres, allez à Filtres.

1
Pour en savoir plus sur `get_or_create` Go to [read/get_or_create](../read/#get_or_create)

Attention!!!Lorsqu 'un élément donné n'existe pas, vous devez passer kwargs pour tous les champs obligatoires du modèle, y compris, mais sans s'y limiter, la colonne Primary_key (sauf si elle est incrémentée automatiquement).

Tous les

all(*args, **kwargs) -> List[Optional["Model"]]

Pour les options de filtre définies, renvoie toutes les lignes de la base de données pour un modèle donné.

Lorsqu 'un kwargs est passé, c'est l'équivalent de l'appel filter(*args, **kwargs) raccourci vers.all()

!!!Tip Pour en savoir plus sur les filtres, allez à Filtres.

1
Pour lire plus sur `all` Aller à [read/tout](../read/#all)

La méthode QuerysetProxy

Lorsque vous accédez directement au champ ManyToMany associé ainsi qu'à la clé ReverseForeignKey, une liste des modèles associés est renvoyée.

Mais en même temps, il expose un sous-ensemble de l'API QuerySet, de sorte que vous pouvez filtrer, créer, sélectionner des modèles pertinents, etc. directement à partir du modèle parent.

Filtré par

Exactement la même fonction de filtrage que ci-dessus, mais vous permet de filtrer les objets pertinents de l'autre côté de la relation.

!!!conseil Pour en savoir plus sur Querysetproxy, visitez la section Querysetproxy

Exclusion de

Exactement la même fonctionnalité d'exclusion que ci-dessus, mais vous permet de filtrer les objets pertinents de l'autre côté de la relation.

!!!conseil Pour en savoir plus sur Querysetproxy, visitez la section Querysetproxy

obtenir

Exactement la même chose que la fonction get ci-dessus, mais vous permet de filtrer les objets pertinents de l'autre côté de la relation.

!!!conseil Pour en savoir plus sur Querysetproxy, visitez la section Querysetproxy

Acquisition ou pas

Exactement comme get décrit ci-dessus, mais si aucun enregistrement de base de données correspondant à la condition n'est trouvé, None est renvoyé au lieu de lever une exception.

Obtenir ou créer

Exactement la même chose que la fonction get_or_create ci-dessus, mais vous permet de filtrer les objets pertinents de l'autre côté de la relation.

!!!conseil Pour en savoir plus sur Querysetproxy, visitez la section Querysetproxy

Tous les

Exactement la même chose que tout ce qui précède, mais vous permet de filtrer les objets pertinents de l'autre côté de la relation.

!!!conseil Pour en savoir plus sur Querysetproxy, visitez la section Querysetproxy

Ordre de

Base de l'ordre

order_by(columns: Union[List, str, OrderAction]) -> QuerySet

Avec order_by(), vous pouvez trier les résultats de la base de données en fonction des champs que vous avez sélectionnés.

Vous pouvez fournir une chaîne avec un nom de champ ou une liste de chaînes avec différents champs.

Le tri dans sql sera appliqué dans l'ordre des noms que vous avez fournis dans order_by.

!!!Tip Par défaut, si vous ne fournissez pas de tri ou triez explicitement par toutes les clés primaires

!!!Avertissement Si vous triez par modèle imbriqué, les lignes résultantes ne seront pas triées par modèle principal, sinon mar fusionnera ces sous-lignes dans un modèle principal.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
Sample raw database rows result (sort by child model desc):
```
MODEL: 1 - Child Model - 3
MODEL: 2 - Child Model - 2
MODEL: 1 - Child Model - 1
```

Le résultat sera en 2 lignes de résultat:
```
MODEL: 1 - Child Models: [3, 1] # encountered first in result, all children rows combined
MODEL: 2 - Child Models: [2]
```

Le modèle principal ne sera jamais dupliqué dans le résultat

Un exemple de modèle donné est le suivant:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import asyncio

import databases
import ormar
import sqlalchemy
from examples import create_drop_database

DATABASE_URL = "sqlite:///test.db"

ormar_base_config = ormar.OrmarConfig(
    database=databases.Database(DATABASE_URL),
    metadata=sqlalchemy.MetaData(),
)


class Owner(ormar.Model):
    ormar_config = ormar_base_config.copy(tablename="owners")

    id: int = ormar.Integer(primary_key=True)
    name: str = ormar.String(max_length=100)


class Toy(ormar.Model):
    ormar_config = ormar_base_config.copy(tablename="toys")

    id: int = ormar.Integer(primary_key=True)
    name: str = ormar.String(max_length=100)
    owner: Owner = ormar.ForeignKey(Owner)


@create_drop_database(base_config=ormar_base_config)
async def run_query():
    # build some sample data
    aphrodite = await Owner.objects.create(name="Aphrodite")
    hermes = await Owner.objects.create(name="Hermes")
    zeus = await Owner.objects.create(name="Zeus")

    await Toy.objects.create(name="Toy 4", owner=zeus)
    await Toy.objects.create(name="Toy 5", owner=hermes)
    await Toy.objects.create(name="Toy 2", owner=aphrodite)
    await Toy.objects.create(name="Toy 1", owner=zeus)
    await Toy.objects.create(name="Toy 3", owner=aphrodite)
    await Toy.objects.create(name="Toy 6", owner=hermes)


asyncio.run(run_query())

Pour trier par champ de modèle principal, fournissez simplement le nom du champ

Le style Django

1
2
3
4
5
6
toys = await Toy.objects.select_related("owner").order_by("name").all()
assert [x.name.replace("Toy ", ") for x in toys]= [
    str(x + 1) pour x dans la plage (6)
]
assert toys[0].owner == zeus
assert toys[1].owner == aphrodite

Styles de Python

1
2
3
4
5
6
toys = await Toy.objects.select_related("owner").order_by(Toy.name.asc()).all()
assert [x.name.replace("Toy ", ") for x in toys] == [
    str(x + 1) pour x dans la gamme (6)
]
assert toys[0].owner == zeus
assert toys[1].owner == aphrodite

Pour trier les modèles imbriqués, séparez les noms de champs avec dunder '__'.

De cette façon, vous pouvez trier tous les types de relation->ForeignKey, FK virtuelle inversée et les champs ManyToMany.

Le style Django

1
2
3
4
toys = await Toy.objects.select_related("owner").order_by("owner__name").all()
assert toys[0]. owner.name == toys[1].owner.name == "Aphrodite"
assert toys[2]. owner.name == toys[3].owner.name == "Hermes"
assert toys[4]. owner.name == toys[5].owner.name == "Zeus"

Styles de Python

1
2
3
4
toys = await Toy.objects.select_related("owner").order_by(Toy.owner.name.asc()).all()
assert toys[0]. owner.name == toys[1].owner.name == "Aphrodite"
assert toys[2]. owner.name == toys[3].owner.name == "Hermes"
assert toys[4]. owner.name == toys[5].owner.name == "Zeus"

Pour trier par ordre décroissant, fournissez un trait d'union avant le nom du champ

Le style Django

1
2
3
4
5
6
7
8
propriétaire = (
    await Owner.objects.select_related("toys")
        .order_by("-toys__name")
        .filter(nom ="Zeus")
        .get()
)
assert owner.toys[0].name == "Toy 4"
assert owner.toys[1].name == "Toy 1"

Styles de Python

1
2
3
4
5
6
7
8
propriétaire = (
    await Owner.objects.select_related("toys")
        .order_by(Owner.toys.name.desc()))
        .filter(Owner.name == "Zeus")
        .get() par
)
assert owner.toys[0].name == "Toy 4"
assert owner.toys[1].name == "Toy 1"

!!!Remarque Toutes les méthodes qui ne renvoient pas de lignes renvoient explicitement une instance QuerySet afin que vous puissiez les lier ensemble.

1
2
3
Ainsi, les opérations comme `filter()`,`select_related()`,`limit()` et `offset()` etc. peuvent être enchaînées.

Quelque chose comme `Track.object.select_related("album").filter(album__name="Malibu").offset(1).limit(1).all()`

Le tri par défaut dans Ormar

Comme il n'y a aucune garantie quant à l'ordre des lignes dans la base de données, ormar émet toujours une clause order by sql pour chaque requête (partielle), même si vous ne fournissez pas vous-même l'ordre.

Par défaut, lorsqu 'une base de données est interrogée avec un modèle donné, les modèles sont triés par ordre croissant de colonne Primary_key. Si vous souhaitez modifier le comportement par défaut, vous pouvez le faire en fournissant le paramètre orders_by à ormar_config.

!!! Astuce Pour en savoir plus sur l'ordre de tri des modèles, visitez la section Modèles de la documentation

Par défaut, les relations suivent le même ordre, mais vous pouvez modifier l'ordre dans lequel les modèles associés sont chargés lors d'une requête en fournissant les paramètres orders_by et related_orders_by à la relation.

!!! Astuce Pour en savoir plus sur l'ordre de tri des modèles, visitez la section Relations de la documentation

La clause order_by est appliquée dans l'ordre suivant:

  • Passer explicitement l'appel order_by() dans une requête
  • Les relations passent par orders_by et related_orders_by (si elles existent)
  • ormar_config objet du modèle orders_by
  • Primary_key colonne ascendante du modèle (backup, utilisé si rien de ce qui précède n'est fourni)

Appliquez les commandes d'une seule source à chaque modèle (de sorte que vous pouvez toujours les remplacer dans une seule requête).

Cela signifie que si vous fournissez explicitement order_by pour le modèle dans la requête, la relation et l'ordre de tri du modèle seront ignorés.

Si vous fournissez une relation, le tri des modèles est ignoré.

Enfin, si vous en fournissez un pour le modèle, la valeur par défaut de primary_key sera ignorée.

La méthode QuerysetProxy

Lorsque vous accédez directement au champ ManyToMany associé, ainsi qu'à la clé ReverseForeignKey, une liste des modèles associés est renvoyée.

Mais en même temps, il expose un sous-ensemble de l'API QuerySet, de sorte que vous pouvez filtrer, créer, sélectionner des modèles pertinents, etc. directement à partir du modèle parent.

Base de l'ordre

Exactement comme la fonction order_by ci-dessus, mais vous permet de trier les objets liés de l'autre côté de la relation.

!!!conseil Pour en savoir plus sur Querysetproxy, visitez la section Querysetproxy