django - 在 Django 中一次提交中执行多个 save() 的最佳方法
问题描述
我是 Django 的新手,实际上是网络开发。一直在寻找,但还没有得到答案。
在我的项目中,当用户提交表单请求时,它会搜索一些网站,如果找到特定的图像,它将下载图像并返回下载链接。
目前我有两个模型:
要求
class Request(models.Model): create_time = models.DateTimeField('create time', auto_now_add=True) user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET('unknown')) image_name = models.CharField(max_length=48) image = models.ForeignKey(Image, on_delete=models.SET('unknown'))
图片
class Image(models.Model): add_time = models.DateTimeField('add time', auto_now_add=True) image_source = models.CharField(max_length=48) image_size = models.CharField(max_length=48)
只是想知道在提交请求时将 save() 保存到模型的最佳方式是什么。我正在考虑的方法是:
选项 A:
- 收到请求时,将包含基本信息的请求模型保存()-“图像 ID”除外(尚不可用),并将状态设置为“已启动”
- 进行搜索,下载图像,然后 save() 到图像模型 - 现在我有了“图像 ID”
- 使用“Image ID”信息更新Request实例,并将状态更新为“success”
选项 B:
收到请求后立即搜索并下载图像,并将 save() 保存到图像模型 - 现在我有了“图像 ID”
Save() 到带有“图像 ID”的请求模型 - 这是一个新的插入活动。
最好的方法是什么?或者还有其他更好的方法吗?
另外,有什么建议在这种情况下使用 Django 的“事务”功能?对于我的小项目,我不喜欢它——只是不想让它太复杂。
解决方案
我会选择选项 A,我强烈建议您将“请求”模型重命名为不同的名称,例如:“SearchRequest”Request
在 django 世界中非常具体,如果您向其中添加新上下文,您将很快就很困惑。
触发后,SearchRequest
您可以保存创建时间、状态,STARTED
然后执行研究。在研究过程中可能会出现问题,因此最好将图像搜索包装在 try/except 中。然后,如果出现问题,您可以保存状态FAILED
和原因。这回答了关于原子事务的问题,你不需要那个。
另一个建议,把图片的名字移到Image模型上,SearchRequest可以从相关图片中获取图片的名字。
SearchRequest 的一个改进是将状态保存为相关模型,以便您可以在搜索期间重建状态的更改。
class SearchRequestStatus(models.Model):
create_time = models.DateTimeField('create time', auto_now_add=True)
status = models.CharField(max_length=48)
detail = models.CharField(max_length=256)
search = models.ForeignKey(SearchRequest, on_delete=models.CASCADE, related_name='statuses')
此解决方案可以通过 2 种方式完成:
您将状态的显式更改保存在相关字段中,手动创建新的 SearchRequestStatus 或..
您保存
status
andstatus_detail
并且保存信号将获取更改并使用接收器SearchRequest
自动创建一个 。SearchRequestStatus
(见: https ://docs.djangoproject.com/en/2.1/topics/signals/ )@receiver(signals.post_save, sender=SearchRequest, weak=False, dispatch_uid="_update_search_request_status_history") def _update_search_request_status_history(sender, instance, **kwargs): current_status = SearchRequest.objects.filter(search=instance).first() if不是 current_status 或 current_status.status != instance.status: SearchRequestStatus.objects.create(search=instance, status=instance.status, status_detail=instance.status_detail)
当然,您必须将字段添加到SearchRequest
模型中并添加 STATUSES 元组以限制状态的选择
status = models.CharField(max_length=15, choices=STATUSES.items(), default=`STARTED`)
status_detail = models.CharField(max_length=80, null=True, blank=True)
推荐阅读
- c# - 如何测试这个简单的索引方法?
- java - 当我在 Android Studio 上从 github 拉取代码时出现代码更改问题?
- python - 如何将列数据转换为行
- python - 如何使用关键字从python中的字典中计算项目值
- google-cloud-platform - 有没有办法强制负载均衡器标头为小写?
- python - 多次运行脚本时收敛时间发生了巨大变化
- android - 大型合并网格的低 FPS
- python - 为什么多处理不会改变类的值?
- python - 无法在 python 中使用 Cloudant 扩展从 CouchDb 获取视图
- angular - 无法让基本的编辑模式在 Angular 8 中工作