关于django的坑(一)
关于django orm 的坑:
- 关于设置数据库表自动更新
django的orm关于更新数据库的方法有update和save两种方法。想要表中自动更新需要一下几个条件:
- 使用 DateTimeField 设置 auto_now_add 与 auto_now属性为True
- 使用orm 模型的save方法,而不是update
update 更新回直接调用 sql(所以update比save快),而不会通过orm的model层,但 auto_now_add 与 auto_now 为 orm 层mode配置,不是数据库属性,所以造成update不会更新相应的时间段
2. django 使用orm创建表数据,通过id执行相应celery任务,出现db记录不存在
-
- 常用的解决办法:
-
ORM属于事物操作,在执行save方法之后,直接触发一步celery任务,数据记录没有存在需要对任务执行设置 countdown 延时执行,比如2s
-
- 网上很多通过django模型信号 post_save(模型执行save后调用方法):
from django.db import models
@receiver(post_save, sender=AppTask) def post_save_db_task(sender, **kwargs): obj = kwargs['instance'] logger.info(f"{AppTask}任务创建成功,开始执行") celery_cb = obj.celery_task_cb print('callable(celery_cb) :', callable(celery_cb) ) # callable(celery_cb) and celery_cb(obj) # model新增操作 if kwargs['created']: # 参数里的created判断是新增还是更新模型 pass else: pass
post_save 数据django数据库ORM模型,在执行save保存后的后续操作,不属于事物,不属于数据库,仅为save之后执行的调用(y),与直接使用save为同样效果。确认是不可行
# 位于django.db.models.base 663-791 行 def save(self, force_insert=False, force_update=False, using=None, update_fields=None): """ 忽略 """ self.save_base(using=using, force_insert=force_insert, force_update=force_update, update_fields=update_fields) save.alters_data = True def save_base(self, raw=False, force_insert=False, force_update=False, using=None, update_fields=None): """""" # Signal that the save is complete if not meta.auto_created: post_save.send( sender=origin, instance=self, created=(not updated), update_fields=update_fields, raw=raw, using=using, )
-
- 确认可行的:通过事物操作
-
1 from django.db import transaction 2 3 class ApiUserScan(View): 4 @classmethod 5 def post(cls, request: WSGIRequest): 6 # 添加扫描操作 7 with transaction.atomic(): 8 """ 创建更新等操作 """ 9 transaction.on_commit(lambda: print("over")) 10 return Resp.success(message="")
创建事务,同时使用 transaction.on_commit(lambda: print("over"))手动提交,on_commit 作为提交保存到数据库后的回调,执行相应的操作,比如出发执行celery 异步任务,可确保新加入的数据已存在于数据库