2011-03-15 6 views
1

J'ai le modèle suivant contenant un FileField où l'utilisateur fournit un fichier zip contenant des images. Ce fichier zip est précessé par une méthode appelée process_zipfile() lors de la sauvegarde.Django: remplir un champ pendant save()

class Album(models.Model): 
    nom = models.CharField(max_length = 200) 
    added_by = models.ForeignKey(User, null=True, blank=True) 
    gallery = models.ForeignKey(Gallery, null=True, blank=True) 
    zip_file = models.FileField('image field .zip', upload_to=PHOTOLOGUE_DIR+"/temp", 
       help_text='Select a .zip file of images to upload into a new Gallery.') 

    class Meta: 
     ordering = ['nom'] 

    def save(self, *args, **kwargs): 
     self.gallery = self.process_zipfile() 
     super(Album, self).save(*args, **kwargs) 

    def delete(self, *args, **kwargs): 
     photos = self.gallery.photos.all() 
     for photo in photos: 
      photo.delete() 
     self.gallery.delete() 
     super(Album, self).delete(*args, **kwargs) 

    def process_zipfile(self): 
     if os.path.isfile(self.zip_file.path): 
     ......(creates gallery object and links the photos) 
     return gallery 

il fonctionne bien, sauf que le champ gallery (laissé vide par la forme) n'est pas remplie par la galerie créée par process_zipfile(). Qu'est-ce que je me trompe?

En outre, la méthode de suppression ne semble pas fonctionner, aucune idée?

+0

Quel est votre type de retour pour process_zipfile()? Avez-vous vérifié que c'est le type de modèle Gallery? –

+0

@kesun: oui est l'utilisation 'gallery = Gallery.objects.create (titre = self.nom, title_slug = slugify (self.nom))' – Mermoz

+2

À propos de la méthode de suppression: parfois (surtout lorsque vous supprimez via django-admin) cette La méthode n'est jamais appelée. Mieux vaut utiliser les signaux pre_delete/post_delete à la place pour s'assurer que les choses que vous voulez faire dans delete sont toujours faites. –

Répondre

0

J'ai enfin pu résoudre mon problème en utilisant post_save et pre_delete:

def depacktage(sender, **kwargs): 
    obj = kwargs['instance'] 
    obj.gallery = obj.process_zipfile() 
    obj.zip_file = None 
    post_save.disconnect(depacktage, sender=Album) 
    obj.save() 
    post_save.connect(depacktage, sender=Album) 

def netoyage(sender, **kwargs): 
     obj = kwargs['instance'] 
     if obj.gallery: 
       if obj.gallery.photos: 
         photos = obj.gallery.photos.all() 
         for photo in photos: 
           photo.delete() 
       gal = Gallery.objects.get(pk = obj.gallery.pk) 
       pre_delete.disconnect(netoyage, sender=Album) 
       gal.delete() 
       pre_delete.connect(netoyage, sender=Album) 

pre_delete.connect(netoyage, sender=Album) 
post_save.connect(depacktage, sender=Album) 
0

Bien que cette question est de deux ans, je suis tombé sur elle en essayant d'apprendre comment faire quelque chose de similaire.

Les fichiers téléchargés ne sont pas écrits dans leur emplacement permanent tant que le modèle ou le champ n'ont pas été sauvegardés. Le chemin peut donc être trompeur. En fonction de votre configuration et de la taille du fichier, il sera généralement en RAM (si inférieur à 2,5 Mo) ou dans le répertoire tmp. Pour plus de détails voir: https://docs.djangoproject.com/en/dev/topics/http/file-uploads/#where-uploaded-data-is-stored

Si vous avez besoin d'obtenir une poignée sur le fichier, avant que le modèle est enregistré, afin de faire un peu de traitement là-dessus, vous pouvez appeler save sur le terrain (il prend deux arguments, les nom de fichier et un objet File représentant son contenu, voir: https://docs.djangoproject.com/en/1.2/ref/models/fields/#django.db.models.FieldFile.save).

Puisque vous appelez save() dans save(), vous voudrez probablement passer le save=False en option (en supposant que vous appelez save() sur le modèle quelque part sur toute la ligne).

La solution OP a fonctionné car le gestionnaire post-save est appelé après l'enregistrement du modèle, de sorte que le fichier existe à l'emplacement prévu. Autres solutions: forcer le traitement du fichier avec le gestionnaire de fichiers tmp et saisir le chemin tmp; implémenter votre propre gestionnaire de téléchargement.

Questions connexes