Как разобрать результат 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 theUser
model [Django-doc] directly. For more information you can see the referencing theUser
model section of the documentation.