Mon exemple de modèle:
return User.objects.exclude(
alpha_thing__assigned_at__isnull=True
).exclude(
beta_thing__assigned_at__isnull=True
).all()
Je souhaite interroger tous les utilisateurs qui n'ont pas de Thing avec une date assigned_at , c'est-à-dire qu'ils pourraient avoir d'autres Choses , mais cela devrait avoir une date définie.
J'ai essayé:
class Thing(models.Model):
alpha = models.ForeignKey('auth.User', on_delete=models.CASCADE,
related_name='alpha_thing')
beta = models.ForeignKey('auth.User', on_delete=models.CASCADE,
related_name='beta_thing')
assigned_at = models.DateTimeField(
_('assigned at'),
null=True,
help_text=_('Assigned at this date'))
mais le résultat est vide (la table des objets est vide, donc je Je ne sais pas si cela a quelque chose à voir avec la jointure?).
4 Réponses :
Pour tous les utilisateurs qui n'ont pas de Thing avec une date vide, essayez:
return User.objects.exclude(
alpha_thing__assigned_at=None
).exclude(
beta_thing__assigned_at=None
)
Au fait, j'ai obtenu le même résultat que j'utilise .all () à la fin ou pas, donc:
return User.objects.exclude(
alpha_thing__assigned_at=None
).exclude(
beta_thing__assigned_at=None
).all()
a renvoyé le même résultat que le premier exemple.
Il existe un autre moyen, puisque vous souhaitez filtrer l'utilisateur sur les "choses" qui contiennent toutes une date_ affectée .
Vous pouvez:
User.objects.filter(
alpha_thign__assigned_at__isnull=False,
beta_thign__assigned_at__isnull=False,
)
Simple.
Il n'est pas nécessaire d'utiliser des objets Q ici ou des opérations | (ou).
Ce que vous voulez n'est pas
alpha_thing__assigned_at__isnull = Faux OU beta_thing__assigned_at__isnull=False Ce que vous recherchez est
alpha_thing__assigned_at__isnull = False AND beta_thing__assigned_at__isnull=False Avez-vous essayé quelque chose comme ça?
from django.db.models import Q has_null_alpha = Q(alpha_thing__isnull=False, alpha_thing__assigned_at__isnull=True) has_null_beta = Q(beta_thing__isnull=False, beta_thing__assigned_at__isnull=True) User.objects.exclude(has_null_alpha | has_null_beta)
Je pense que la raison pour laquelle vous voyez des résultats inattendus n'a peut-être rien à voir avec le fait qu'il existe sont plusieurs chemins ForeignKey dans le jeu de requêtes. Votre déclaration selon laquelle "la table d'objets est vide" pourrait être la clé, et la raison pour laquelle les utilisateurs ne s'affichent pas est qu'ils n'ont pas de relation alpha_thing ou beta_thing .
Le QuerySet User.objects.exclude (alpha_thing__assigned_at__isnull = True) produit une jointure externe gauche entre la table User et le code Thing > table, ce qui signifie qu'avant d'effectuer des comparaisons dans la clause WHERE , vous obtenez NULL pour assigned_at dans toute ligne où il n'y a pas Thing.
Une chose vraiment étrange ici est qu'un filtre provoque une jointure INNER , de sorte que l'instruction User.objects.filter (alpha_thing__assigned_at__isnull = False ) ne donne en fait que les utilisateurs qui ont alpha_thing objets liés avec une valeur non NULL pour assigned_at code> (en laissant de côté les gars sans alpha_thing) associé .
Juste pour clarifier: si j'ai cette collection de choses [Thing (user1, user2, datetime), Thing (user2, user3, None)] ... quels utilisateurs voulez-vous? [utilisateur2, utilisateur3], [utilisateur3] ...?
@spadarian tous les utilisateurs qui n'ont pas de Thing avec une date vide, donc votre exemple ne serait pas user2 et user3, donc seulement user1 est attendu.
Je pense que vous vouliez dire "tous les utilisateurs qui n'ont pas de chose avec out une date
assignée" - est-ce exact?Juste pour vérifier: vous voulez inclure
Userdes objets qui n'ont pas aucunalpha_thingouassocié objets beta_thing, non?