如何在Django的upload_to函数中使用UUID主键值?
问题原因
当Django处理ImageField的上传时,会先调用upload_to函数生成文件路径,此时模型实例还未被保存到数据库中。你的id字段使用default=uuid.uuid4,这个默认值是在实例即将写入数据库时才会生成的,所以此时instance.id的值还是None。
解决方案
方案1:提前生成UUID主键(推荐)
修改模型,在实例创建时就生成UUID并赋值给id,确保调用upload_to函数时id已经存在:
import uuid from django.db import models class Foo(models.Model): def picture_path(instance, filename): return 'pictures/{0}/{1}'.format(instance.id, filename) # 移除default参数,改为在实例初始化时生成UUID id = models.UUIDField(primary_key=True, editable=False) picture = models.ImageField(upload_to=picture_path, null=True, blank=True) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # 如果id未设置,生成新的UUID if not self.id: self.id = uuid.uuid4()
这样,当你创建Foo实例(比如通过表单提交或代码实例化)时,id已经被赋值,upload_to函数就能正常获取到该值。
方案2:分两步保存实例
如果不想修改模型结构,可以先保存实例(此时id会被生成),再上传图片:
# 先创建并保存实例,生成id foo = Foo.objects.create() # 为picture字段赋值并再次保存 foo.picture = request.FILES['picture'] foo.save()
这种方法需要分两次操作数据库,适合不需要一次性提交表单的场景。
内容的提问来源于stack exchange,提问作者Ryan
相关产品推荐
相关产品推荐

