Human readable file name - django

Whenever I create an ImageField using a file called moon.png, Django, correctly following my configuration settings, puts the file in:
campaign/primary-banner/2015/11/25/moon.png
or
campaign/primary-banner/2015/11/25/moon_RcJ3FuD.png
And that is the value of imagefield.name, which I can show to the user, but is not really user friendly.
I would like to show the name of ImageField.name, but in a human readable format. Is it possible to extract the original file name (moon.png) from the ImageField? The workarounds that I can think of are:
add an extra field to my model to hold the human readable file name. Extra work, which I would like to avoid: DRY.
process the imagefield.name value to extract the original filename, but this seems too complex (I would need to exactly understand how django is generating the filename in the first place, to make sure I cover corner cases)

I had similar problem and solved it by creating my own subdirectry under MEDIA_ROOT, in which I made directory structure involvind the date and also some unique identifier. Then I moved my file to that final subdirectory and put the name to FileField.name. Everything works like charm - files are unique (thanks to unique directories) and the final name is exactly what i want user to see (as there is no need to rename it - no conflict is possible)
p.filename=get_filename_of_existing_file_to_be_stored()
p.originalfilename=get_how_it_should_be_named()
masterobject=MyNewMaster.objects.get(pk=some_id)
uniq_name=masterobject.make_something_unique()
new_object=MyObject()
new_object.master=masterobject
new_object.some_fields=some_values
daystr=date.today().strftime('%y-%m-%d')
directory='MyDir/%s/%s/%s/'%(daystr,masterobject.id,uniq_name)
if not os.path.exists(os.path.join(settings.MEDIA_ROOT,directory)):
os.makedirs(os.path.join(settings.MEDIA_ROOT,directory))
fname=os.path.join(directory,p.originalfilename)
os.rename(p.filename,os.path.join(settings.MEDIA_ROOT,fname))
new_object.filename = fname
new_object.save()
Now everthing works for me and no conflicts are possible and even Django seems happy with this hack and provides the correct filename and url for everything i tried to do with MyObject :)
Now I ended with path like:
MyDir/2015-11-29/12345/child_7/moon.png

Related

Django - Unique upload filenames regardless of file extension

I want to create unique filenames for each uploaded file (Similar to this), but regardless of the extension (ie, name.txt and name.dxf is a clash)
I'm converting files on my server (ie, ogg, wav, etc) to a particular filetype extension, ie. mp3, and then removing the original file.
This issue is if someone uploads a file with different extension but the same base name, then the conversion will override the original file.
I can obviously do a check if the target file already exists. I know Django will also generate some sort of unique identifier (appended to the uploaded filename) such as "_HVk3AIt" if there is a conflict with an exact filename match. Is this a UUID?
I originally though adding a randomly generated UUID would be a bad solution because even though 2^128 is like 4*10^38 (little chance of clash) you could technically override something eventually, but I guess you just keep checking the new proposed filename, and add secondary UUID if you've got a second collision etc.
Is this a good solution, or what is standard practise for such a problem?

How safe is createuuid in a clustered environment?

The title pretty much says it all. The scenario is a user uploads a file but they could be hitting 1 of 6 servers depending on the current load at the time. We have run into a situation where the users are trying to upload files with special characters in their names. We can write a function to sanitize the file name but then we have to check that the new sanitized file name doesn't exists. My thought was to just rename the file using createuuid(). I believe the createuuid() function uses the servername as part of the algorithm if I remember correctly so if anything, the uniqueness should be 6 fold due to the 6 servers. Am I correct in this thinking?
If I remember correctly, CF uses timestamp+clock+servername.
Did you consider sanitizing the uploaded filename and just append the UUID? This appears failproof to me.

How to manage string url parameter properly (primary key issue)

I'm trying to manage folder navigation in django 1.6, my goals is to get something like the url pattern you can see on Dropbox website. The url looks like to : 'Home/Folder/Subfolder'.
I've an issue when there is two folders with the same name but with a different primary key of course. These folders are located in a different directory.
First, in my template, i was sending the name of the folder as a get parameter. In order to get the right folder object in my view when i had two folder with the same name, i have changed my url conf passing the folder pk as a post data (similar to this answer : https://stackoverflow.com/a/6118735/2112198).
It works, but i would like to find a better way to achieve this. Could i pass the pk as a get parameter and rewrite the url next in the view to get only the folder name in the url browser ?
If you need two identical urls to represent two different objects then your url scheme is conceptually flawed.
With the caveat... clearly this works for Dropbox. It is worth thinking about why this works: in Dropbox you are logged in as a specific user. Each user has their own folder structure, but a user can't have two folders with the same name.
i.e. there is a hidden variable (user id) that is added to the folder path in order to locate a unique object.
Alternatively, if you are just trying to work around this simpler problem:
Home/Documents/Work
Home/Pictures/Work
i.e. two folders named Work then you just need to consider the whole path like Pictures/Work vs Documents/Work in order to disambiguate them.

Is there anyway to rename the "Source" button to something like "HTML"?

Is there anyway to rename the "Source" button to something like "HTML", I ask this as users are confused at how to add html code using the editor?
Yes, inside of the "lang" folder you will see all of the various language files.
For my case, and probably yours, You will want to edit the file "en.js". The file is "compressed" to some degree so it may be difficult to read, but it's still not too difficult to change one string. If you do plan on changing multiple strings you will most likely want to use a service to format Javascript.
Search for the following segment of code. It was one of the very last lines in the file.
"sourcearea":{"toolbar":"Source"}
change it to
"sourcearea":{"toolbar":"HTML"}
Avoid This Method Unless Required
And as for a very unsuggested method, since you can't modify the language files for some reason, you can modify the ckeditor.js file and force a specific label.
Inside of "ckeditor.js" change the line below
a.ui.addButton("Source",{label:a.lang.sourcearea.toolbar,command:"source",toolbar:"mode,10"});
to the follow code
a.ui.addButton("Source",{label:"HTML",command:"source",toolbar:"mode,10"});
The only thing modified is the "label" value in the above line. We remove the reference to the a.language.sourcearea.toolbar and insert a string in it's place instead.

Is there a way for uploading file by asking user input local file path in django?

Is it possible to have a charfield in a form to ask user input a absolute file path then bound the file to Request.file object? I think this is quite routine but I cannot use forms.fileField to do this since I cannot find a argument you can input file path. I searched but seems no related posts can be found.
No, there is no way to do this, because there is no way to give a path to a browser file upload field - for very good security reasons imposed by the browsers themselves.