Django - Фильтровать связанные объекты - PullRequest
0 голосов
/ 02 октября 2019

Допустим, у меня есть список мест, где у каждого места есть список некоторых объектов. Я хочу убедиться, что я получаю эти местоположения, но с отфильтрованным списком объектов.

Вот структура models.py:

class Location(models.Models):
    # fields


class LocationObject(models.Models):
    location = models.ForeignKey(Location, related_name="objects_list")
    # other fields that are used in filtering

Вот как я делаю фильтрацию:

locations = Location.objects.all()

if request_square_from:
    locations = locations.filter(objects_list__size__gte=request_square_from)

if request_square_to:
    locations = locations.filter(objects_list__size__lte=request_square_to)

# Other filters ...

Проблема в том, что, используя этот метод фильтрации, я получаю в каждом местоположении список объектов, в которых есть по крайней мере один объект, который удовлетворяет условию locations.filter(),Это не то, что мне действительно нужно. Мне нужно исключить каждый объект (я имею в виду LocationObject), который не удовлетворяет условию в методе filter().

Есть ли идея сделать это?

Обновление . Немного пояснения

Вот как выглядит этот список:

Location #1
   - Object 1 (size=40)
   - Object 2 (size=45)
   - Object 3 (size=30)

Location #2
   - Object 4 (size=20)
   - Object 5 (size=25)

Я хочу отфильтровать каждый объект местоположения, скажем, по свойству размера. Предположим, это условие: Location.objects.filter(objects_list__size__gte=40). Это будет соответствовать местоположениям, которые содержат даже только одну запись списка, которая имеет это свойство. Это не , что мне нужно. Ожидаемый результат должен быть:

Location #1:
   - Object 1 (size=40)
   - Object 2 (size=45)

Ответы [ 3 ]

0 голосов
/ 02 октября 2019

Если я не ошибаюсь, вы хотите получить exclude().

filter(), чтобы отфильтровать все необходимые объекты. Поэтому вы должны использовать:

locations = locations.filter(objects_list__size__gte=request_square_from)

Это даст вам все объекты, которые удовлетворяют этому условию.

Но если вы хотите исключить соответствующий запрос. Вам нужно использовать exclude()

locations = locations.exclude(objects_list__size__gte=request_square_from)

Это даст вам объекты, которые не удовлетворяют условию, и вернет остальные объекты.

0 голосов
/ 02 октября 2019

Согласно вашему обновлению, вам нужен список объектов местоположения , а не местоположений, поэтому вместо фильтрации ваших местоположений отфильтруйте объекты местоположений!

objects = LocationObject.objects.all()
if request_square_from:
    objects = objects.filter(size__gte=request_square_from)

if request_square_to:
    objects = objects.filter(size__lte=request_square_to)

Вы являетесь не ограничен фильтрацией внешних ключей, вы можете фильтровать любой экземпляр модели.

Если после этого вам нужно местоположение любого объекта, вы просто ...

objects[0].location
0 голосов
/ 02 октября 2019

Предполагая, что вам действительно нужны те местоположения, в которых есть хотя бы один объект, удовлетворяющий обоим условиям, вы можете выполнить:

locations = locations.filter(objects_list__size__gte=request_square_from, 
                             objects_list__size__lte=request_square_to)

Но поскольку вы не уверены, что оба параметра есть, вы не можете этого сделать. Однако вы можете достичь этого, используя Q объекты:

from django.db.models import Q

# ...    
locations = Location.objects.all()
q = Q()    
if request_square_from:
    q &= Q(objects_list__size__gte=request_square_from)    
if request_square_to:
    q &= Q(objects_list__size__lte=request_square_to)    
if q:
    locations = locations.filter(q)
...