Django.fun

Django complex query with a many to many field

Let's explain the problem. I am trying to filter out all Person that have certain attributes.

These are my models:

class Person(models.Model):
    community = models.ForeignKey(
        Community, on_delete=models.CASCADE, related_name="people"
    )


class Attribute(models.Model):
    community = models.ForeignKey(
        Community, on_delete=models.CASCADE, related_name="attributes"
    )
    name = models.CharField(max_length=50)
    value = models.CharField(max_length=100)


class Trait(models.Model):
    person = models.ForeignKey(
        Person, on_delete=models.CASCADE, related_name="person_attributes"
    )
    attribute = models.ForeignKey(
        Attribute, on_delete=models.CASCADE, related_name="traits"
    )

A person could have the following attributes:

Attribute(name='head', value='big')
Attribute(name='head', value='small')
Attribute(name='head', value='medium')

Attribute(name='hands', value='white')
Attribute(name='hands', value='red')
#...

These attributes are linked to Person through the Trait entity.

Now, I have the following dict, witch I use to dynamically build the query:

{
  "head": ["small", "medium"],
  "hands": ["white", "red"],
}

I want to filter out all the Person that have the attribute "head" with the value "small" or "medium" and the "hands" "white" or "red"

This is what I have done so far, but it doesn't works:

# value is the dict like the one explained above from which 
# I will obtain the elements for filtering
def routine(self, value):
    query = Q()
    for attr, traits in value.items():
      if len(traits) > 0:
        query &= Q(
            Q(person_attributes__attribute__name=attr) &
            Q(person_attributes__attribute__value__in=traits)
        )

    return Person.objects.filter(query)

Tutorials

Современный Python: начинаем проект с pyenv и poetry

Настройка проекта Python — виртуальные среды и управление пакетами

Использование requests в Python — тайм-ауты, повторы, хуки

Понимание декораторов в Python

ProcessPoolExecutor в Python: полное руководство

map() против submit() с ProcessPoolExecutor в Python

Понимание атрибутов, словарей и слотов в Python

Полное руководство по slice в Python

Выпуск Django 4.0

Безопасное развертывание приложения Django с помощью Gunicorn, Nginx и HTTPS

Автоматический повтор невыполненных задач Celery

Django REST Framework и Elasticsearch

Докеризация Django с помощью Postgres, Gunicorn и Nginx

Асинхронные задачи с Django и Celery

Релизы безопасности Django: 3.2.4, 3.1.12 и 2.2.24

Выпуски исправлений ошибок Django: 3.2.3, 3.1.11 и 2.2.23

Эффективное использование сериализаторов Django REST Framework

Выпуски безопасности Django: 3.2.2, 3.1.10 и 2.2.22

Выпущенные релизы безопасности Django: 3.2.1, 3.1.9 и 2.2.21

Обработка периодических задач в Django с помощью Celery и Docker

View all tutorials →