python - Django 发出跟随/取消关注的信号
问题描述
我有一个看起来像这样的信号:
@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
方法吗?
首先,增量最好是原子的,以确保不会丢失任何更改。
使用F() 表达式可以实现原子增量。
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()
infollow_unfollow
- 因为它用内存中的值覆盖数据库中的实例,这不应该是这种情况,至少following_count
因为它的增量逻辑是信号。如果在follow_unfollow
方法中对字段进行了一些更改,而不是followng_count
完成 - 那么save()
应该使用update_fields
list调用以仅更新更改的字段。
正+= 1
则取当前内存中的实例字段值,即count=5
增量(count=6
),稍后,当调用保存时,它被保存为更新count=6
。并且在此期间,数据库中的值可能已经多次更改(并且无论如何 update 会将其设置为 6),尤其是在负载/同时操作下。
使用原子增量逻辑从 python 移动到数据库 - 并将在进行事务时增加实际值。
推荐阅读
- blazor - 如何使用 https 和自定义域在本地运行 Blazor WebAssembly?
- android - Spinner:使用点击监听器以编程方式选择项目
- python - 在pytorch中连接两个张量(有一个扭曲)
- ruby-on-rails - Rails:推送到 Heroku 时,字段“浏览器”不包含有效的别名配置
- reactjs - 如何在 Create-React-App 应用程序上打开 2 个端口,1 个用于 HTTP,1 个用于 HTTPS
- c - 我收到此分段错误(核心转储)错误。有谁知道为什么?
- python - 在 Python 中使用 Boto3 向 Amazon EC2 实例发送命令
- reactjs - 将状态从子级传递给父级 React Native
- .net - Webview 2 .NET(Windows 窗体)NullReferenceException
- python - 无法使用pycharm从其他目录访问ini文件