简体   繁体   English

Django 两个或多个模型的唯一 slug 字段

[英]Django unique slug field for two or more models

I have such structure:我有这样的结构:

class Category(models.Model):
    name = models.CharField(max_length=255, validators=[MinLengthValidator(3)])
    parent = models.ForeignKey('self', blank=True, null=True,
                               related_name='children',
                               on_delete=models.CASCADE
                               )
    slug = models.SlugField(max_length=255, null=False, unique=True)


class Product(models.Model):
    name = models.CharField(max_length=255, validators=[MinLengthValidator(3)])
    to_category = models.ForeignKey(Category, on_delete=models.SET_NULL,
                                    blank=True, null=True,
                                    )
    slug = models.SlugField(max_length=255, null=False, unique=True)

I have created one category with slug "test".我创建了一个带有 slug“test”的类别。 When I try to create new category with slug "test" I got warning message and it is Ok.当我尝试使用 slug“test”创建新类别时,我收到警告消息,没问题。 But If I try to create product with slug "test" I dont have warning and this is not good in my case.但是,如果我尝试使用 slug“test”创建产品,我不会收到警告,这对我来说并不好。 Is there a solution or method to validate slug field for uniqueness with Product and Category model?是否有解决方案或方法来验证 slug 字段与产品和类别 model 的唯一性?

You can override the save method for each, and then check if the given slug already exists for a product or category.您可以覆盖每个方法的保存方法,然后检查给定的 slug 是否已经存在于产品或类别中。

def is_slug_unique(slug):
    product_exists = Product.objects.filter(slug=slug).exists()
    category_exists = Category.objects.filter(slug=slug).exists()
    if product_exists or category_exists:
        return False
    else:
        return True

class Category(models.Model)
    ...

    def save(self, *args, **kwargs):
        slug_unique = is_slug_unique(self.slug)
        if not slug_unique:
            # do something when the slug is not unique
        else:
            # do something when the slug is unique
            super().save(*args, **kwargs)

class Product(models.Model)
    ...

    def save(self, *args, **kwargs):
        slug_unique = is_slug_unique(self.slug)
        if not slug_unique:
            # do something when the slug is not unique
        else:
            # do something when the slug is unique
            super().save(*args, **kwargs)


An idea might be to create a Slug model that stores all the slugs, optionally with a backreference to the object:一个想法可能是创建一个存储所有 slug 的Slug model,可以选择向后引用 object:

class Slug(models.Model):
    slug = models.SlugField(max_length=255, primary_key=True)

Then the slugs in your models are ForeignKey s to that Slug model, and you check if such slug already exists:然后你的模型中的 slug 是那个Slug model 的ForeignKey s,你检查这样的 slug 是否已经存在:

from django.core.exceptions import ValidationError


class Product(models.Model):
    name = models.CharField(max_length=255, validators=[MinLengthValidator(3)])
    to_category = models.ForeignKey(
        Category, on_delete=models.SET_NULL, blank=True, null=True
    )
    slug = models.ForeignKey(Slug, on_delete=models.PROTECT)

    def validate_slug(self):
        if self.pk is not None and Slug.objects.filter(pk=self.slug_id).exclude(
            product__pk=self.pk
        ):
            raise ValidationError('The slug is already used.')

    def clean(self, *args, **kwargs):
        self.validate_slug()
        return super().clean(*args, **kwargs)

    def save(self, *args, **kwargs):
        self.validate_slug()
        return super().save(*args, **kwargs)

That being said, often overlapping slugs for different entity types are allowed.也就是说,通常允许不同实体类型重叠的 slug。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM