Django unique filename method - python

I am looking for the method Django uses to generate unique filename when we upload a file.
For example, if I upload a file called test.csv twice in the same directory, the first one will be saved as test.csv and the second file will be saved as test_2.csv. I already tried to find how Django manages that, but I only found django.utils.text.get_valid_filename which could be useful, but that not what I am looking for...
I already saw other topics with random naming solution, that not what I am looking for here :) I really trying to understand how Django manage that problem.

I actually take a closer look with your help and a found something :)
So basically I have to do something like:
from django.core.files.storage import FileSystemStorage
fss = FileSystemStorage()
filepath = fss.get_available_name(filepath)
Thank you all :)
PS: If you are interesting, the comment from django.core.file.storage.FileSystemStorage._save says:
There's a potential race condition between get_available_name and
saving the file; it's possible that two threads might return the
same name, at which point all sorts of fun happens. So we need to
try to create the file, but if it already exists we have to go back
to get_available_name() and try again.

If you see the implementation of class django.core.files.storage.Storage you will know how Django 1.6 manages the file names.
Look into the save method of this class. In this the line
name = self.get_available_name(name)
is doing the trick.
This is the default implementation of getting the new file name before saving the file. If you want to write your own version (like the file should be overridden) then consider writing your own custom storage system

Actually, you were on the right track.
From the docs,
Internally, Django uses a django.core.files.File instance any time it
needs to represent a file.
And also,
Behind the scenes, Django delegates decisions about how and where to
store files to a file storage system
Which means that, when the file is uploaded, using the default storage (FileSystemStorage), Django delegates the naming (or the available name), behind the scene, for the file to the storage, which then uses: get_available_name(name).
So, If you want to change the way files are named when uploaded, you need to add a custom file storage, which would basically only override get_available_name. The documentation on the matter is here.

Related

How to close a pdf opened with fitz if I've replaced its variable name?

