Мы можем сделать это, создав две модели: Post
(которые в действительности будут содержать дополнительные данные, такие как message
, author
и т. Д.) И Like
, который действуеткак отношение многие ко многим между Post
и User
:
class Post(models.Model):
total_likes = models.IntegerField(default=0)
likes = models.ManyToManyField(User, through='app.Like')
def like(self, user):
_, created = Like.objects.get_or_create(user=user, post=self)
if created:
self.total_likes += 1
self.save()
@classmethod
def update_likes(cls):
cls.objects.annotate(total=Count('likes')).update(total_likes=F('total'))
class Like(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
post = models.ForeignKey(Post, on_delete=models.CASCADE)
Таким образом, функция like(..)
используется для , как пост (с параметром пользователь).Таким образом, мы можем назвать somepost.like(someuser)
.Он извлечет или создаст новый объект Like
, который сопоставляется с конкретным post
и конкретным user
.Если экземпляр Like
уже существует, ничего не происходит, в противном случае мы увеличиваем поле total_likes
, в котором хранится общее количество лайков.
Возможно, вы не хотите обновлять этот счетчик каждый раз, когда пользователю нравитсяpost: в конце концов, это создает дополнительную нагрузку на сервер.В этом случае, часть if created:
может быть опущена, и мы должны регулярно звонить Post.update_likes
.Эта функция будет выполнять агрегирование за Post
, которое подсчитывает количество лайков, и обновляет поле total_likes
.
Независимо от того, постоянно ли вы обновляете total_likes
, лучше время от времениобновить общее количество лайков на пост.Так как другие виды, модели и т. Д. Могут - учитывая, что разработчики не очень строго к этому относятся - удалять объекты Like
.Кроме того, User
s могут быть удалены и т. Д., И мы не очень контролируем это.Да, мы можем создавать сигналы, которые срабатывают после удаления (и создания) Like
s и User
s, но все же могут быть проблемы с подсчетом количества лайков, таких как условия гонки .Поэтому я бы посоветовал периодически обновлять количество лайков.