2016-02-23 17 views
8

Öğrenme amaçlarım için matplotlib ile çizim yapan bir webapp yapıyorum ve bu arsa görüntüsünü Plot modelinin figure alanına kaydetmek istiyorum ama ben bir komplo oluşturduğumda boş bir görüntüyü /media/figures/ dizinine kaydeder. Bunu başka bir gönderide önerdim ama işe yaramadı.Matplotlib arsa görüntüsünü Django modeline kaydetme

Ben komplo yaparken Bilgi Daha, arsa görüntü <_io.StringIO object at 0xb1ac69ec> gibi bir isim ile benim django Projenin ana dizine kaydedilir, fakat dediğim gibi modelde kaydedilmez arsa görüntü boştur alır. Ayrıca, önemliyse Python 2.7'u kullanıyorum.

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') 

Oluşturulan dosya oluşturuldu ve çizim örnekleri oluşturuldu.

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 

Plot Modeli

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

Plot modelinin neye benzediğini kaydedebilir misiniz? ContentFile ne yapar? – Jonathan

+0

Plot modelini ekledim, ContentFile/https://docs.djangoproject.com/en/1.9/ref/files/file/#the-contentfile-class – eustass

cevap

5

Kodunuzdaki ile birkaç sorun vardır:

  • Bir StringIO ancak bunun yerine, bir io.BytesIO() rakamı kaydetmek gerekir. Bunun nedeni, PNG dosyasının içeriğinin insan tarafından okunabilir metin değil, ikili veri olmasıdır.

  • Başka bir sorun, savefig'a iletirken BytesIO (kodunuzdaki StringIO kodunun) işleyişidir. Bir BytesIO bir dosyayla ilişkili değildir (bu, bellek içi dosya benzeri bir nesneye sahip olmanın tüm noktasıdır), bu nedenle bir dosya adı yoktur. Bu, u'%s' % figure ifadesiyle almak istediğinizi tahmin ediyorum. . Bunun yerine, sadece dosya benzeri nesneye yazınız.

  • Üçüncü olarak, ContentFile yerine django.core.files.images.ImageFile kullanın. Ayrıca, bayt değeri değil, BytesIO nesnesinin kendisi ile başlatabilirsiniz.

Kodunuzdaki ilgili kısmı şuna dönüşür:

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

Bunu denedim ama aynı şey oluyor, biraz daha ekledim Mesajdaki bilgi belki yardımcı olacaktır. – eustass

+1

Django projesinde bunu denemeye çalışacağım, çünkü koddan hemen başka bir hata göremiyorum. Bununla birlikte, proje dizininize kaydedilmiş komik bir isme sahip bir dosya hakkındaki bu bölüm, kodunuzu "şekil" e geçmek için doğrudan kaydettikten sonra güncellenmelidir. Komik isim, tam olarak 'u'% s '% figure' ifadesinin yanlış sonucudur. –

+1

Oh bekle, başka bir şey görüyorum: Belki de doğrudan 'ContentFile' kullanmamalısınız, ama bunun alt sınıfını da 'django.core.files.images.ImageFile' biçiminde karıştırmalısınız. Eğer bu işe yaramazsa, fig.getvalue() öğesinin beklediğiniz görüntü dosyasının içeriğine benzeyip göstermediğini kontrol etmek için 'savefig''e çağrı yaptıktan sonra bir hata ayıklayıcı da yerleştirebilirsiniz.En azından, hatanın çizimde mi yoksa Django tarafında mı olduğunu söyleyeyim. –