425 votes

Comment puis-je faire un filtre OU dans une requête Django ?

Je veux pouvoir lister les éléments ajoutés par un utilisateur (ils sont répertoriés comme créateur) ou les éléments qui ont été approuvés.

Donc, je dois essentiellement sélectionner:

item.creator = propriétaire or item.moderated = False

Comment puis-je faire cela en Django? (de préférence avec un filtre ou un queryset).

11voto

Furkan Siddiqui Points 662

Plusieurs façons de le faire.

1. En utilisant directement l'opérateur pipe |.

from django.db.models import Q

Items.objects.filter(Q(field1=value) | Q(field2=value))

2. En utilisant la méthode __or__.

Items.objects.filter(Q(field1=value).__or__(field2=value))

3. En modifiant l'opération par défaut. (Faites attention à réinitialiser le comportement par défaut)

Q.default = Q.OR # Non recommandé (Q.AND est le comportement par défaut)
Items.objects.filter(Q(field1=value, field2=value))
Q.default = Q.AND # Réinitialiser après utilisation.

4. En utilisant l'argument de classe _connector de Q.

logic = Q(field1=value, field2=value, field3=value, _connector=Q.OR)
Item.objects.filter(logic)

Snapshot de l'implémentation de Q

class Q(tree.Node):
    """
    Encapsule les filtres comme des objets qui peuvent ensuite être combinés logiquement (en utilisant
    `&` et `|`).
    """
    # Types de connexion
    AND = 'AND'
    OR = 'OR'
    default = AND
    conditional = True

    def __init__(self, *args, _connector=None, _negated=False, **kwargs):
        super().__init__(children=[*args, *sorted(kwargs.items())], connector=_connector, negated=_negated)

    def _combine(self, other, conn):
        if not(isinstance(other, Q) or getattr(other, 'conditional', False) is True):
            raise TypeError(other)

        if not self:
            return other.copy() if hasattr(other, 'copy') else copy.copy(other)
        elif isinstance(other, Q) and not other:
            _, args, kwargs = self.deconstruct()
            return type(self)(*args, **kwargs)

        obj = type(self)()
        obj.connector = conn
        obj.add(self, conn)
        obj.add(other, conn)
        return obj

    def __or__(self, other):
        return self._combine(other, self.OR)

    def __and__(self, other):
        return self._combine(other, self.AND)
    .............

Réf. Implémentation de Q

2 votes

Très bon aperçu des options +1

1voto

Dorin Rusu Points 426

Cela pourrait être utile https://docs.djangoproject.com/en/dev/topics/db/queries/#spanning-multi-valued-relationships

En gros, cela semble fonctionner comme un OU

-2voto

Raj Kushwaha R Points 1
Item.objects.filter(field_name__startswith='votre_mot_clé')

1 votes

Veuillez ajouter une explication à votre réponse afin que les autres puissent en apprendre.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X