如何在不再次调用post_save信号的情况下使用post_save并在post_save中使用instance.save?

时间:2020-04-04 18:53:55

标签: django django-models django-signals

我正在使用信号来更改上载的文件,并执行一些过程将.mkv | mp4文件转换为.m3u8和.ts文件,但是当我使用在信号中创建的新.m3u8文件保存实例时, instance.save方法再次调用该信号,这会引发错误。

代码示例:

@receiver(post_save, sender=Lecture)
def handle_video_upload(sender, instance, created, **kwargs):
    # check if a new video has uploaded
    file_has_changed = instance.tracker.has_changed('file')

    if created or file_has_changed and instance.file_type == "V":
    # .../ process to convert video into a .m3u8 file...

        # open the m3u8 created file and change the original (mp4, mkv...) file for the m3u8
        with open(m3u8_absolute_path, "r") as file_object:
            file_m3u8 = File(name=m3u8_absolute_path, file=file_object)
            instance.file.save(m3u8_filename, file_m3u8) # this call this signal again and raise a error

文件字段为:file = models.FileField()

完整代码:

import subprocess
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.core.files import File
from pathlib import Path
from .models import Lecture


@receiver(post_save, sender=Lecture)
def handle_video_upload(sender, instance, created, **kwargs):
    # check if the file field has changed
    file_has_changed = instance.tracker.has_changed('file')

    # the process run when:
    # the file_type is a video (setted as "V"), and:
    # - the instance is created
    # - the video is changed (i.e, reuploaded)
    if created or file_has_changed and instance.file_type == "V":
        instance_absolute_path = Path(instance.file.path)
        m3u8_absolute_path = instance_absolute_path.with_suffix(".m3u8")
        m3u8_filename = m3u8_absolute_path.name

        # use shell commands to create HLS .m3u8 file
        # and delete the original video file
        subprocess.run([
            "ffmpeg",
            "-i",
            instance_absolute_path,
            "-f",
            "hls",
            m3u8_absolute_path
        ])
        subprocess.run(["rm", instance_absolute_path])

        # update the file with the new .m3u8 file
        with open(m3u8_absolute_path, "r") as file_object:
            file_m3u8 = File(name=m3u8_absolute_path, file=file_object)
            instance.file.save(m3u8_filename, file_m3u8)

模型的相关代码:

class Lecture(models.Model):
    FILE_TYPE_CHOICES = (("V", "Video"), ("P", "PDF"))
    file = models.FileField()
    file_type = models.CharField(
        max_length=1,
        choices=FILE_TYPE_CHOICES,
        default="V")
    tracker = FieldTracker()

该网站中的错误:

FileNotFoundError at /admin/lectures/lecture/add/
[Errno 2] No such file or directory: '/home/marcos/geeknoon/geeknoon_server/local/media/media/lectures/second/2020-04-04_16-11-20_8bbOfdb.m3u8

跟踪:https://pastebin.com/PQxgv78n

0 个答案:

没有答案