Django уникальное поле slug для двух или более моделей
У меня есть такая структура:
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)
Я создал одну категорию с меткой "test". Когда я пытаюсь создать новую категорию с меткой "test", я получаю предупреждение, но это нормально. Но если я пытаюсь создать продукт с slug "test", я не получаю предупреждения, и это не очень хорошо в моем случае. Есть ли решение или метод для проверки поля slug на уникальность в модели продукта и категории?
Вы можете переписать метод сохранения для каждого, а затем проверить, существует ли уже данный 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)
Идея может заключаться в создании модели Slug
, которая хранит все слизни, опционально с обратной ссылкой на объект:
class Slug(models.Model):
slug = models.SlugField(max_length=255, primary_key=True)
Тогда слизни в ваших моделях ForeignKey
относятся к этой модели 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)
При этом часто допускается перекрытие слогов для различных типов сущностей.