La petite astuce du jour qui permet de manière élégante, je trouve, de renommer les fichiers enregistrés dans des « FileField ».
Cherchons à regarder comment ça fonctionne
Si nous nous penchons sur le code de FileField, nous pouvons constater cela dans le __init__ :
def __init__(self, verbose_name=None, name=None, upload_to='', storage=None, **kwargs): #... if callable(upload_to): self.generate_filename = upload_to #...
Si upload_to est callable, donc une lambda ou une fonction par exemple, il y a un traitement particulier.
Regardons un peu plus loin :
def save(self, name, content, save=True): name = self.field.generate_filename(self.instance, name)
Lorsque le fichier est sauvé (la fonction save est appelée), la méthode generate_filename est appelée avec 2 paramètres, l’instance de l’objet que l’on est en train de sauver et le nom du fichier.
Donc ?
Donc, si je passe en paramètre `upload_to` une lambda ou une fonction, celle-ci sera appelée pour récupérer le nom du fichier.
Petit exemple :
class MonModel(Model): my_file = models.FileField(upload_to=lambda instance, filename: '/'.join(['folder', str(instance.pk) + '-' + filename]))
Ce qui pourrait donner : `folder/37-monfichier.pdf`
Cela marche aussi pour la classe ImageField, étant donné qu’elle hérite de FileField ;).