2016-02-23 18 views
8

Ai fini dell'apprendimento, sto creando una webapp che crea grafici con matplotlib e voglio salvare l'immagine di quella trama nel campo figure del modello Plot ma quando faccio un complotto tutto salva un'immagine vuota nella directory /media/figures/. Ho fatto questo come suggerito da un altro post, ma non funziona.Salva l'immagine di trama Matplotlib nel modello Django

Ulteriori informazioni Quando faccio la trama, l'immagine plot viene salvato nella directory principale del mio progetto Django con un nome come <_io.StringIO object at 0xb1ac69ec>, ma come ho detto l'immagine trama che viene salvato nel modello è vuota. Inoltre sto usando Python 2.7 se questo è importante.

def simple_plot(request): 
    if request.method == "POST": 
     name = request.POST.get("name") 
     xvalues = request.POST.get("xvalues") 
     yvalues = request.POST.get("yvalues") 
     plots.simple_plot(request, name, xvalues, yvalues) 
     messages.success(request, "Plot created!") 
     redirect("plots:create") 
    return render(request, 'plots/simple.html') 

Il file di cui sono costituiti i grafici e le istanze di stampa create.

def simple_plot(request ,name, xvalues, yvalues): 
    file_name = name+".png" 
    xvalues = [int(x.replace(" ","")) for x in xvalues.split(",")] 
    yvalues = [int(y.replace(" ","")) for y in yvalues.split(",")] 

    figure = io.StringIO() 
    plot = plt.plot(xvalues, yvalues) 
    plt.savefig(u'%s' % figure, format="png") 

    content_file = ContentFile(figure.getvalue()) 
    plot_instance = Plot(name=name, user=request.user) 
    plot_instance.figure.save(file_name, content_file) 
    plot_instance.save() 
    return True 

Trama Modello

class Plot(models.Model): 
    user = models.ForeignKey(User, on_delete=models.CASCADE) 
    name = models.CharField(max_length=200) 
    figure = models.ImageField(upload_to='figures/') 
    timestamp = models.DateTimeField(auto_now_add=True) 
+0

Potresti postare il modello di Plot? Cosa fa ContentFile? – Jonathan

+0

Ho aggiunto il modello Plot, ContentFile/https://docs.djangoproject.com/en/1.9/ref/files/file/#the-contentfile-class – eustass

risposta

5

Ci sono diversi problemi con il tuo codice:

  • Non si dovrebbe salvare la figura di un StringIO ma, invece, un io.BytesIO(). Questo perché il contenuto del file PNG non è un testo leggibile ma binario.

  • Un altro problema è come si gestisce BytesIO (StringIO nel codice) quando lo si passa a savefig. Un BytesIO non è associato a un file (che è l'intero punto di avere un oggetto simile a un file in memoria), quindi non ha un nome file - che è quello che suppongo tu voglia ottenere con quell'espressione u'%s' % figure . Invece, basta scrivere sull'oggetto simile a un file stesso.

  • In terzo luogo, utilizzare django.core.files.images.ImageFile anziché ContentFile. Inoltre, inizializzalo con lo stesso oggetto BytesIO, non il suo valore in byte.

La quota di competenza del codice diventa allora:

figure = io.BytesIO() 
plt.plot(xvalues, yvalues) 
plt.savefig(figure, format="png") 
content_file = ImageFile(figure) 
+0

Ho provato questo, ma sta accadendo la stessa cosa, ho aggiunto un po 'di più informazioni nel post forse sarà d'aiuto. – eustass

+1

Ho intenzione di provarlo in un progetto Django in quanto non riesco a vedere nessun altro errore immediatamente dal codice. La parte relativa a un file con un nome divertente salvato nella directory del progetto dovrebbe essere eliminata, tuttavia, una volta aggiornato il codice da salvare direttamente su "figura". Il nome divertente è esattamente il risultato di quell'espressione di '% figura' errata 'u'% s. –

+1

Oh aspetta, trovo qualcos'altro: forse non dovresti usare direttamente 'ContentFile' ma una sottoclasse di esso che si mescola anche in' django.core.files.images.ImageFile'. Se ciò non aiuta, puoi anche mettere un debugger dopo la chiamata a 'savefig' per verificare se figure.getvalue() assomiglia al contenuto del file immagine che ti aspetti.Almeno questo ti dirà se l'errore è nel complotto o sul lato Django. –

1

si potrebbe anche voler provare la biblioteca plotly - hanno uno script js che è possibile aggiungere al codice HTML (https://plot.ly/javascript/getting-started/) e si è sempre possibile serializzare gli array che devono essere importati nel grafico

+0

Grazie per l'informazione :) – eustass