jason
jason

Reputation: 3075

Django model error maximum recursion depth exceeded

I'm following this guide and I get the following error when saving...

RuntimeError at /admin/products/product/2/
maximum recursion depth exceeded

Why do I get this error? I have included the full model below.

Thanks

models.py:

class Product(models.Model):
    title = models.CharField(max_length=60)
    qr_url = models.URLField(blank=True)
    qr_image = models.ImageField(
        upload_to="public/uploads/",
        height_field="qr_image_height",
        width_field="qr_image_width",
        null=True,
        blank=True,
        editable=False
    )
    qr_image_height = models.PositiveIntegerField(null=True, blank=True, editable=False)
    qr_image_width = models.PositiveIntegerField(null=True, blank=True, editable=False)

    #FK
    category = models.ManyToManyField(ProductCategory)
    attribute_answers = models.ManyToManyField(AttributeAnswers)
    # Custom Managers

    def __unicode__(self):
        return self.title

    def qr_code(self):
        return '' % self.qr_image.url
    qr_code.allow_tags = True

def product_pre_save(sender, instance, **kwargs):
    if not instance.pk:
        instance._QRCODE = True
    else:
        if hasattr(instance, '_QRCODE'):
            instance._QRCODE = False
        else:
            instance._QRCODE = True


models.signals.pre_save.connect(product_pre_save, sender=Product)


def product_post_save(sender, instance, **kwargs):
    if instance._QRCODE:
        instance._QRCODE = False
    if instance.qr_image:
        instance.qr_image.delete()
    qr = QRCode(4, QRErrorCorrectLevel.L)
    qr.addData(instance.qr_url)
    qr.make()
    image = qr.makeImage()

    #Save image to string buffer
    image_buffer = StringIO()
    image.save(image_buffer, format='JPEG')
    image_buffer.seek(0)

    #Here we use django file storage system to save the image.
    file_name = 'UrlQR_%s.jpg' % instance.id
    file_object = File(image_buffer, file_name)
    content_file = ContentFile(file_object.read())
    instance.qr_image.save(file_name, content_file, save=True)


models.signals.post_save.connect(product_post_save, sender=Product)

Upvotes: 3

Views: 3242

Answers (4)

Dat TT
Dat TT

Reputation: 3083

My approach is just to use udpate method of QuerySet object instead of save one from Model:

Model.objects.filter(pk=obj.pk).update(fieldx=valuey)

Upvotes: 0

Arpit Singh
Arpit Singh

Reputation: 416

To solve this problem, You should add one more field in database, this field will describe that inserted record is inserted by simple view or signal. then in receiver function you should check that if instance is inserted by signal if so don't apply receiver function

@receiver(post_save) def my_callback(using,sender,instance,**kwargs):
   if not(instance.added_by == 'signal'):
       obj = Student1()
       obj.name = instance.name
       obj.city = instance.city
       obj.state = instance.state
       obj.postal_code = instance.postal_code
       obj.age = instance.age
       obj.added_by = 'signal'
       obj.save()

Upvotes: 0

WBAR
WBAR

Reputation: 4984

You copiend in wrong way from tutorial :)

def product_post_save(sender, instance, **kwargs):
    if instance._QRCODE:
        instance._QRCODE = False
        if instance.qr_image:
            instance.qr_image.delete()
        qr = QRCode(4, QRErrorCorrectLevel.L)
        qr.addData(instance.qr_url)
        qr.make()
        image = qr.makeImage()

        #Save image to string buffer
        image_buffer = StringIO()
        image.save(image_buffer, format='JPEG')
        image_buffer.seek(0)

        #Here we use django file storage system to save the image.
        file_name = 'UrlQR_%s.jpg' % instance.id
        file_object = File(image_buffer, file_name)
        content_file = ContentFile(file_object.read())
        instance._already_saving = True
        instance.qr_image.save(file_name, content_file, save=True)

Upvotes: 3

DrewM
DrewM

Reputation: 1906

Your post save signal call save which calls the post save signal which calls save ...

This is basically an infinite loop which the runtime kills with the Max Recursion error.

Upvotes: 5

Related Questions