La lecture des données de fichier lors de la méthode propre de forme
-
25-09-2019 - |
Question
Alors, je travaille sur la mise en œuvre de la réponse à href="https://stackoverflow.com/questions/2798670/processing-file-uploads-before-object-is-saved"> .
Voici mon modèle:
class Talk(models.Model):
title = models.CharField(max_length=200)
mp3 = models.FileField(upload_to = u'talks/', max_length=200)
Voici ma forme:
class TalkForm(forms.ModelForm):
def clean(self):
super(TalkForm, self).clean()
cleaned_data = self.cleaned_data
if u'mp3' in self.files:
from mutagen.mp3 import MP3
if hasattr(self.files['mp3'], 'temporary_file_path'):
audio = MP3(self.files['mp3'].temporary_file_path())
else:
# What goes here?
audio = None # setting to None for now
...
return cleaned_data
class Meta:
model = Talk
Mutagène a besoin des objets semblables aux fichiers ou les noms de fichiers sur le disque (I < em> penser ) - le premier cas (où le fichier téléchargé est plus grande que la taille du fichier manipulé en mémoire) fonctionne très bien, mais je ne sais pas comment gérer InMemoryUploadedFile
que je reçois autrement. J'ai essayé:
# TypeError (coercing to Unicode: need string or buffer, InMemoryUploadedFile found)
audio = MP3(self.files['mp3'])
# TypeError (coercing to Unicode: need string or buffer, cStringIO.StringO found)
audio = MP3(self.files['mp3'].file)
# Hangs seemingly indefinitely on my test file (~800KB)
audio = MP3(self.files['mp3'].file.read())
Y at-il quelque chose de mal avec Mutagène, ou que je fais mal?
Après rébus réponse
Modification du paramètre FILE_UPLOAD_HANDLERS
à la volée dans ma classe ModelAdmin
comme ceci:
def add_view(self, request, form_url='', extra_context=None):
request.upload_handlers = [TemporaryFileUploadHandler()]
return super(TalkAdmin, self).add_view(request, form_url, extra_context)
me fait l'erreur suivante 500 quand je frappe présenter:
Vous ne pouvez pas définir les gestionnaires de téléchargement après le téléchargement a été traité.
même si je le fais dès que je le peux!
En outre, je ne suis pas sûr que j'ai une méthode save
sur l'objet Je reviens (je l'ai regardé dans dir(self.files['mp3'].file)
et dir(self.files['mp3'])
).
La solution
Vous pouvez essayer de changer votre FILE_UPLOAD_HANDLERS de telle manière si Django utilise toujours gestionnaire de fichiers Temporaire de:
default FILE_UPLOAD_HANDLERS
:
("django.core.files.uploadhandler.MemoryFileUploadHandler",
"django.core.files.uploadhandler.TemporaryFileUploadHandler",)
Vous pouvez laisser seulement TemporaryFileUploadHandler
en remplaçant le paramètre dans votre settings.py.
Modifier
Beaucoup plus simple, aurait pensé à la première place: (:
from your.models import Talk
mp3 = self.files['mp3']
f = Talk.mp3.save('somename.mp3', mp3)
MP3(f.mp3.path)
>>> {'TRCK': TRCK(encoding=0, text=[u'5'])}
Vous pouvez enregistrer InMemoryUploadedFile
sur le disque de cette façon, puis utiliser le chemin vers ce fichier pour travailler avec mutagen
.
Modifier
Même chose sans une instance de modèles.
import os
from django.core.files.storage import default_storage
from django.core.files.base import ContentFile
from django.conf import settings
from mutagen.mp3 import MP3
mp3 = request.FILES['mp3'] # or self.files['mp3'] in your form
path = default_storage.save('tmp/somename.mp3', ContentFile(mp3.read()))
MP3(os.path.join(settings.MEDIA_ROOT, path))
Notez qu'il est d'enregistrer le fichier dans MEDIA_ROOT, lorsque je tente de le sauver nulle part ailleurs je reçois SuspiciousOperation car il y a des limites à l'endroit où vous pouvez écrire ... vous devez supprimer ce fichier après l'avoir examiné, je suppose, la vraie chose sera sur votre modèle ...
path = default_storage.delete('tmp/somename.mp3')