Django - filtrage sur les propriétés de clé étrangère


106

J'essaie de filtrer une table dans Django en fonction de la valeur d'un champ particulier d'un ForeignKey.

Par exemple, j'ai deux modèles:

class Asset(models.Model):
    name = models.TextField(max_length=150)
    project = models.ForeignKey('Project')

class Project(models.Model):
    name = models.TextField(max_length=150)

Je souhaite filtrer ma liste d'actifs en fonction du nom du projet associé.

Actuellement, j'effectue deux requêtes:

project_list = Project.objects.filter(name__contains="Foo")
asset_list = Asset.objects.filter(desc__contains=filter,
                                  project__in=project_list).order_by('desc')

Je me demande s'il existe un moyen de spécifier ce type de filtrage dans la requête principale?

Réponses:


168

Asset.objects.filter( project__name__contains="Foo" )


1
Merci, j'avais essayé mais apparemment j'avais oublié d'utiliser le double soulignement.
Fraser Graham

3
est contient nécessaire ??
DeadDjangoDjoker

@DeadDjangoDjoker containsdécrit le type de comparaison utilisé dans la requête que l'ORM django produit, le sql ressemblera probablement LIKE '%Foo%'.
orangecaterpillar

17

Cela a été possible depuis que la queryset-refactorbranche a atterri avant la version 1.0. Le ticket 4088 a révélé le problème. Cela devrait fonctionner:

Asset.objects.filter(
    desc__contains=filter,
    project__name__contains="Foo").order_by("desc")

La documentation Django Many-to-one contient ceci et d'autres exemples de clés étrangères suivantes à l'aide de l'API de modèle.


1
Est-ce que cela va frapper la base de données deux fois, devrais-je utiliser select_related () pour rendre cela plus optimal?
Fraser Graham

5
Vous pouvez ajouter un .query.as_sql () pour voir quel sql sera réellement exécuté.
fastmultiplication

le lien vers les documents django est complètement obsolète et atterrit sur une «page 410 supprimée»: - /
szeitlin

0
student_user = User.objects.get(id=user_id)
available_subjects = Subject.objects.exclude(subject_grade__student__user=student_user) # My ans
enrolled_subjects = SubjectGrade.objects.filter(student__user=student_user)
context.update({'available_subjects': available_subjects, 'student_user': student_user, 
                'request':request, 'enrolled_subjects': enrolled_subjects})

Dans mon application ci-dessus, je suppose qu'une fois qu'un étudiant est inscrit, une instance SubjectGrade sera créée qui contient la matière inscrite et l'étudiant lui-même.

Le modèle utilisateur sujet et étudiant est une clé étrangère du modèle SubjectGrade.

Dans "available_subjects", j'ai exclu toutes les matières qui sont déjà inscrites par le student_user actuel en vérifiant toutes les instances subjectgrade qui ont l'attribut "student" comme étant le student_user actuel

PS. Toutes mes excuses à l'avance si vous ne pouvez toujours pas comprendre à cause de mon explication. C'est la meilleure explication que je puisse fournir. Merci beaucoup


Je pense que ce sera formidable d'éditer et d'ajouter du texte, des explications ou des commentaires au bloc de code pour le mettre en contexte.
Elisha Senoo

Je donne une explication. Merci @ElishaSenoo
Kinowe
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.