首页 > 解决方案 > 如何追溯保存扩展的 Django 模型?

问题描述

我正在尝试使用继承来扩展 Django 模型。我有一个自定义模型,例如:

from request.models import Request

class RequestExtended(Request):
    start_time = DateTimeField(_('start time'), default=None, db_index=True, blank=True, null=True, editable=False)
    total_seconds = FloatField(_('total seconds'), default=None, db_index=True, blank=True, null=True, editable=False)

    def save(self, *args, **kwargs):
        start_time = get_current_request_start()
        total_seconds = None
        if start_time and self.time:
            total_seconds = (self.time - start_time).total_seconds()
        self.start_time = start_time
        self.total_seconds = total_seconds
        super(RequestExtended, self).save(*args, **kwargs)

应用程序中有一个中间件,它会为每个处理的 Django 请求request自动保存一条新request记录,但这不会自动触发我扩展模型的创建。所以我尝试添加一个post_save信号,例如:

def post_request_save(sender, instance, **kwargs):
    print('request.id:', instance.id, instance.ip)
    RequestExtended.objects.get_or_create(request_ptr=instance)

post_save.connect(post_request_save, sender=Request)

但是,这会引发错误,因为RequestExtended它忽略了我的request_ptr值并尝试实例化一个空白Request实例而不填写任何必填字段。

您如何创建通过继承扩展的模型并将其链接到它应该扩展的现有记录?

标签: pythondjangodjango-models

解决方案


经过进一步研究,我发现这个 Reddit 评论解释了这个问题。

即使我的模型没有复制父模型中的字段,因为 Python 层直接模拟了包含所有字段的继承模型,所以我需要在创建父对象时包含父对象中的所有字段。否则,即使我指定了ptr对象,它也会尝试将它们设置为空白值。

所以正确的代码是:

def post_request_save(sender, instance, **kwargs):
    o = RequestExtended()
    o.__dict__.update(instance.__dict__)
    o.save()

推荐阅读