Why I can't get pk value after Model create ?
Describe the bug I'm write a BaseModel and rewrite the create method, because I want auto create audit record after I create a new record. but I found I can't get instance's pk after I create it. It's will be null ever for my audit record id field. even stranger is I can print instance's id before I create audit instance. why and what should I do ?
To Reproduce This is a simple case:
# model.py
class BaseModel(models.Model):
"""
基础模型, 所有的模型都应该继承自该模型
"""
audit_model = None
all_objects = models.Manager()
id = BigIntField(pk=True, description="主键ID")
create_time = StrDatetimeField(auto_now_add=True, description="创建时间")
update_time = StrDatetimeField(auto_now=True, description="更新时间")
delete_time = StrDatetimeField(null=True, description="删除时间")
class Meta:
abstract = True
auditable = False
manager = AuditGenerateManager()
@classmethod
async def create(cls: Type[MODEL], using_db: Optional[BaseDBAsyncClient] = None, **kwargs: Any) -> MODEL:
instance = await super().create(**kwargs)
if cls.audit_model:
await cls.audit_model.create(
**kwargs,
id=instance.pk,
operation="create",
operation_user="system",
operation_ip="localhost",
operation_device="system script",
)
return instance
this is auditModel generate file:
# modelAudit.py
from copy import deepcopy
from tortoise.fields.relational import ForeignKeyFieldInstance, ManyToManyFieldInstance, OneToOneFieldInstance
from . import modelApplication, modelAuth
from .model import BaseAuditModel
from .model import CharField
for model_module in [modelAuth, modelApplication]:
for model in model_module.__dict__.values():
if meta := getattr(model, "Meta", None):
if getattr(meta, "auditable", False) and not getattr(model, 'abstract', False):
class_args, meta_class_args = {}, {}
audit_name, meta_name = f'Audit{model.__name__}', f'Audit{model.__name__}Meta'
meta_table, meta_table_description = f"tortoise_audit_{model._meta.db_table}", f"{model._meta.table_description}'s audit model"
meta_class_args.update({'table': meta_table, 'table_description': meta_table_description})
for name, field in model._meta.fields_map.items():
new_field = deepcopy(field)
new_field.unique, new_field.index, new_field.pk, new_field.null = False, False, False, True
if isinstance(field, (ForeignKeyFieldInstance, ManyToManyFieldInstance, OneToOneFieldInstance)) or name == "password":
new_field = CharField(max_length=255, default="", description=f"{field.description}")
class_args.update({name: new_field})
meta_class = type(meta_name, (), meta_class_args)
class_args.update({'Meta': meta_class})
audit_model = type(audit_name, (BaseAuditModel,), class_args)
model.audit_model = audit_model
globals().update({audit_name: audit_model})
at last, this is my business logic Model :
# modelAuth.py
class AuthUser(BaseModel):
name = CharField(max_length=16, default="", description="用户姓名")
email = CharField(max_length=128, null=True, description="用户邮箱")
mobile = CharField(max_length=16, null=True, description="用户手机号")
password = PasswordField(max_length=255, null=True, description="用户密码")
is_super = BooleanField(default=False, description="是否为超级管理员")
last_login = DatetimeField(null=True, description="最后登录时间")
class Meta:
table = 'tortoise_auth_user'
table_description = "用户表, 用于记录用户信息"
auditable = True
constraints = ["CHECK (email IS NOT NULL OR mobile IS NOT NULL)"]
unique_together = [("mobile", "delete_time"), ("email", "delete_time")]
# ... more other models
Expected behavior In my mind, after I await super create instance, I should got this pk, and pass it to my audit model.
Additional context python version: 3.11.4 system os : MacOS tortoise-orm version: 0.20.0 database: mysql 8.0
I really need help, look forward your response, thanks!
I am curious. Where is StrDatetimeField coming from here?
I am curious. Where is
StrDatetimeFieldcoming from here?
just a custom field, I do some custom serialize base on datetime field 🥹
I am curious. Where is
StrDatetimeFieldcoming from here?just a custom field, I do some custom serialize base on datetime field 🥹
Oooh. Wait do you think a custom field like that will fix this issue? #1482