Django - filtrado de propiedades de claves foráneas

105

Estoy tratando de filtrar una tabla en Django según el valor de un campo particular de un ForeignKey.

Por ejemplo, tengo dos modelos:

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

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

Me gustaría filtrar mi lista de activos según el nombre del proyecto asociado.

Actualmente, estoy realizando dos consultas:

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

Me pregunto si hay alguna forma de especificar este tipo de filtrado en la consulta principal.

Fraser Graham
fuente

Respuestas:

167

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

Fragsworth
fuente
1
Gracias, lo había intentado, pero aparentemente me había olvidado de usar doble subrayado.
Fraser Graham
3
¿Es necesario?
DeadDjangoDjoker
@DeadDjangoDjoker containsdescribe el tipo de comparación utilizada en la consulta que produce el ORM de django, probablemente se verá el sql LIKE '%Foo%'.
orangecaterpillar
17

Esto ha sido posible desde que la queryset-refactorsucursal aterrizó antes de la 1.0. El ticket 4088 expuso el problema. Esto debería funcionar:

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

La documentación de Django Many-to-one tiene este y otros ejemplos de las siguientes claves externas utilizando la API del modelo.

Michael Greene
fuente
1
¿Esto golpeará la base de datos dos veces, debería usar select_related () para hacer esto más óptimo?
Fraser Graham
5
Puede agregar un .query.as_sql () para ver qué sql se ejecutará realmente.
fastmultiplication
el enlace a los documentos de django está completamente desactualizado y aterriza en un '410 Página eliminada': - /
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})

En mi solicitud anterior, asumo que una vez que un estudiante está inscrito, se creará una instancia de SubjectGrade de asignatura que contiene la asignatura inscrita y el estudiante mismo.

El modelo Subject and Student User es una clave externa para el modelo SubjectGrade.

En "available_subjects", excluí todas las asignaturas que ya están inscritas por el student_user actual marcando todas las instancias de asignatura que tienen el atributo "student" como el student_user actual

PD. Disculpas de antemano si aún no puedes entender debido a mi explicación. Esta es la mejor explicación que puedo dar. Muchas gracias

Kinowe
fuente
Creo que será genial editar y agregar algo de texto, explicación o comentario al bloque de código para ponerlo en contexto.
Elisha Senoo
Proporciono una explicación. Gracias @ElishaSenoo
Kinowe