You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何关联Django Model字段与Celery Worker生成的MP3文件并存储

如何关联生成的MP3文件与Word模型及优化文件存储

一、关联生成的MP3文件到Word模型

核心逻辑是:先保存Word实例获取唯一ID,再通过Celery异步生成MP3,最后反向更新实例的audio字段。

  1. 编写Celery异步任务
    任务接收Word实例ID,生成音频后找到对应实例并完成关联:
from celery import shared_task
from django.core.files import File
from .models import Word
import os
import hashlib
from gtts import gTTS  # 示例TTS工具,可替换为你使用的生成库

@shared_task(autoretry_for=(Exception,), retry_backoff=3)
def generate_word_audio(word_id):
    try:
        word_instance = Word.objects.get(id=word_id)
        # 跳过已存在音频的情况,避免重复生成
        if word_instance.audio:
            return

        # 生成MP3文件(示例用gTTS,根据你的TTS工具调整逻辑)
        tts = gTTS(text=word_instance.word, lang='en')
        temp_path = f"/tmp/{word_instance.word}_temp.mp3"
        tts.save(temp_path)

        # 用单词哈希作为文件名,避免重复存储相同音频
        word_hash = hashlib.md5(word_instance.word.encode()).hexdigest()
        filename = f"{word_hash}.mp3"
        
        # 将生成的文件关联到Word实例的audio字段
        with open(temp_path, 'rb') as audio_file:
            word_instance.audio.save(filename, File(audio_file), save=True)

        # 清理临时文件
        os.remove(temp_path)
    except Word.DoesNotExist:
        pass
  1. 修改Word模型的save方法
    必须先保存实例获取ID,再触发异步任务,否则任务无法定位到对应实例:
class Word(models.Model):
    word = models.CharField(max_length=50)
    translate = models.CharField(max_length=50)
    audio = models.FileField(upload_to='uploads/', blank=True, null=True)

    def save(self, *args, **kwargs):
        # 统一单词为小写
        self.word = self.word.lower()

        # 更新时,如果单词变更则删除旧音频
        if self.pk:
            old_word = Word.objects.get(pk=self.pk).word
            if old_word != self.word and self.audio:
                self.audio.delete(save=False)

        # 先保存实例获取ID
        super().save(*args, **kwargs)
        # 触发异步音频生成任务
        generate_word_audio.delay(self.id)

二、优化文件存储组织

  1. 拆分存储目录,避免单目录文件过载
    用动态路径函数按单词首字母拆分存储目录,提升文件系统性能:
def audio_upload_path(instance, filename):
    # 按单词首字母分目录,例如uploads/a/xxx.mp3
    first_char = instance.word[0].lower()
    return f'uploads/{first_char}/{filename}'

class Word(models.Model):
    # ...其他字段
    audio = models.FileField(upload_to=audio_upload_path, blank=True, null=True)
  1. 自动清理冗余文件
  • 更新单词时删除旧音频(已在save方法中处理)
  • 用post_delete信号删除已删除实例对应的音频文件:
from django.db.models.signals import post_delete
from django.dispatch import receiver

@receiver(post_delete, sender=Word)
def delete_word_audio(sender, instance, **kwargs):
    if instance.audio:
        instance.audio.delete(save=False)
  1. 生产环境切换云存储
    通过django-storages库配置云存储后端(如S3、阿里云OSS),替换本地文件存储,既能避免本地存储瓶颈,还能配合CDN加速音频访问。

内容的提问来源于stack exchange,提问作者Алексей Остапчук

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 07:01:57