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?

Fraser Graham
la source

Réponses:

168

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

Fragsworth
la source
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.

Michael Greene
la source
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

Kinowe
la source
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