Django RecursionError:比较中超过了最大递归深度

时间:2020-04-20 11:30:02

标签: python django

我已经看到很多这样的错误,但是没有一个与我正在搜索的错误相匹配,因此请帮助我了解在将信号保存为Django时我在哪里出错。我知道该save方法正在无限运行,但是由于我是初学者,我如何才能停止在代码中执行?

from django.db import models
import random
import os
from .utils import unique_slug_generator
from django.db.models.signals import pre_save, post_save

class ProductQuerySet(models.query.QuerySet):    
    def active(self):
        return self.filter(active=True)

    def featured(self):
        return self.filter(featured=True, active=True)

class ProductManager(models.Manager):
    def get_queryset(self):
        return ProductQuerySet(self.model, using=self._db)

    def all(self):
        return self.get_queryset().active()

    def features(self):
        return self.get_queryset().featured()

    def get_by_id(self, id):
        qs=self.get_queryset().filter(id=id)
        if qs.count() ==1:
            return qs.first()
        return None

# Create your models here.
class Product(models.Model):
    title = models.CharField(max_length=120)
    slug = models.SlugField(blank=True, unique=True)
    description = models.TextField()
    price = models.DecimalField(decimal_places=2, max_digits=20, default=39.99)
    image = models.ImageField(upload_to='products/', null=True, blank=True)
    featured = models.BooleanField(default=False)
    active = models.BooleanField(default=True)    

    objects=ProductManager()

    def __str__(self):
        return self.title

    def __unicode__(self):
        return self.title

def product_pre_save_receiver(sender, instance, *args, **kwargs):
    if not instance.slug:
        instance.slug = unique_slug_generator(instance)

pre_save.connect(product_pre_save_receiver, sender=Product)

这可能是model.py

from django.utils.text import slugify

import random
import string

def random_string_generator(size=10, chars=string.ascii_lowercase+string.digits):
    return ''.join(random.choice(chars) for _ in range(size))

def unique_slug_generator(instance, new_slug=None):
    if new_slug is not None:
        slug = new_slug
    else:
        slug = slugify(instance.title)

    klass = instance.__class__
    qs_exists = klass.objects.filter(slug=slug).exists()
    if qs_exists:
        ne_slug = "{slug}-{randstr}".format(
            slug=slug,
            randstr=random_string_generator(size=4)
            )
        return unique_slug_generator(instance, new_slug=new_slug)
    return slug

这是我的utils.py

堆栈跟踪

