Django - filtrowanie według właściwości klucza obcego

106

Próbuję przefiltrować tabelę w Django na podstawie wartości określonego pola ForeignKey.

Na przykład mam dwa modele:

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

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

Chciałbym przefiltrować listę zasobów na podstawie nazwy powiązanego projektu.

Obecnie wykonuję dwa zapytania:

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

Zastanawiam się, czy istnieje sposób na określenie tego rodzaju filtrowania w głównym zapytaniu?

Fraser Graham
źródło

Odpowiedzi:

168

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

Fragsworth
źródło
1
Dzięki, próbowałem tego, ale najwyraźniej zapomniałem użyć podwójnego podkreślenia.
Fraser Graham
3
czy zawiera niezbędne ??
DeadDjangoDjoker,
@DeadDjangoDjoker containsopisuje typ porównania użyty w zapytaniu, które generuje ORM django, prawdopodobnie sql będzie wyglądać LIKE '%Foo%'.
orangecaterpillar
17

Było to możliwe, ponieważ queryset-refactorgałąź wylądowała przed 1.0. Bilet 4088 ujawnił problem. To powinno działać:

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

Dokumentacja Django Wiele do jednego zawiera ten i inne przykłady stosowania kluczy obcych przy użyciu interfejsu API modelu.

Michael Greene
źródło
1
Czy to uderzy w DB dwa razy, czy powinienem używać select_related (), aby uczynić to bardziej optymalnym?
Fraser Graham
5
Możesz dodać .query.as_sql (), aby zobaczyć, który sql faktycznie zostanie wykonany.
fastmultiplication
link do dokumentacji django jest całkowicie nieaktualny i wyląduje na "Usunięto stronę 410": - /
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})

W powyższym wniosku zakładam, że po zarejestrowaniu studenta zostanie utworzona instancja przedmiotu SubjectGrade, która będzie zawierała zarejestrowany przedmiot i samego ucznia.

Model podmiotu i użytkownika ucznia jest kluczem obcym do modelu SubjectGrade.

W „available_subjects” wykluczyłem wszystkie przedmioty, które są już zarejestrowane przez obecnego student_user, zaznaczając wszystkie wystąpienia przedmiotów, które mają atrybut „student” jako bieżący student_user

PS. Przepraszamy z góry, jeśli nadal nie możesz zrozumieć z powodu mojego wyjaśnienia. To najlepsze wyjaśnienie, jakie mogę podać. Dziękuję bardzo

Kinowe
źródło
Myślę, że wspaniale będzie edytować i dodać tekst, wyjaśnienie lub komentarz do bloku kodu, aby umieścić go w kontekście.
Elisha Senoo
Podaję wyjaśnienie. Dzięki @ElishaSenoo
Kinowe