Django - Filterung nach Fremdschlüsseleigenschaften

105

Ich versuche, eine Tabelle in Django basierend auf dem Wert eines bestimmten Feldes von a zu filtern ForeignKey.

Zum Beispiel habe ich zwei Modelle:

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

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

Ich möchte meine Asset-Liste anhand des Namens des zugehörigen Projekts filtern.

Derzeit führe ich zwei Abfragen durch:

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

Ich frage mich, ob es eine Möglichkeit gibt, diese Art der Filterung in der Hauptabfrage anzugeben.

Fraser Graham
quelle

Antworten:

167

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

Fragsworth
quelle
1
Danke, ich hatte das versucht, aber anscheinend hatte ich vergessen, doppelten Unterstrich zu verwenden.
Fraser Graham
3
ist enthält notwendig ??
DeadDjangoDjoker
@DeadDjangoDjoker containsbeschreibt die Art des Vergleichs, der in der Abfrage verwendet wird, die der Django-ORM erzeugt. Die SQL wird wahrscheinlich so aussehen LIKE '%Foo%'.
Orangecaterpillar
17

Dies war möglich, seit der queryset-refactorZweig vor 1.0 gelandet ist. Ticket 4088 enthüllte das Problem. Das sollte funktionieren:

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

In der Django Many-to-One-Dokumentation finden Sie dieses und andere Beispiele für das Folgen von Fremdschlüsseln mithilfe der Modell-API.

Michael Greene
quelle
1
Wird dies die Datenbank zweimal treffen, sollte ich select_related () verwenden, um dies optimaler zu machen?
Fraser Graham
5
Sie können eine .query.as_sql () hinzufügen, um zu sehen, welche SQL tatsächlich ausgeführt wird.
Fastmultiplication
Der Link zu den Django-Dokumenten ist völlig veraltet und landet auf einer '410 Seite entfernt': - /
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})

In meiner obigen Bewerbung gehe ich davon aus, dass nach der Einschreibung eines Schülers eine SubjectGrade-Instanz erstellt wird, die das eingeschriebene Fach und den Schüler selbst enthält.

Das Benutzermodell für Betreff und Schüler ist ein Fremdschlüssel für das SubjectGrade-Modell.

In "available_subjects" habe ich alle Fächer ausgeschlossen, die bereits vom aktuellen student_user eingeschrieben sind, indem ich alle Subjectgrade-Instanzen mit dem Attribut "student" als aktuellem student_user überprüft habe

PS. Entschuldigung im Voraus, wenn Sie aufgrund meiner Erklärung noch nicht verstehen können. Dies ist die beste Erklärung, die ich liefern kann. Ich danke dir sehr

Kinowe
quelle
Ich denke, es wird großartig sein, Text, Erklärungen oder Kommentare zu dem Codeblock zu bearbeiten und hinzuzufügen, um ihn in einen Kontext zu setzen.
Elisha Senoo
Ich gebe eine Erklärung. Danke @ElishaSenoo
Kinowe