Вопрос

У меня есть такая модель:

class Thing(models.Model):
    property1 = models.IntegerField()
    property2 = models.IntegerField()
    property3 = models.IntegerField()

class Subthing(models.Model):
    subproperty = models.IntegerField()
    thing = modelsForeignkey(Thing)
    main = models.BooleanField()

У меня есть функция, которой передается список фильтров, где каждый фильтр имеет форму {'type': something, 'value': x}. Эта функция должна возвращать набор результатов И объединять все фильтры вместе:

final_q = Q()
for filter in filters:
        q = None
        if filter['type'] =='thing-property1':
            q = Q(property1=filter['value'])
        elif filter['type'] =='thing-property2':
            q = Q(property2=filter['value'])
        elif filter['type'] =='thing-property2':
            q = Q(property3=filter['value'])
        if q:
            final_q = final_q & q
return Thing.objects.filter(final_q).distinct()

У каждого Subthing есть булево свойство main. Каждая вещь имеет 1 и только 1 подраздел, где main == True.

Теперь мне нужно добавить фильтр, который возвращает все вещи, у которых есть Subthing, где main == True и subproperty == filter ['value']

Могу ли я сделать это как часть объекта Q , который я создаю? Если нет, то как? Набор запросов, который я получаю до того, как мой новый фильтр может быть довольно большим, поэтому я хотел бы использовать метод, который не включает циклический просмотр результатов.

Это было полезно?

Решение

Это немного легче понять, если вы явно дадите своим субтитрам " related_name " в их отношении к Вещи

class Subthing(models.Model):
    ...
    thing = models.ForeignKey(Thing, related_name='subthings')
    ...

Теперь вы используете присоединение к Django. синтаксис для создания вашего объекта Q:

Q(subthings__main=True) & Q(subthings__subproperty=filter['value'])

Обратное отношение имеет имя по умолчанию «subthing_set», но я считаю, что легче следовать, если вы дадите ему лучшее имя, например «subthings».

Другие советы

Использование (вместо final_q = Q () в начале)

final_q=Q(subthing_set__main=True)
sub_vals = map(lambda v: v['value'], filters)
if sub_vals:
    final_q = final_q & Q(subthing_set__subproperty__in=sub_vals)

должен получить то, что вы хотите, вы также можете настроить свой цикл, чтобы построить список sub_vals и применить его после цикла.

subthing_set - это автоматически добавляемое связанное поле, добавляемое в Thing для доступа к связанным субтитрам.

вы можете назначить другое связанное имя, например.

thing=models.ForeignKey(Thing,related_name='subthings')
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top