System check identified no issues (0 silenced).
April 20, 2020 - 16:27:28
Django version 3.0.5, using settings 'ecommerce.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
Internal Server Error: /admin/products/product/add/
Traceback (most recent call last):
  File "C:\ProgramData\Anaconda3\lib\site-packages\django\core\handlers\exception.py", line 34, in inner
    response = get_response(request)
  File "C:\ProgramData\Anaconda3\lib\site-packages\django\core\handlers\base.py", line 115, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "C:\ProgramData\Anaconda3\lib\site-packages\django\core\handlers\base.py", line 113, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:\ProgramData\Anaconda3\lib\site-packages\django\contrib\admin\options.py", line 607, in wrapper
    return self.admin_site.admin_view(view)(*args, **kwargs)
  File "C:\ProgramData\Anaconda3\lib\site-packages\django\utils\decorators.py", line 130, in _wrapped_view
    response = view_func(request, *args, **kwargs)
  File "C:\ProgramData\Anaconda3\lib\site-packages\django\views\decorators\cache.py", line 44, in _wrapped_view_func
    response = view_func(request, *args, **kwargs)
  File "C:\ProgramData\Anaconda3\lib\site-packages\django\contrib\admin\sites.py", line 231, in inner
    return view(request, *args, **kwargs)
  File "C:\ProgramData\Anaconda3\lib\site-packages\django\contrib\admin\options.py", line 1638, in add_view
    return self.changeform_view(request, None, form_url, extra_context)
  File "C:\ProgramData\Anaconda3\lib\site-packages\django\utils\decorators.py", line 43, in _wrapper
    return bound_method(*args, **kwargs)
  File "C:\ProgramData\Anaconda3\lib\site-packages\django\utils\decorators.py", line 130, in _wrapped_view
    response = view_func(request, *args, **kwargs)
  File "C:\ProgramData\Anaconda3\lib\site-packages\django\contrib\admin\options.py", line 1522, in changeform_view
    return self._changeform_view(request, object_id, form_url, extra_context)
  File "C:\ProgramData\Anaconda3\lib\site-packages\django\contrib\admin\options.py", line 1565, in _changeform_view
    self.save_model(request, new_object, form, not add)
  File "C:\ProgramData\Anaconda3\lib\site-packages\django\contrib\admin\options.py", line 1081, in save_model
    obj.save()
  File "C:\ProgramData\Anaconda3\lib\site-packages\django\db\models\base.py", line 746, in save
    force_update=force_update, update_fields=update_fields)
  File "C:\ProgramData\Anaconda3\lib\site-packages\django\db\models\base.py", line 771, in save_base
    update_fields=update_fields,
  File "C:\ProgramData\Anaconda3\lib\site-packages\django\dispatch\dispatcher.py", line 175, in send
    for receiver in self._live_receivers(sender)
  File "C:\ProgramData\Anaconda3\lib\site-packages\django\dispatch\dispatcher.py", line 175, in <listcomp>
    for receiver in self._live_receivers(sender)
  File "F:\Ecom\DjangoEcommerce\products\models.py", line 69, in product_pre_save_receiver
    instance.slug = unique_slug_generator(instance)
  File "F:\Ecom\DjangoEcommerce\products\utils.py", line 22, in unique_slug_generator
    return unique_slug_generator(instance, new_slug=new_slug)
  File "F:\Ecom\DjangoEcommerce\products\utils.py", line 22, in unique_slug_generator
    return unique_slug_generator(instance, new_slug=new_slug)
  File "F:\Ecom\DjangoEcommerce\products\utils.py", line 22, in unique_slug_generator
    return unique_slug_generator(instance, new_slug=new_slug)
  [Previous line repeated 920 more times]
  File "F:\Ecom\DjangoEcommerce\products\utils.py", line 16, in unique_slug_generator
    qs_exists = klass.objects.filter(slug=slug).exists()
  File "C:\ProgramData\Anaconda3\lib\site-packages\django\db\models\query.py", line 777, in exists
    return self.query.has_results(using=self.db)
  File "C:\ProgramData\Anaconda3\lib\site-packages\django\db\models\sql\query.py", line 537, in has_results
    return compiler.has_results()
  File "C:\ProgramData\Anaconda3\lib\site-packages\django\db\models\sql\compiler.py", line 1121, in has_results
    return bool(self.execute_sql(SINGLE))
  File "C:\ProgramData\Anaconda3\lib\site-packages\django\db\models\sql\compiler.py", line 1138, in execute_sql
    sql, params = self.as_sql()
  File "C:\ProgramData\Anaconda3\lib\site-packages\django\db\models\sql\compiler.py", line 490, in as_sql
    extra_select, order_by, group_by = self.pre_sql_setup()
  File "C:\ProgramData\Anaconda3\lib\site-packages\django\db\models\sql\compiler.py", line 51, in pre_sql_setup
    self.setup_query()
  File "C:\ProgramData\Anaconda3\lib\site-packages\django\db\models\sql\compiler.py", line 42, in setup_query
    self.select, self.klass_info, self.annotation_col_map = self.get_select()
  File "C:\ProgramData\Anaconda3\lib\site-packages\django\db\models\sql\compiler.py", line 218, in get_select
    select.append((RawSQL(sql, params), alias))
  File "C:\ProgramData\Anaconda3\lib\site-packages\django\db\models\expressions.py", line 711, in __init__
    output_field = fields.Field()
  File "C:\ProgramData\Anaconda3\lib\site-packages\django\db\models\fields\__init__.py", line 156, in __init__
    if isinstance(choices, collections.abc.Iterator):
  File "C:\ProgramData\Anaconda3\lib\abc.py", line 139, in __instancecheck__
    return _abc_instancecheck(cls, instance)
RecursionError: maximum recursion depth exceeded in comparison

1 个答案:

答案 0 :(得分:2)

我建议您尝试使用while循环而不是递归,因为这比递归有效得多,并且不会影响程序堆栈。

也许是这样的:

def unique_slug_generator(instance, new_slug=None):
    if new_slug is not None:
        slug = new_slug
    else:
        slug = slugify(instance.title)

    klass = instance.__class__

    while True:
        if not klass.objects.filter(slug=slug).exists():
            return slug

        slug = "{slug}-{randstr}".format(
            slug=slug,
            randstr=random_string_generator(size=4)
            )