问题
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