【发布时间】: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 字段(lft、rght、level、get_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