更改视图中模型的文件保存位置

时间:2014-05-14 07:58:12

标签: django amazon-web-services amazon-s3 boto

我有以下型号。

class Image(models.Model):
    customer = models.ForeignKey(Customer, related_name='images')
    image = models.ImageField(upload_to='/pictures/', verbose_name='Image')

每次用户添加新图片时,我都希望将其放在pictures/customer.id/custom_filename下 当我使用本地文件系统时,这很容易。我使用了一个处理文件块上传的函数,并使用新名称并返回新路径。但现在我想用S3来存储我的文件。所以我使用的是django-storage。我做了以下测试:

testmodel

class TestModel(models.Model):
    name = models.CharField(max_length=10)
    logo = models.ImageField(upload_to='pictures/')

当我在我看来这样做时

def index(request):
    form = TestModelForm(request.POST or None, request.FILES or None)
    if request.method == 'POST':
    if form.is_valid():
        print 'posting form'
        model = form.save(commit=False)
        print model.name
        print model.logo.url
        model.save()

并在mybucket.s3.amazon.com/pictures/logoname.jpg下按原样上传图片 但是,如果我通过某种方式更改文件名,如

def index(request):
    form = TestModelForm(request.POST or None, request.FILES or None)
    if request.method == 'POST':
    if form.is_valid():
        print 'posting form'
        model = form.save(commit=False)
        print model.name
        filename = str(request.FILES['logo']).split('.')[0]
        extension = str(request.FILES['logo']).split('.')[1]
        path = '%d%d%d_%s_%d.%s' %(datetime.now().year, datetime.now().month, datetime.now().day, filename, models_no+1, extension)
        model.logo = path
        print model.logo.url
        model.save()

我得到一个新的网址mybucket.s3.amazon.com/newlogoname.jpg(正确,因为我没有在新路径中显示用户图片),但文件未上传。我必须手动使用boto吗?我想这是唯一的方法,因为每个客户(初始示例)的文件夹可能不存在并且需要创建。在每个模型的自定义位置/目录上传图像的正确方法是什么?

我试图直接调用默认存储将图像保存在我想要的位置但是没有工作

default_storage.save('pictures/one.jpg', ContentFile(request.FILES['logo']))

创建密钥(文件夹和文件)但图像为空。我认为以灵活的方式使用云存储非常困难:(

1 个答案:

答案 0 :(得分:1)

您可以在模型定义中传递一个callable作为 upload_to 命名参数(因此您实际上不必在视图级别执行此操作)。为了说清楚,尝试做这样的事情:

class Image(models.Model):
    customer = models.ForeignKey(Customer, related_name='images')
    image = models.ImageField(upload_to=self.generate_upload_path, verbose_name='Image')

    def generate_upload_path(self, filename):
        return os.path.join('/pictures/'+str(self.customer.id), filename)