【问题标题】:Django doesn't recognize/can't find post_save edited field?Django 无法识别/找不到 post_save 编辑字段?
【发布时间】:2021-05-06 22:28:55
【问题描述】:

我正在尝试使用 post_save 模型信号创建一个独特的 SlugField。如果 SlugField 已经存在,则应在 slug 上附加一个数字以使其唯一。

但是,Django 似乎无法识别 SlugField 何时已经存在。

我正在使用单表继承的 MPTT 模型:

class Text(MPTTModel):
    type = models.CharField(max_length=255, blank=False)  # for STI. Essentially returns the class name.
    title = models.CharField(max_length=255, blank=True)
    slug = models.SlugField(max_length=255, blank=True)
    slug_order = models.CharField(max_length=255, blank=True)

    def __init__(self, *args, **kwargs):
        super(Text, self).__init__(*args, **kwargs)
        # If we don't have a subclass at all, then we need the type attribute to match
        # our current class.
        if not self.__class__.__subclasses__():
            self.type = self.__class__.__name__.lower()
        else:
            subclass = [
                x
                for x in self.__class__.__subclasses__()
                if x.__name__.lower() == self.type
            ]
            if subclass:
                self.__class__ = subclass[0]
            else:
                self.type = self.__class__.__name__.lower()

class Book(Text):
    objects = BookManager()

    class Meta:
        proxy = True

@receiver(post_save, sender=Book, dispatch_uid="create_book_slug")
def create_book_slug(sender, instance, **kwargs):
    slug = slugify(instance.title)
    slug_exists = Book.objects.filter(slug=slug).exists() # This always seems to be False
    counter = 1
    while slug_exists:
        counter += 1
        new_slug = f"{slug}-{counter}"
        slug_exists = Book.objects.filter(slug=new_slug).exists()
    if counter > 1:
        slug = f"{slug}-{counter}"
    instance.slug = slug

我的测试:

b1 = Book.objects.create(title="book book")
b2 = Book.objects.create(title="book book")

self.assertEqual(b1.slug, "book-book") # True
self.assertEqual(b2.slug, "book-book-2") # False - b2.slug gives "book-book"
self.assertEqual(b1.slug, b2.slug) # This is True... obviously not what I want.

self.assertEqual(Book.objects.filter(slug=b1.slug).exists(), True) # False. I have no idea why.

self.assertEqual(Book.objects.filter(title=b1.title).exists(), True) # True. This works.

我必须使用post_save,因为我实际上想利用默认 MPTT 字段(lftrghtlevelget_root() 等)我实际上还有另一个 STI 模型,称为 Chapter将使用slug_order:

class Chapter(Text):
    objects = ChapterManager()

    class Meta:
        proxy = True

@receiver(post_save, sender=Chapter, dispatch_uid="create_chapter_slug")
def create_chapter_slug(sender, instance, **kwargs):
    print(instance.get_root()) # This works and points to the Chapter's top parent
    print(instance.get_root().slug) # This doesn't work and returns nothing
    instance.slug = instance.get_root().slug

    # slug_order code below works
    order = instance.rght - instance.lft
    if instance.level == 1:
        instance.slug_order = order
    else:
        instance.slug_order = f"{instance.parent.slug_order}/{order}"

【问题讨论】:

    标签: django django-mptt


    【解决方案1】:

    看起来post_save 信号实际上并没有保存。

    b1 = Book.objects.create(title="book book")
    self.assertEqual(b1.slug, "book-book") # True
    
    b1.refresh_from_db()
    self.assertEqual(b1.slug, "") # True
    

    instance.save() 添加到post_save 接收器会产生递归错误。

    使用pre_save 代替create_book_slug 解决了我最初的问题。

    我的create_chapter_slug 实际上是另一个问题(我计算顺序的方法是错误的),我将在另一个线程上发布......

    【讨论】:

      猜你喜欢
      • 2016-08-11
      • 1970-01-01
      • 2020-05-07
      • 1970-01-01
      • 2018-02-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-21
      相关资源
      最近更新 更多