Django绑定模型post_save信号创建Board对应目录触发报错如何解决
问题根因
你遇到的启动报错是两个错误导致的:
- 你在
models.py中调用signals.post_save.connect()的时候,直接执行了mkdir_board(Board, sender=Board),传给connect的是函数执行后的返回值(None),而不是mkdir_board函数本身,Django要求信号接收器必须是可调用对象,因此抛出AssertionError: Signal receivers must be callable. signals.py中信号处理函数的参数定义错误,同时导入逻辑、目录创建逻辑也存在问题。
修复步骤
1. 修正signals.py代码
替换为以下内容:
from django.db.models.signals import post_save from django.dispatch import receiver import errno import os from django.conf import settings from .models import Board # 建议基于MEDIA_ROOT拼接路径,避免相对路径受工作目录影响导致位置错误 BASE_STORAGE_PATH = os.path.join(settings.MEDIA_ROOT, "boards/User_Files/") # 直接指定sender=Board,只监听Board模型的保存信号,避免全局监听所有模型浪费性能 @receiver(post_save, sender=Board) def mkdir_board(sender, instance, created, **kwargs): # 仅新建Board实例时创建对应目录,更新操作跳过 if created: # 每个Board对应独立目录,用主键id作为目录名保证唯一性,避免名称重复冲突 board_dir = os.path.join(BASE_STORAGE_PATH, str(instance.id)) try: os.makedirs(board_dir) except OSError as exc: if exc.errno == errno.EEXIST and os.path.isdir(board_dir): pass else: raise
2. 删除models.py中多余的信号绑定代码
删掉models.py末尾的这行代码:
signals.post_save.connect(mkdir_board(Board, sender=Board))
你已经用@receiver装饰器定义了信号监听,并且apps.py的ready方法已经导入了signals模块,绑定逻辑会自动生效,不需要手动调用connect。
其他注意事项
如果之前没配置MEDIA_ROOT,需要在项目settings.py中添加配置,示例:
import os MEDIA_ROOT = os.path.join(BASE_DIR, 'media') MEDIA_URL = '/media/'
测试时新建Board实例后,会自动在media/boards/User_Files/下生成对应主键id的目录。
内容的提问来源于stack exchange,提问作者Mohammad Damra
相关产品推荐
相关产品推荐

