Django: filtro sulle proprietà della chiave esterna


106

Sto cercando di filtrare una tabella in Django in base al valore di un particolare campo di un file ForeignKey.

Ad esempio, ho due modelli:

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

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

Vorrei filtrare il mio elenco di risorse in base al nome del progetto associato.

Al momento sto eseguendo due query:

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

Mi chiedo se esiste un modo per specificare questo tipo di filtro nella query principale?

Risposte:


168

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


1
Grazie, ci avevo provato ma a quanto pare avevo dimenticato di usare il doppio trattino basso.
Fraser Graham

3
è necessario?
DeadDjangoDjoker

@DeadDjangoDjoker containsdescrive il tipo di confronto utilizzato nella query prodotta da django ORM, lo sql sarà probabilmente simile LIKE '%Foo%'.
orangecaterpillar

17

Ciò è stato possibile da quando la queryset-refactorfiliale è atterrata prima della 1.0. Il ticket 4088 ha esposto il problema. Questo dovrebbe funzionare:

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

La documentazione di Django Many-to-one contiene questo e altri esempi di utilizzo di chiavi esterne utilizzando l'API del modello.


1
Questo colpirà il DB due volte, dovrei usare select_related () per renderlo più ottimale?
Fraser Graham

5
Puoi aggiungere un .query.as_sql () per vedere quale sql verrà effettivamente eseguito.
fastmultiplication

il link ai documenti di django è completamente obsoleto e finisce su una '410 Pagina rimossa': - /
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})

Nella mia domanda di cui sopra, presumo che una volta che uno studente è iscritto, verrà creata un'istanza SubjectGrade del soggetto che contiene il soggetto iscritto e lo studente stesso.

Il modello Soggetto e Utente Studente è una chiave esterna per il modello SubjectGrade.

In "available_subjects", ho escluso tutti i soggetti che sono già iscritti dallo student_user corrente controllando tutte le istanze del subjectgrade che hanno l'attributo "student" come student_user corrente

PS. Mi scuso in anticipo se non riesci ancora a capire a causa della mia spiegazione. Questa è la migliore spiegazione che posso fornire. Grazie mille


Penso che sarà fantastico modificare e aggiungere del testo, spiegazioni o commenti al blocco di codice per metterlo nel contesto.
Elisha Senoo,

Fornisco una spiegazione. Grazie @ElishaSenoo
Kinowe
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.