gpt4 book ai didi

django - 如何防止Django中的post_save递归?

转载 作者:行者123 更新时间:2023-12-04 13:15:57 26 4
gpt4 key购买 nike

在Django中使用signal时遇到一些问题。
post_save发生递归,因为函数内部存在instance.save()

但是奇怪的是只有一种情况发生递归。

  • 不发生递归的情况。
  • models.py
    class Product(TimeStampedModel):
    name = models.CharField(max_length=120)
    slug = models.SlugField(null=True, blank=True)
    description = models.CharField(max_length=400, blank=True)
    is_active = models.BooleanField(default=True)

    objects = ProductManager()

    class Meta:
    ordering = ('-created',)

    def __str__(self):
    return self.name

    def get_absolute_url(self):
    return reverse(
    "products:product_detail",
    kwargs={
    "slug": self.slug,
    }
    )
    signals.py
    @receiver(post_save, sender=Product)
    def post_save_product(sender, instance, created, **kwargs):
    if not instance.slug:
    instance.slug = slugify(instance.name, allow_unicode=True)
    instance.save()

    当我使用 Product创建 Product.objects.create()时,不会发生递归。
  • 发生递归的情况
  • models.py
    class Variation(TimeStampedModel):
    COLOR_CHOICES = (
    ('black', '흑백'),
    ('single', '단색'),
    ('multi', '컬러'),
    )
    price = models.DecimalField(
    decimal_places=2,
    max_digits=15,
    blank=True,
    null=True,
    )
    product = models.ForeignKey(Product)
    color = models.CharField(
    max_length=10,
    choices=COLOR_CHOICES,
    default='흑백'
    )
    is_active = models.BooleanField(default=True)

    class Meta:
    ordering = ('product',)

    def __str__(self):
    return "{product} - {color}".format(
    product=self.product,
    color=self.color
    )
    signals.py
    @receiver(post_save, sender=Variation)
    def post_save_variation(sender, instance, created, **kwargs):
    if not instance.price:
    if instance.color == '흑백':
    instance.price = 40000
    elif instance.color == '단색':
    instance.price = 50000
    elif instance.color == '컬러':
    instance.price = 60000
    instance.save()

    这种情况下发生递归错误:
    File "/Users/Chois/.pyenv/versions/spacegraphy/lib/python3.5/site-packages/django/db/models/base.py", line 708, in save
    force_update=force_update, update_fields=update_fields)
    File "/Users/Chois/.pyenv/versions/spacegraphy/lib/python3.5/site-packages/django/db/models/base.py", line 745, in save_base
    update_fields=update_fields, raw=raw, using=using)
    File "/Users/Chois/.pyenv/versions/spacegraphy/lib/python3.5/site-packages/django/dispatch/dispatcher.py", line 192, in send
    response = receiver(signal=self, sender=sender, **named)
    File "/Users/Chois/Dropbox/Workspace/django/spacegraphy-project/spacegraphy/products/signals/post_save.py", line 24, in post_save_variation
    instance.save()
    File "/Users/Chois/.pyenv/versions/spacegraphy/lib/python3.5/site-packages/django/db/models/base.py", line 708, in save
    force_update=force_update, update_fields=update_fields)
    File "/Users/Chois/.pyenv/versions/spacegraphy/lib/python3.5/site-packages/django/db/models/base.py", line 745, in save_base
    update_fields=update_fields, raw=raw, using=using)
    File "/Users/Chois/.pyenv/versions/spacegraphy/lib/python3.5/site-packages/django/dispatch/dispatcher.py", line 192, in send
    response = receiver(signal=self, sender=sender, **named)
    File "/Users/Chois/Dropbox/Workspace/django/spacegraphy-project/spacegraphy/products/signals/post_save.py", line 24, in post_save_variation
    instance.save()
    File "/Users/Chois/.pyenv/versions/spacegraphy/lib/python3.5/site-packages/django/db/models/base.py", line 708, in save
    force_update=force_update, update_fields=update_fields)
    File "/Users/Chois/.pyenv/versions/spacegraphy/lib/python3.5/site-packages/django/db/models/base.py", line 736, in save_base
    updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
    File "/Users/Chois/.pyenv/versions/spacegraphy/lib/python3.5/site-packages/django/db/models/base.py", line 796, in _save_table
    base_qs = cls._base_manager.using(using)
    File "/Users/Chois/.pyenv/versions/spacegraphy/lib/python3.5/site-packages/django/db/models/manager.py", line 122, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
    File "/Users/Chois/.pyenv/versions/spacegraphy/lib/python3.5/site-packages/django/db/models/manager.py", line 214, in get_queryset
    return self._queryset_class(model=self.model, using=self._db, hints=self._hints)
    File "/Users/Chois/.pyenv/versions/spacegraphy/lib/python3.5/site-packages/django/db/models/query.py", line 171, in __init__
    self.query = query or sql.Query(self.model)
    File "/Users/Chois/.pyenv/versions/spacegraphy/lib/python3.5/site-packages/django/db/models/sql/query.py", line 155, in __init__
    self.where = where()
    RecursionError: maximum recursion depth exceeded while calling a Python object

    我认为这两种情况具有相同的结构,但只有一种情况发生递归。

    不知道为什么。需要帮助,谢谢。

    最佳答案

    保存前先断开信号,然后重新连接。 https://docs.djangoproject.com/en/1.10/topics/signals/#disconnecting-signals

    def post_save_product(sender, instance, **kwargs):
    post_save.disconnect(post_save_product, sender=sender)
    instance.do_stuff()
    instance.save()
    post_save.connect(post_save_product, sender=sender)
    post_save.connect(post_save_product, sender= Product)

    关于django - 如何防止Django中的post_save递归?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39481625/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com