gpt4 book ai didi

python - Django - post_init 信号在模型实例保存和创建实例之前被调用。为什么?

转载 作者:太空狗 更新时间:2023-10-29 18:02:39 24 4
gpt4 key购买 nike

我正在尝试编写一个接收视频文件的小应用程序,并在上传后将它们转换为统一格式(因此添加到数据库中)。我已经在网上搜索了最好的解决方案,并决定将 Django 的信号与 Celery 一起使用。 .但现在我正在尝试创建一个概念验证,看看它是否有效。

我正在尝试在上传新视频后执行 video_repalce() 方法(因此,数据库中添加了新行)。但是信号不正常,或者我不明白整个系统是如何工作的。

我正在使用带有预定义信号 django.db.models.signals.post_initDjango 1.2.3should be called after a model has been instantiated (因此,一个新行被添加到数据库中)。

from django.core.files.base import File
from django.db.models.signals import post_init
import os
import os.path
import subprocess

class Project(models.Model):
video = models.FileField(upload_to="projects/videos")

def replace_video(self):
"""Replace original video with an updated one."""

# Video conversion process code goes here,
# resulting in a new external video file.

self.video.delete() # Delete the original video.
self.video.save("newfile.webm", File(open("path/to/newfile.webm") ,"wb"))) # Save the new video instead.

self.save() # Commit everything to database.

os.remove("path/to/newfile.webm") # Remove original video copy after it was commited (copied) into the DB.

# ...
# ...

def handle_new_project(sender, **kwargs):
"""Handels some additional tasks for a new added project. i.e. convert video to uniform format."""

project = kwargs['instance']
project.replace_video()

# Call 'Project.replace_video()' every time a new project is added.
post_init.connect(handle_new_project, sender=Project, dispatch_uid="new_project_added")

但是,post_init 不仅在创建新模型实例时被调用,而且...:

  1. 甚至在模型被实例化之前。我的意思是,它是在我第一次执行服务器时调用的,当时数据库中甚至没有一行数据(因此,不应实例化任何模型对象)。实例的self.pkNone!
  2. save() 模型时。当我点击 self.save() 时,上面的代码也会执行。

实际上,根据文档,它不起作用。

我做错了什么?请记住,这是一个概念验证。我打算将代码移动到 Celery在我看到它正在工作之后。但是,如果信号不能正常工作,Celery无济于事 - 每当我 save() 或更新视频时,信号总是会重新发送几次。

你认为我不应该在 replace_video() 方法中调用 save() 吗?那我应该在哪里调用呢?我应该选择哪个信号? post_save 不是一个好的选择,因为每当我点击 save() 时它也会被调用。

最佳答案

您似乎对实例化对象的含义有些困惑。它与数据库无关。这会实例化一个模型对象而不将其保存到数据库中,在这种情况下它的 pk 将为 None:

MyObject(field1='foo', field2='bar')

这(间接地)通过从数据库中获取对象来实例化它:

MyObject.objects.get(field1='baz')

post_init 信号将在这两种情况下发送,即使它们都与保存到数据库无关。

如果您希望在保存时发生某些事情,请覆盖 save 方法本身,或者使用 pre_savepost_save 信号。您可以通过验证其 pk 是否为 None 来检查该对象之前是否已保存。

关于python - Django - post_init 信号在模型实例保存和创建实例之前被调用。为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4700209/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com