Ваш ответ будет обновляться только при сохранении самого пользователя, а не только при обновлении отношения m2m. То, что вам нужно, это измененный м2м сигнал .
Я отключил AbstractUser
для models.Model
, чтобы избежать дополнительной работы здесь, но он протестирован и работает.
from django.db import models
from django.db.models.signals import m2m_changed
class Country(models.Model):
# ...
pass
class User(models.Model):
countries = models.ManyToManyField(Country, related_name="users", blank=True)
country_count = models.IntegerField(blank=True, default=0)
# ...
def countries_changed(sender, instance, action, **kwargs):
# add, remove, and clear all have pre_ and post_
# events that trigger this signal; we only want to
# run this -after- one of those events has completed,
# to get the final count.
if action.startswith("post_"):
instance.country_count = instance.countries.count()
instance.save()
m2m_changed.connect(countries_changed, sender=User.countries.through)
Пример (запустить в интерактивном режиме ./manage.py shell
):
from eh.models import User, Country
user = User()
user.save()
print(user.country_count)
# 0
countries = (Country.objects.create() for i in range(10))
for c in countries:
user.countries.add(c)
print(user.country_count)
# 1
# 2
# 3
# 4
# 5
# 6
# 7
# 8
# 9
# 10
user.countries.remove(user.countries.first())
print(user.country_count)
# 9
user.countries.clear()
print(user.country_count)
# 0
Обратите внимание, однако, что этот не будет отлавливать случаи, когда Страна удаляется (для этого можно дополнительно использовать сигнал pre_delete
, связанный с моделью Страны).