Более эффективный и действенный кверисет?

У меня есть эти модели в моем проекте:

...
class User(AbstractBaseUser):
    ...
    income = models.BigIntegerField()
    ...

class Credit(models.Model):
    ...
    user = models.ForeignKey(User, on_delete=models.PROTECT)
    cycle = models.CharField(choices=CYCLE_CHOICES, max_length=2)
    amount = models.BigIntegerField()
    ...

Мне нужен набор запросов, который запрашивает базу данных для пользователя, чей доход больше $10,000, и у которого есть как минимум два (2) кредита, чье cycle равно cycle_credited и сумма $30,000.

В настоящее время у меня есть следующие наборы запросов:

...
user = get_object_or_404(User, id=id)

is_eligible = False

num_of_ten_k_credits = Credit.objects.filter(user=user, user__income__gt=10000, cycle=constants.cycle_credited, amount=30000).count()

if num_of_ten_k_credits >= 2:
    is_eligible = True

Есть ли более эффективный и действенный способ сделать это? Например, однострочное решение с меньшим количеством вызовов БД?

Да, вы можете оптимизировать и сделать его более читабельным, добавив несколько изменений в существующую кодовую базу. Например, добавьте related_name в класс модели Credit


lass Credit(models.Model):
    ...
    user = models.ForeignKey(User, on_delete=models.PROTECT, related_name="credits")
    cycle = models.CharField(choices=CYCLE_CHOICES, max_length=2)
    amount = models.BigIntegerField()
    ...

Вот как можно достичь желаемого результата, используя более оптимизированный и читабельный код

  1. Если вы находитесь внутри представления, имеющего запрос с пользователем
num_of_ten_k_credits = request.user.credits.filter(income__gt=10000,
                                             cycle=constants.cycle_credited,
                                             amount=30000,
                                             )

if num_of_ten_k_credits >= 2:
    is_eligible = True

  1. Если вы не в представлениях и у вас нет request.user, то сделайте это следующим образом

user = get_object_or_404(User, id=id)

num_of_ten_k_credits = user.credits.filter(income__gt=10000,
                                             cycle=constants.cycle_credited,
                                             amount=30000,
                                             )

if num_of_ten_k_credits >= 2:
    is_eligible = True

В обоих случаях я старался избегать __, которые по своей природе являются соединениями и делают запросы медленными.

Вернуться на верх