Django: как создать слизни в django?

Я хочу создать slug в django, я использовал slug = models.SlugField(unique=True). Теперь, когда я создаю пост со slug'ом learning-to-code, он работает, но если я создаю другой пост с тем же slug'ом learning-to-code, он показывает ошибку Unique Constraint Failed. Но я хочу создавать посты с тем же slug, есть ли способ сделать slug уникальным только для времени создания поста?

вот как выглядит моя модель

class Article(models.Model):
    title = models.CharField(max_length=200)
    description = models.TextField(blank=True, null=True)
    slug = models.SlugField(unique=True)
    user = models.ForeignKey('userauths.User', on_delete=models.SET_NULL, null=True)

Как я могу добиться этого?

Если вы просто хотите преобразовать заголовок в slug, но не хотите использовать его в качестве альтернативы основному ключу, вы можете использовать утилиту slugify django для преобразования заголовка при сохранении и хранения его в общем CharField.

https://docs.djangoproject.com/en/4.0/ref/utils/#django.utils.text.slugify

from django.utils.text import slugify

class Article(models.Model):
    title = models.CharField(max_length=200)
    description = models.TextField(blank=True, null=True)
    slug = models.CharField(max_length=300)
    user = models.ForeignKey('userauths.User', on_delete=models.SET_NULL, null=True)

    def save(self, *args, **kwargs):
        self.slug = slugify(self.title)
        return super().save(*args, **kwargs)

Вы можете использовать save для проверки slug перед добавлением, например:

from django.utils.text import slugify


def save(self, *args, **kwargs):
    if self._state.adding:
        self._generate_slug()
    super(Article, self).save(*args, **kwargs)

def _generate_slug(self):
    if self.slug:
        slug_candidate = slug_original = self.slug
    else:
        # To Generate New Slug If None, You can change
        slug_candidate = slug_original = slugify(self.title, allow_unicode=True)
        if not slug_candidate:
            slug_candidate = slug_original = lambda: random.randint(1, 10000000)
    # Check if Slug exists and add ( learning-to-code-1, learning-to-code-2,................)
    for i in itertools.count(1):
        if not Article.objects.filter(slug=slug_candidate).exists():
            break
        slug_candidate = '{}-{}'.format(slug_original, i)

    self.slug = slug_candidate

Создание постов с одинаковым slug не имеет особого смысла, так как slug используется для определения какого Article. Если два предмета имеют learning-to-code, то вы не можете определить какой из двух Article является правильным.

If your Article for example has a DateField, you can use this such that is works with both the date and the slug to determine the Article. The easist way to achieve that is likely with the django-autoslug package [PyPi]. This will work with a UniqueConstraint [Django-doc], such that the combination of the date and the slug is unique, so:

from autoslug import AutoSlugField
from django.conf import settings

class Article(models.Model):
    title = models.CharField(max_length=200)
    slug = AutoSlugField(populate_from='title', unique_with=['publish_date'])
    description = models.TextField(blank=True, null=True)
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET_NULL,
        null=True
    )
    publish_date = models.DateField(auto_now_add=True)

В urls.py необходимо добавить спецификации для даты, так:

path('<int:year>/<int:month>/<int:date>/<slug:slug>', some_view, name='article_detail')

затем в DetailView, или других представлениях, мы можем фильтровать по QuerySet с датой:

from datetime import date
from django.views.generic import DetailView

class ArticleDetailView(DetailView):
    model = Article
    
    def get_queryset(self, *args, **kwargs):
        return super().get_queryset(*args, **kwargs).filter(
            publish_date=date(self.kwargs['year'], self.kwargs['month'], self.kwargs['day'])
        )

Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.

from django.utils.text import slugify

Добавьте эту функцию в свой класс

def save(self,*args,**kwargs):
    self.slug=slugify(self.slug)
    super().save(*args,**kwargs)
Вернуться на верх