web-dev-qa-db-fra.com

Comment changer le nom d'un fichier configuré dans Django?

Est-il possible de changer le nom de fichier d'un fichier téléchargé dans Django? J'ai cherché, mais je n'ai trouvé aucune réponse.

Mon exigence est que chaque fois qu'un fichier est téléchargé, son nom doit être modifié dans le format suivant.

format = userid + transaction_uuid + file_extension

Merci beaucoup...

27

Comment chargez-vous le fichier? Je suppose avec le FileField.

La documentation de FileField.upload_to indique que le champ upload_to,

peut également être un objet appelable, tel qu'une fonction, qui sera appelée pour obtenir le chemin de téléchargement, y compris le nom du fichier. Cet objet appelable doit pouvoir accepter deux arguments et renvoyer un chemin de type Unix (avec des barres obliques) à transmettre au système de stockage. Les deux arguments qui seront passés sont:

" instance ": instance du modèle dans laquelle la variable FileField est définie. Plus spécifiquement, il s'agit de l'instance particulière où le fichier en cours est attaché.

" nom_fichier ": nom de fichier initialement attribué au fichier. Cela peut être pris en compte ou non lors de la détermination du chemin de destination final.

Il semble donc que vous ayez juste besoin de créer une fonction pour gérer votre nom et renvoyer le chemin.

def update_filename(instance, filename):
    path = "upload/path/"
    format = instance.userid + instance.transaction_uuid + instance.file_extension
    return os.path.join(path, format)
48
monkut

Vous devez avoir une FileField avec le upload_to qui appelle un rappel, voir [1].

Votre callback doit appeler une méthode wrapper qui obtient une instance sous l’un des paramètres et nom-fichier l’autre. [2]

Changez-le comme vous le souhaitez et renvoyez le nouveau chemin [3]

1. LOGIQUE

FileField(..., upload_to=method_call(params),....)

2. définir la méthode

def method_call(params):
    return u'abc'

3. Wrapper:

def wrapper(instance, filename):
    return method

c'est la méthode de rappeur dont vous avez besoin pour obtenir l'instance.

def wrapper(instance, filename):
... Your logic
...
return wrapper

Code complet

def path_and_rename(path, prefix):
    def wrapper(instance, filename):
        ext = filename.split('.')[-1]
        project = "pid_%s" % (instance.project.id,)
        # get filename
        if instance.pk:
            complaint_id = "cid_%s" % (instance.pk,)
            filename = '{}.{}.{}.{}'.format(prefix, project, complaint_id, ext)
        else:
            # set filename as random string
            random_id = "rid_%s" % (uuid4().hex,)
            filename = '{}.{}.{}.{}'.format(prefix, project, random_id, ext)
            # return the whole path to the file
        return os.path.join(path, filename)

    return wrapper

Appel à la méthode

sales_attach = models.FileField("Attachment", upload_to=path_and_rename("complaint_files", 'sales'), max_length=500,
                                help_text="Browse a file")

J'espère que cela t'aides. Merci.

6
Clayton

si vous voulez que votre fonction soit réutilisable:

import hashlib
import datetime
import os
from functools import partial

def _update_filename(instance, filename, path):
    path = path

    filename = "..."

    return os.path.join(path, filename)

def upload_to(path):
    return partial(_update_filename, path=path)

Vous devez juste l'utiliser de cette façon:

document = models.FileField(upload_to=upload_to("my/path"))
4
nicolas

Le moyen de base est

import os

os.rename('a.txt', 'b.html')

Pour votre situation, cela ressemblerait probablement à

os.rename ("a.txt", "{id}{uuid}.{ext}".format(id=userid, uuid=transaction_uuid, ext=file_extension))
0
Bárbara Este