Upload file to Django with dynamic path

老子叫甜甜 提交于 2021-02-16 15:39:07

问题


I am trying to upload files and organise the directory structure in the media folder. In specific I want the upload to create subfolders basis one of the values in the model. The issue I face is that in the view I add information to the instance (in my example code this is the relevant profile). I would like to use this information for the subfolder, but it does not exist in my model until the save which is after the upload...

What would be the appropriate approach to get the information into Upload so that the subfolder can be created?

Thanks

Model:

class Upload(models.Model):
    file = models.FileField(upload_to="upload/")
    profile = models.ForeignKey(Profile, blank=True, null=True)

    def get_upload_to(self, field_attname):
        return 'upload/%d' % self.profile

View:

def profile(request, profile_slug):
    profile = Profile.objects.get(slug=profile_slug)
    context_dict['profile'] = profile
    if request.method=="POST":
            for file in request.FILES.getlist('file'):
                    upload = UploadForm(request.POST, request.FILES)
                    if upload.is_valid():
                            newupload = upload.save(commit=False)
                            newupload.profile = profile
                            newupload.save()
    else:
        pass

    upload=UploadForm()
    context_dict['form'] = upload

    return render(request, 'app/profile.html', context_dict)

SOLUTION, thanks to xyres:

Model:

def get_upload_to(instance, filename):
    return 'upload/%s/%s' % (instance.profile, filename)

class Upload(models.Model):
    file = models.FileField(upload_to=get_upload_to)
    profile = models.ForeignKey(Profile, blank=True, null=True)

View:

def profile(request, profile_slug):
    profile = Profile.objects.get(slug=profile_slug)
    context_dict['profile'] = profile
    if request.method=="POST":
        upload = UploadForm(request.POST, request.FILES)
        if upload.is_valid():
            for f in request.FILES.getlist('file'):
                Upload.objects.create(file=f, profile=profile)
        return redirect(reverse('profile')
    else:
        pass

    return render(request, 'app/profile.html', context_dict)

回答1:


The function which will return the upload path takes 2 arguments, namely: instance and filename. You'll need to define this function outside this class and supply this function to upload_to option.

This is how you need to rewrite your code:

def get_upload_to(instance, filename):
    return 'upload/%d/%s' % (instance.profile, filename)


class Upload(models.Model):
    file = models.FileField(upload_to=get_upload_to)
    profile = models.ForeignKey(Profile, blank=True, null=True)

EDIT:

In case you're wondering why get_upload_to can't be defined inside the class, below is the error you'll most likely get:

ValueError: Could not find function get_upload_to in categ.models.

Please note that due to Python 2 limitations, you cannot serialize unbound method functions (e.g. a method declared and used in the same class body). Please move the function into the main module body to use migrations.



来源:https://stackoverflow.com/questions/35631972/upload-file-to-django-with-dynamic-path

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!