Django: могу ли я проверить, соответствует ли экземпляр модели фильтру без фильтрации всех экземпляров модели

#python #django #django-models #filter #django-queryset

#python #django #django-модели #Фильтр #django-queryset

Вопрос:

У меня есть экземпляр модели. У меня есть набор запросов. Могу ли я проверить, соответствует ли экземпляр фильтру без фильтрации всех объектов модели?

Ситуация: у меня есть модель Alpha , когда эта модель создается, мне нужно проверить, соответствует ли она определяемому пользователем фильтру, который хранится в модели Bravo . Будет много Alpha моделей и много Bravo моделей (фильтров).

 class Alpha(models.Model):
    test = models.CharField()

class Bravo(models.Model):
    test = models.CharField()

    def get_qs(self):
        # These could be longish and complex, defined by users
        return Q(test=self.test) | Q(test=f"{self.test}a")

# There will be many of these but I only want to check this instance
a = Alpha(test="testa")
# There will be many of these, I need to check if queries from get_qs match "a"
b = Bravo(test="test")

# Lots of Bravo, all need to be checked, unavoidable
for bravo in Bravo.objects.all():
    # Lots of Alpha, don't want to check them all
    # Just check "a" matches bravo.get_qs filter
    if a in Alpha.objects.filter(bravo.get_qs()):
        # Do something with "a" depending on which "b"
        pass
  

Мое предположение

 if a in Alpha.objects.filter(bravo.get_qs())
  

Будет фильтровать все Alpha объекты. Я не хочу этого, потому что мне не нужно проверять какие-либо другие экземпляры, кроме «a», и их будет много. Я не хочу проверять все Alpha объекты для каждого Bravo объекта.

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

Ответ №1:

Вместо a in Alpha.objects.filter(bravo.get_qs()) вы можете проверить, что набор запросов, имеющий тот же первичный ключ, что и a существует в Alpha .

 alpha = Alpha.objects.filter(pk=a.pk)

for bravo in Bravo.objects.all():
    if alpha.filter(bravo.get_qs()).exists():
        # Do something with "a" depending on which "b" 
  

Комментарии:

1. Если я использую pk я не буду знать, какие Bravo совпадения. Я мог бы сделать Alpha.objects.filter(bravo.get_qs()).exists() , я не уверен, в чем разница между exists и in , и было бы ли это улучшением.

2. вы можете объединить фильтры в цепочку. exists это улучшение по сравнению с in , потому что, кроме того, он фильтрует по первичному ключу. В идеале возвращаемый набор запросов из первой операции фильтрации должен соответствовать одной записи и возвращать альфа-экземпляр