2016-05-26 21 views
1

Beim Versuch QR-Codes mit QR-Code 5.3 unter Verwendung von Python3.4 zu generieren. Ich bin mit mehreren Problemen konfrontiert:Maximale Rekursionstiefe überschritten, Methode speichern, Django

Zuerst habe ich io.StringIO und ich habe eine Zeichenfolge Argument erwartet, bekam 'Bytes' Fehlermeldung. Also habe ich dann io.StringIO in io.BytesIO geändert. Dann bekam ich einen anderen Fehler, der war '_io.BytesIO' Objekt hat kein Attribut 'len' so, um die Länge des Objekts zu erhalten, die ich buffer.getbuffer() .nbytes, aber jetzt habe ich eine Die maximale Rekursionstiefe hat überschritten und es werden 298 QR-Code-Bilder statt nur einer generiert. Irgendwelche Ideen, was ich falsch mache?

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) 

-------------------- LÖSUNG UPDATE --------------------- ----------

Da save rief generate_qrcode, und das war Aufruf von self.qrcode.save und das Modell war der Aufruf von save verursacht unendliche Rekursion. Um dies zu verhindern, müssen Sie es nur umgehen, indem Sie der save-Methode des FileFields ein zusätzliches drittes Argument übergeben.

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

Was passiert, wenn Sie 'pdb' durchlaufen? Außerdem ist es ein Stich im Dunkeln, aber verschwindet die Rekursion, wenn Sie 'self.qrcode.save' entfernen? –

+0

Was ändert sich, wenn Sie 'super (EmployeeProfile, self) .save()' entfernen? – Keiwan

+0

@AlexHall, Ja, die Rekursion verschwindet, wenn ich self.qrcode.save entferne, aber dann werden die generierten Bilder nicht gespeichert. – nastyn8

Antwort

1

self.qrcode.save bedeutet, dass das ganze Modellobjekt gespeichert werden soll, so dass es zu einem Aufruf an save führt, die generate_qrcode ruft die self.qrcode.save ruft ... (übrigens sollten Sie in der Lage sein Sehen Sie dies im Traceback), so dass Ihr Problem nichts mit BytesIO zu tun hat. Fügen Sie eine Bedingung ein, um die rekursive Schleife zu unterbrechen.

+0

Sie haben also recht. Da Save den Befehl generate_qrcode aufruft und es self.qrcode.save aufruft und dann save aufgerufen wird, wird die Schleife fortgesetzt. Also, wo soll ich generate_qrcode aufrufen, wenn nicht in der save() Methode? – nastyn8

+1

@ Nastyn8 werfen Sie einen Blick auf http://StackOverflow.com/A/14963186/2482744 und http://StackOverflow.com/A/25408209/2482744 –

+0

Wow, das hat funktioniert! Danke vielmals. – nastyn8

0

okey hier ist meine volle Lösung für models.Model, die mit Schnecken Feld arbeitet und auch get_absolute_url und 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 

es einfach, Nutzen zu helfen.

Verwandte Themen