I was trying to save some files using Django FileSystemStorage. My model is as shown below
key_store = FileSystemStorage(
location='account/files/'+datetime.date.today().isoformat())
class Account(models.Model):
name = models.CharField(max_length=100, null=True, blank=True)
user = models.ForeignKey(User, related_name='auth_user_account_relation')
subscription_id = models.CharField(max_length=100, null=True, blank=True)
info_file = models.FileField(storage=key_store)
But when I save an object of this model only the file name is stored in the db.
So when I try to access the path it returns path appended with todays date and not as the uploaded date. ie. If I upload a file on say 09-21-2015 and I try to access the path on the next day it will return account/files/09-22-2015/<file_name>
which will be an invalid path. So what tweak should be made to store absolute path in db. Or what am I doing wrong here?
I'm pretty sure, your version does not do what you intend it to:
key_store = FileSystemStorage(
location='account/files/'+datetime.date.today().isoformat()
)
is evaluated when the module is loaded (usually only when you start your application). After that the date stays fixed as long as the module is not re-loaded. Hence it points to a directory with the name of the date the application was started, which is probably not what you want.
Also, FileSystemStorage
serializes with full path name, meaning that this also triggers a migration every other day (because the storage path changed).
You can solve this problem by using a combination of FileSystemStorage
(to store files outside of the media directory) and upload_to
with a callable:
key_store = FileSystemStorage(location='account/files/')
def key_store_upload_to(instance, path):
# prepend date to path
return os.path.join(
datetime.date.today().isoformat(),
path
)
class Account(models.Model):
# [...]
info_file = models.FileField(storage=key_store, upload_to=key_store_upload_to)
This uses a new FileSystemStorage
for the base directory of uploaded files and upload_to
to determine the name of an uploaded file relative to the storage's root.
Edit 1 : Thanks for pointing out that upload_to
takes a date format.
Since upload_to
also takes strftime()
format specifiers, a pure-date related path choice can also be implemented without the callable:
info_file = models.FileField(storage=key_store, upload_to='account/files/%Y-%m-%d')
As for explanation:
A storage is essentially an abstraction of a hierarchical file system in django. FileField
s always store their files in a storage . By default the media storage is used, but that can be changed.
To determine the path a file is uploaded to, FileField
roughly does the following
upload_to
option specified for the file field. If upload_to
is a string, use this string as a base directory. upload_to
is run through strftime()
to process any date specifiers. Concatenate upload_to
and the request path, which results in a target path relative to the storage. upload_to
is a callable, call it with (instance, request_path)
and use the return value as the target path (relative to the storage). As one can see, the storage is meant to be more or less static. Changing the storage potentially invalidates all existing file paths in the database, because they are relative to the storage.
Solved the same problem. It uploads the file from the local machine to server
views.py
def receiveAudioRecord(request):
if not os.path.exists('recording/wavFiles'):
os.makedirs('recording/wavFiles')
if not request.FILES['fileupload']:
return render(request, "recording.html", {'msg': "Try Again! Unable to upload. </span>"})
elif request.method == 'POST' and request.FILES['fileupload']:
myfile = request.FILES['fileupload']
fs = FileSystemStorage("recording/wavFiles")
filename = fs.save(myfile.name, myfile) # saves the file to `media` folder
fs.url(filename) # gets the url
return render(request, "recording.html",{'msg':"successfully uploaded"})
else:
return render(request,"recording.html",{'msg':"Try Again! Unable to upload. </span>"})
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.