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 theUser
model [Django-doc] directly. For more information you can see the referencing theUser
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)