This is a simple issue. I use jupyter notebook for python and usually deal with pdfs using pymupdf.
I usually define pdf = fitz.open('dir/to/file.pdf') but somethimes I forget to close the file before i redefine pdf = fitz.open('dir/to/other_file.pdf')
Sometimes I need to (for example) move or delete file.pdf (the original file) but I can't because python is using it.
Not being an expert, I don't know how to close this file when I have redefined the variable pdf, as obviously pdf.close() would close 'other_file.pdf' and I end up reeinitializing my .ipynb file, which feels dumb.
How can I access an object which variable name has been redefined?
If you do a Document.save("newname.pdf") then that new file, newname.pdf will be immediately available for other processes - it is not blocked by the process you are currently executing.
The original file however, oldname.pdf, from which you have created your Document object remains owned by your current process.
It will be freed if you do a Document.close().
But there is a way to work with the oldname.pdf under PyMuPDF without blocking it. It actually entails making a memory-resident copy:
import pathlib
import fitz
pdfbytes = pathlib.Path("oldname.pdf").read_bytes()
# from here on, file oldname.pdf is fully available
doc = fitz.open("pdf", pdfbytes)
# doc can be saved under any name, even the original one.
Writting this issue made me think about globals()
Browsing throughout its keys I found that the objects which variables have been reused are stored with dummy names (don't know the term used for them). I found the object I was looking for and I was able to 'close' it.
If there's a better - more elegant solution, I'd be glad to hear about it.

How to save program settings to computer?

I'm looking to store some individual settings to each user's computer. Things like preferences and a license key. From what I know, saving to the registry could be one possibility. However, that won't work on Mac.
One of the easy but not so proper techniques are just saving it to a settings.txt file and reading that on load.
Is there a proper way to save this kind of data? I'm hoping to use my wx app on Windows and Mac.
There is no proper way. Use whatever works best for your particular scenario. Some common ways for storing user data include:
Text files (e.g. Windows INI, cfg files)
binary files (sometimes compressed)
Windows registry
system environment variables
online profiles
There's nothing wrong with using text files. A lot of proper applications uses them exactly for the reason that they are easy to implement, and additionally human readable. The only thing you need to worry about is to make sure you have some form of error handling in place, in case the user decides to replace you config file content with some rubbish.
Take a look at Data Persistence on python docs. One option a you said could be persist them to a simple text file. Or you can save your data using some serialization format as pickle (see previous link) or json but it will be pretty ineficient if you have several keys and values or it will be too complex.
Also, you could save user preferences in an .ini file using python's ConfigParser module as show in this SO answer.
Finally, you can use a database like sqlite3 which is simpler to handle from your code in order to save and retrieve preferences.

How do I make files downloadable for a particular role in Plone?

I wish to make the contents of a folder in Plone downloadable only for certain roles. Can this be done easily? At present anybody who clicks the hyperlink for file name in the folder contents can download the file easily. I know about the site-wide option of overriding the at_download code using ZMI.
The codeless way to do this is to make use of Plone's workflow system.
Out-of-the-box, Plone's file and image content types do not have their own workflow. That means that files and images will simply inherit the publication state of their parent folder. This is easy and sensible, but it doesn't meet the need you're describing.
To change the situation, you may use the "types" configuration panel to turn on independent workflow for files and images. Then, their publication status may be set separately from their containing folders. Typically, you'd choose the same workflow that you're using for documents. Then, you may publish a folder and list its contents while having the files within be private -- thus requiring login for viewing.
If you need this to work differently in different places, you may turn on "placeful" workflow (turn it on by adding it in the add-ons panel; it's pre-installed, but not active). This allows different workflows in different parts of a site. It increases complexity, but is often an ideal solution to this kind of puzzle.
This is probably not so simple and you need to add some line of code in a little Plone product (no way TTW). Code snippets below are not tested.
Plone file are developed using the Archetypes framework (this will probably change on Plone 5). What you need to change is the read_permission of the file field (see the Archetypes field reference).
from Products.Archetypes.content.file import ATFile
ATFile.schema['file'].read_permission = 'you new permission'
The you simply need to assign your new permission to a role.
This could be not enough (probably step 1 is not useful nowadays). You need to perform the same operation for the [plone.app.blob extension][2]:
from plone.app.blob.subtypes import SchemaExtender
SchemaExtender.fields[0]..read_permission = 'you new permission'
Last one: you probably need to customize the file_view template or an "Unauthorized" error will be raised when a user without the permission will visit the file view.

Using Python FTP Server (pyftplib) - create HTML file on log in

I have a FTP server working great using Python and the pyftplib library (https://code.google.com/p/pyftpdlib/). I would like to, on login (either anonymous or user), create a html file reflecting the latest state of the server in a nice looking way. For example, all the files that are on the server and their properties nicely separated and looking nice. I thought that since I was already doing everything in Python, and my html wouldn't be overly complex, I would just have python write the html file on log in, and then the user could open the html file for the information that was written seconds before.
My main problem is that when I override the "public callbacks" section of the handlers.py (or any section so far), no file is created that I can find. I am new to python, but it seems like a modification in the handlers.py file should affect the Handler class. Another idea I plan on trying is to override the handler base class with my "on_login" function that does create the html file.
What I am really asking for is
1) Advice from anybody who has done/tried this before
2) Any red flags that are going off in your head regarding my plan
3) Any other ideas (ideally strictly using python)
Thanks!
What worked for me was not editing the handler.py file, but rather creating my own subclass (myFTPHandler) and then redefining the onconnect method to write my html file then.
Thanks for the help though!

template files evaluation in python

I am trying to use python for translating a set of templates to a set of configuration files based on values taken from a main configuration file. However, I am having certain issues. Consider the following example of a template file.
file1.cfg.template
%(CLIENT1)s %(HOST1)s %(PORT1)d C %(COMPID1)s
%(CLIENT2)s %(HOST2)s %(PORT2)d C %(COMPID2)s
This file contains an entry for each client. There are hundreds of config files like this and I don't want to have logic for each type of config file. Python should do the replacements and generate config files automatically given a set of global values read from a main xml config file. However, in the above example, if CLIENT2 does not exist, how do I delete that line? I expect Python would generate the config file using something like this:
os.open("file1.cfg.template").read() % myhash
where myhash is hash of configuration parameters from the main config file which may not contain CLIENT2 at all. In the case it does not contain CLIENT2, I want that line to disappear from the file. Is it possible to insert some 'IF' block in the file and have python evaluate it?
Thanks for your help. Any suggestions most welcome.
Sounds like you may have outgrown your originally simple home-grown templating solution. Maybe you should move to something like Jinja? It might be less of a headache to simply implement a third-party solution than it would be to create/continue to maintain your own solution.
Other options:
cheetah
mako
Maybe you can use a standalone Django template.
How do I use Django templates without the rest of Django? - Stack Overflow
Given that the files already exist, I would set default values for things like CLIENT2 (assuming you know ahead of time all possible keys). You can probably set the default value to something unusual so you can do
config = os.open("file1.cfg.template").read() % myhash
config = [l for l in config.split('\n') if <l does not have unusual text>].join('\n')
I agree with others that in the long term a more robust template would be better.

Categories