Как разобрать результат applicant__count в Model.objects.values(«applicant», 'counter').annotate(Count(«applicant»)) на поле counter?

У меня есть модель с этими полями, хотя есть и другие поля, но это мой MRE:

class Application(models.Model):     
    applicant = models.ForeignKey(User, on_delete=models.CASCADE,    to_field='email')     
    company = models.CharField(max_length=100)     
    counter = models.PositiveIntegerField(editable=False, default=0)   

Я хочу найти количество заявок в таблице для каждого заявителя и автоматически разобрать это значение в поле counter. В моем файле views.py мне удалось использовать:

model = Application.objects.values('applicant','counter').annotate(Count("applicant"))  

, который возвращает правильные значения:

{'applicant': 'test@users.com', 'counter': 1, 'applicant__count': 2} {'applicant': 'second@user.org', 'counter': 1, 'applicant__count': 4}

Но я не могу извлечь значение `applicant__count` и разобрать его непосредственно в поле counter в models.py.

Я пробовал использовать метод update, update_or_create, но у меня не получается обновить модель. Я также пробовал использовать сигналы django pre_save и post_save, но они продолжают инкрементировать каждое значение. Например, у одного соискателя может быть много заявок на работу, но вместо того, чтобы вернуть общее количество заявок на работу для соискателя, сигналы django увеличивают все заявки в таблице.

Есть ли способ автоматически сохранять результат `applicant__count` в поле счетчика? Буду очень признателен за любую помощь.

Я бы посоветовал не работать с counter полем. Хранение агрегатов часто не является хорошей идеей: вы можете определить их при необходимости.

Я также пробовал сигналы django pre_save и post_save, но они продолжают увеличивать каждое значение.

Именно, это основная причина не хранить агрегаты. Они требуют обновления во всевозможных сценариях: если целевая модель удалена, обновлена, создана и т. д. Если запросы выполняются bulk, сигналы даже не запускаются, что часто делает почти невозможным поддержание counter в идеальной синхронизации.

Вы можете удалить поле counter:

from django.conf import settings


class Application(models.Model):
    applicant = models.ForeignKey(
        settings.AUTH_USER_MODEL, on_delete=models.CASCADE, to_field='email'
    )
    company = models.CharField(max_length=100)
    # counter = models.PositiveIntegerField(editable=False, default=0)

и вычисляйте его при необходимости с помощью .annotate(…) [Django-doc]: User.objects.annotate(counter=Count('application')).

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

Хранить агрегат на модели Application также не имеет особого смысла: это означало бы, что приложение хранит, сколько раз applicant из Application подал заявку?


Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.

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