2016-05-26 8 views
1

QRコード5.3をPython3.4を使用して生成しようとすると、私はいくつかの問題に直面しています:最大再帰深度を超過し、メソッドを保存する、Django

最初はio.StringIOを使用しましたが、文字列引数が必要ですが、 'bytes'がありますエラーメッセージ。そこで、io.StringIOをio.BytesIOに変更しました。次に、私は'_io.BytesIO'オブジェクトの属性が 'len'でない別のエラーが発生しましたbuffer.getbuffer()。nbytesしかし、今私はを取得していますオブジェクトの長さを取得するために最大再帰深度はを超え、1つではなく298のQRコードイメージを生成しています。私が間違っていることは何ですか?

from django.db import models 
from django.conf import settings 
from django.core.urlresolvers import reverse 
from django.core.files.uploadedfile import InMemoryUploadedFile 

import random 
import qrcode 
import io 
import sys 

from PIL import Image 

import pdb; 


def qrcode_location(instance, filename): 
    return '%s/qr_codes/%s' % (instance.user.username, filename) 


# Create your models here. 
class EmployeeProfile(models.Model): 
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) 
    qrcode = models.ImageField(upload_to=qrcode_location, null=True, blank=True) 
    first_name = models.CharField(max_length=30) 
    last_name = models.CharField(max_length=30) 

    def __str__(self): 
     return self.first_name + ' ' + self.lastname 

    def save(self): 
     first_initial = self.first_name[0].upper() 
     second_initial = self.last_name[0].upper() 
     id_number = first_initial + second_initial + str(random.randint(1000000, 9999999)) 
     self.generate_qrcode() 

     if not EmployeeProfile.objects.filter(employee_id=id_number).exists(): 
      self.employee_id = id_number 
      super(EmployeeProfile, self).save() 

    def generate_qrcode(self): 
     qr = qrcode.QRCode(
      version=1, 
      error_correction=qrcode.constants.ERROR_CORRECT_L, 
      box_size=10, 
      border=4, 
     ) 
     qr.add_data('Some data') 
     qr.make(fit=True) 

     img = qr.make_image() 

     buffer = io.BytesIO() 
     img.save(buffer) 
     filename = 'qrcode.png' 
     filebuffer = InMemoryUploadedFile(buffer, None, filename, 'image/png', buffer.getbuffer().nbytes, None) 
     self.qrcode.save(filename, filebuffer) 

--------------------解決方法--------------------- ----------

saveはgenerate_qrcodeを呼び出していたので、self.qrcode.saveを呼び出していました。このモデルは無限再帰を引き起こすsaveを呼び出していました。したがって、FileFieldのsaveメソッドに第3の​​引数を追加するだけで、バイパスする必要がなくなります。

Django FileField in model maximum recursion depth exceeded while calling a Python object

# set 3 argument to false(save=False) otherwise infinite recursion will happen 
self.qrcode.save(filename, filebuffer, False) 
+0

'pdb'を実行するとどうなりますか?また、暗闇の中で刺すこともありますが、 'self.qrcode.save'を削除すると、再帰はなくなりますか? –

+0

'super(EmployeeProfile、self).save()を削除すると、何が変わるのですか? – Keiwan

+0

@AlexHall、はい、self.qrcode.saveを削除すると再帰がなくなりますが、生成されたイメージは保存されません。 – nastyn8

答えて

1

self.qrcode.save方法によって次のことができるようにすべきである(...それはself.qrcode.saveを呼び出すgenerate_qrcodeを呼び出しsaveへの呼び出しにつながるように、モデル全体のオブジェクトは、保存する必要があることを意味しトレースバックでこれを見てください)あなたの問題はBytesIOとは関係ありません。再帰的ループを壊すためにどこかに条件を挿入します。

+0

そうです。 Saveはgenerate_qrcodeを呼び出しており、self.qrcode.saveを呼び出しています。そして、saveが呼び出されている間、それはループし続けます。では、save()メソッドでなければgenerate_qrcodeをどこで呼び出すべきですか? – nastyn8

+1

@ nastyn8 http://stackoverflow.com/a/14963186/2482744とhttp://stackoverflow.com/a/25408209/2482744を参照してください –

+0

うわーうまくいった!どうもありがとう。 – nastyn8

0

ここでオーケーはslugフィールドで動作し、またはget_absolute_url models.Modelのための私の完全なソリューションであるとqr_code

class Posts(models.Model): 
    slug = models.SlugField(unique=True) 
    title = models.CharField(max_length=30) 
    my_qrcode = models.ImageField(upload_to='qrCode', null=True, blank=True) 

    def save(self, *args, **kwargs): 
     # we override the save method other wise, slug will not be effect and get_absolute_url will not work 
     if self.slug: 
      pass # here prevents to create slug again when updating your posts 
     else: 
      self.generate_qrcode() 
     super(Posts,self).save(*args, **kwargs) 

    def get_absolute_url(self): 
     return reverse('posts:detail', kwargs={'slug':self.slug}) 

    def generate_qrcode(self): 
     # this part creates unique slugs 
     slug = slugify(self.title) 
     while self.__class__.objects.filter(slug=slug).order_by('-id').exists(): 
      qs = self.__class__.objects.filter(slug=slug).order_by('-id') 
      new_slug = '%s-%s' % (slug, qs.first().id) 
      slug = new_slug 
     self.slug = slug 

     qr = qrcode.QRCode(
      version=1, 
      error_correction=qrcode.constants.ERROR_CORRECT_L, 
      box_size=6, 
      border=0, 
     ) 
     qr.add_data(self.get_absolute_url()) 
     qr.make(fit=True) 

     img = qr.make_image() 

     buffer = StringIO.StringIO() 
     img.save(buffer) 
     filename = 'QrCode-%s.png' % (slug) 
     filebuffer = InMemoryUploadedFile(buffer, None, filename, 'image/png', buffer.len, None) 
     self.my_qrcode.save(filename, filebuffer, False) # we already have save method so just make False itself save behavior 

助けのちょうどそれ、利益。

関連する問題