Hen*_*rik 2 python django django-rest-framework
假设我Models在 Django 中有两个:
书:
class Book(models.Model):
title = models.CharField(max_length=100, blank=False)
number_of_readers = models.PositiveIntegerField(default=0)
Run Code Online (Sandbox Code Playgroud)
读者:
class Reader(models.Model):
book = models.ForeignKey(Book)
name_of_reader = models.CharField(max_length=100, blank=False)
Run Code Online (Sandbox Code Playgroud)
每次我Reader向数据库添加一个新的时,我想number_of_readers在Book模型中增加 1。出于性能原因,我不想动态计算Reader与特定 相关的行数Book。
哪里是增加number_of_readers场的最佳位置?在Serializer或在Model?我应该使用什么方法?我应该重写.save的Model?或者里面的其他东西Serializer?
如果有人可以提供一个完整的示例,说明Book在发布新的Reader.
谢谢。
我不会在REST API 级别执行此操作,我会在模型级别执行此操作,因为这样 +1 的增加将始终发生,无论发生在何处(不仅在您点击特定的 REST 视图/序列化程序时)
每次我向数据库添加一个新的 Reader 时,我都想将 Book 模型中的 number_of_readers 增加 1
我想实现post_save的是,当触发模型(阅读器)信号产生
该信号有一个参数称为created,即True在创建模型时,这比Model.save()覆盖更方便
示例大纲
from django.db.models.signals import post_save
def my_callback(sender, instance, created, **kwargs):
if created:
reader = instance
book = reader.book
book.number_of_readers += 1 # prone to race condition, more on that below
book.save(update_fields='number_of_readers') # save the counter field only
post_save.connect(my_callback, sender=your.models.Reader)
Run Code Online (Sandbox Code Playgroud)
https://docs.djangoproject.com/en/1.8/ref/signals/#django.db.models.signals.post_save
竞争条件
在上面的代码片段中,如果你想避免竞争条件(当许多线程更新同一个计数器时可能发生),你也可以book.number_of_readers += 1用 F 表达式替换该部分F('number_of_readers') + 1,这使得在 DB 级别上进行读/写蟒蛇,
book.number_of_readers = F('number_of_readers') + 1
book.save(update_fields='number_of_readers')
Run Code Online (Sandbox Code Playgroud)
更多关于这里:https : //docs.djangoproject.com/en/1.8/ref/models/expressions/#avoiding-race-conditions-using-f
post_delete如果您曾经想过支持“未读”一本书,那么也有一个信号可以反转计数器:)
如果您希望批量导入阅读器,或者需要定期更新(或“重排”)阅读器计数(例如每周一次),除了上述之外,您还可以实现一个功能来重新计算阅读器并更新 Book.number_of_readers
| 归档时间: |
|
| 查看次数: |
1527 次 |
| 最近记录: |