Bienvenue sur IndexError.

Ici vous pouvez poser des questions sur Python et le Framework Django.

Mais aussi sur les technos front comme React, Angular, Typescript et Javascript en général.

Consultez la FAQ pour améliorer vos chances d'avoir des réponses à vos questions.

Renommer le nom de fichier apres upload?

+1 vote

Pour renommer le nom de fichier apres l'upload, j'utilise cette fonction a l'interieur de mon modele:

def content_file_name(instance, filename):
        ext = filename.split('.')[-1]
        filename = "%s_%s_%s%s%s.%s" % (instance.author_id,
                                        instance.title.replace (" ", "_"),
                                        instance.width, "x", instance.height,
                                        ext)
        return os.path.join('wappa', filename)

Et je m'en sers ainsi:

...
image = models.ImageField(max_length=200, upload_to=content_file_name)
...

Ma question est la suivante: comment inserer dans le nom du fichier, l'id de l'objet courant, sachant que ce dernier n'existe pas encore?

demandé 17-Fev-2015 par Nsukami_ (1,998 points)

J'ai pas encore pu voir dans la doc (suis dans le bus) mais plein de framework permettent ça. Je chercherai un fonction last_inserted() ou un truc dans le genre

2 Réponses

+1 vote
 
Meilleure réponse

Une solution qui marche mais qui ne me paraît pas tout à fait satisfaisante c'est de modifier la méthode save() pour qu'elle s'exécute deux fois lors de la création d'une instance, afin de récupérer l'id. Ça devrait nous donner quelque chose comme ça :

def save(self, *args, **kwargs):
    if self.id is None:
        super(TonModele, self).save(*args, **kwargs)

    # l'instance a forcément un id à ce niveau
    super(TonModele, self).save(*args, **kwargs)

Ce code n'est pas suffisant car la méthode content_file_name() est exécutée seulement lors du premier appel de save() comme l'image n'a pas changée. Pour résoudre ça, il suffit de remplacer le contenu de image par None lors du premier appel de save() :

def save(self, *args, **kwargs):
    if self.id is None:
        image_temporaire, self.image = self.image, None
        super(TonModele, self).save(*args, **kwargs)
        self.image = image_temporaire

    # l'instance a forcément un id à ce niveau
    super(TonModele, self).save(*args, **kwargs)

C'est assez basique mais ça marche.

répondu 17-Fev-2015 par yomytho (296 points)
sélectionné 22-Fev-2015 par Nsukami_

Pas mal, pas mal . Je garde cette option sous le coude. Puis je avoir ton avis sur mon commentaire a la reponse de Foxmask?

+2 votes

Truc simple :

obj = Foo.objects.latest('id')

Ou juste après le save()

obj = Foo.save()
obj.id
répondu 17-Fev-2015 par foxmask (2,888 points)

Cette ligne:

obj = Foo.objects.latest('id')

Me renvoie le dernier objet enregistré ds la bdd, ok. Serais tu entrain de supposer qu'a partir de cet objet, je peux recuperer le dernier id:

last_inserted_id = obj.id

Et ensuite, creer l'objet suivant en definissant moi meme la valeur de l'id:

def content_file_name(instance, filename):
        current_id = Foo.objects.latest('id').id + 1
        ext = filename.split('.')[-1]
        filename = "%s_%s_%s%s%s.%s" % (instance.author_id,
                                       current_id,
                                        instance.width, "x", instance.height,
                                        ext)
        return os.path.join('wappa', filename)

Ça semble tenir la route.

Non , je ferai le save sans l'image et immédiatement après je recupererai l'id puis mettrai a jour l'image et ferai le save une seconde fois.
Ta solution ne marchera pas a chq coup car si 3 users font la même chose en même temps tu vas chopper le même id pour tout le monde et le save qui suivra pour les 2 suivants va leur péter une exception sur la base avec un id déjà existant

Donc

foo = Foo.save() 

Sans l'image puis,

foo2 = get_object_or_404(Foo, pk=foo.id)    
foo2.image = ce que tu veux()
foo2.save()

Le premier save fera un insert info
Le second juste un update foo set image where id

Ça tient la route tant qu'aucun objet n'est sauvegardé entre le moment où Foo.objects.latest() et save() sont exécutées. C'est un laps de temps très court mais ça ne me paraît pas impossible.

En plus si jamais on supprime le dernier objet de la base, ça casse tout :

>>> t1 = TonModele()
>>> t1.save()
>>> t1.id
1

>>> t2 = TonModele()
>>> t2.save()
>>> t2.id
2

>>> TonModele.objects.latest('id').id + 1
3
>>> t2.delete()
>>> TonModele.objects.latest('id').id + 1
2

>>> t2.save()
>>> t2.id
3

Merci a tous les deux. Je vois bcp mieux maintenant. Lequel de vous deux modifie sa reponse pour que je l'accepte comme reponse valide?

Ma réponse est valide telle quelle . les commentaires appuient celle ci. C'est a toi de choisir

...