我有一个看起来像这样的信号:
@receiver([post_save, post_delete], sender=Following)
def increment_follow_count(instance, created=False, **kwargs):
if created:
instance.follower.following_count += 1
instance.target.follower_count += 1
else:
instance.follower.following_count -= 1
instance.target.follower_count -= 1
[当一个用户关注另一个用户时,它可以正常工作。但是,当同一用户取消关注该用户时,只有该用户关注的对象(目标)的追随者计数递减,但该用户的追随者计数不会递减。为什么会发生这种现象,我该如何解决?
型号:
class Following(models.Model):
target = models.ForeignKey('User', related_name='followers', on_delete=models.CASCADE, null=True)
follower = models.ForeignKey('User', related_name='targets', on_delete=models.CASCADE, null=True)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return '{} is followed by {}'.format(self.target, self.follower)
要关注/取消关注用户的代码
def follow_unfollow(follower, target):
# Query to see if the following exists or not
following = target.followers.filter(follower=follower)
if following.exists():
following.delete()
else:
target.followers.create(follower=follower)
target.save()
follower.save()
[increment_follow_count
]信号包含增量逻辑,但没有保存逻辑,是否完成保存是另一种follow_unfollow
方法?
首先,increment优于beatomic,以确保不会丢失任何更改。
使用F() expressions可以实现原子增量。
from django.db.models import F
@receiver([post_save, post_delete], sender=Following)
def increment_follow_count(instance, created=False, **kwargs):
if created:
User.objects.filter(
pk=instance.follower_id
).update(
following_count=F('following_count') + 1
)
User.objects.filter(
pk=instance.target_id
).update(
following_count=F('following_count') + 1
)
else:
User.objects.filter(
pk=instance.follower_id
).update(
following_count=F('following_count') - 1
)
User.objects.filter(
pk=instance.target_id
).update(
following_count=F('following_count') - 1
)
这里的增量不仅是原子的,而且更改会立即保存在数据库中使用相同的方法。
此外,我建议删除target.save()
中的follower.save()
和follow_unfollow
-因为它是数据库中具有内存值的overwrites实例,并且不应该这样,至少对于following_count
,因为其增量逻辑已输入信号。如果在follow_unfollow
方法中对字段进行了一些更改,而不是followng_count
,则应使用save()
调用update_fields
list以仅更新更改的字段。
常规update_fields
获取当前的内存中实例字段值,即+= 1
,增量(count=5
)和后期,当调用save时,它将被保存为更新count=6
。并且在此期间,数据库中的值可能已经更改了很多次(无论更新如何将其设置为6),尤其是在加载/同时操作的情况下。
随着原子增量逻辑从python移至数据库-并将在进行事务处理时增加实际值。