Django: how to create slugs in django?
Creating posts with the same slug makes not much sense, since a slug is used to determine what Article
is used. If two items have learning-to-code
, then you can not determine which of the two Article
s is the right one.
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)
The urls.py
will need to add specifications for the date, so:
path('<int:year>/<int:month>/<int:date>/<slug:slug>', some_view, name='article_detail')
then in a DetailView
, or other views, we can filter on the QuerySet
with the date:
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.
How to auto generate slug from my Album model in django 2.0.4
Django autogenerates the slug from the string object you pass to the slug field.
# Import slugify to generate slugs from strings
from django.utils.text import slugify
class Album(models.Model):
artist = models.CharField(max_length=250)
album_title = models.CharField(max_length=250)
genre = models.CharField(max_length=100)
album_logo = models.CharField(max_length=1000,blank=True)
slug = models.SlugField(unique=True)
def save(self, *args, **kwargs):
self.slug = slugify(self.album_title)
super(Album, self).save(*args, **kwargs)
def __str__(self):
return self.album_title
class Song(models.Model):
album = models.ForeignKey(Album, on_delete=models.CASCADE)
artist = models.CharField(max_length=250, blank=True)
file_type = models.CharField(max_length=10)
song_title = models.CharField(max_length=100)
slug = models.SlugField(max_length=100, unique=True)
def save(self, *args, **kwargs):
self.slug = slugify(self.song_title)
super(Song, self).save(*args, **kwargs)
def __str__(self):
return self.artist
How to create a unique slug in Django
I use this snippet for generating unique slug and my typical save method look like below
slug will be Django SlugField with blank=True but enforce slug in save method.
typical save method for Need model might look below
def save(self, **kwargs):
slug_str = "%s %s" % (self.title, self.us_zip)
unique_slugify(self, slug_str)
super(Need, self).save(**kwargs)
and this will generate slug like buy-a-new-bike_Boston-MA-02111 , buy-a-new-bike_Boston-MA-02111-1 and so on. Output might be little different but you can always go through snippet and customize to your needs.
How to generate slug based on title of post in django?
I recommend checking out the Django documentation for slugify. You will need to override the save method of your model to do this, so your new code will most likely look something like this:
from django.utils.text import slugify
slug=models.SlugField()
def save(self,*args,**kwargs):
self.slug=slugify(self.title)
super(Post,self).save(*args,**kwargs)
I would keep in mind the unique parameter that you can set to either true or false in your slugfield.
How to create a slug from non-English values?
To solve this problem you can use the unidecode
and slugify
.
you should install it by pip install unidecode
from unidecode import unidecode
from django.template import defaultfilters
slug = defaultfilters.slugify(unidecode(input_text))
example:
import unidecode
a = unidecode.unidecode('привет')
the answer will be ('privet') #this is just an example in russian.
and after that you can apply slugify
Django - How to create a slug url that works?
So guys, I finally figured it out. My slug url is now working perfectly.
The error was actually coming from my list page. The url to the detail view wasn't written well. I didn't include a namespace. So instead of <a href="{{ post.get_absolute_url }}">
it becomes <a href="{% url 'blog:blog_post' post.slug %}">
I also deleted redundant lines of codes in my models and my views page.
Here is what it looks like now.
models.py:
class Post(models.Model):
STATUS_CHOICES = (
('draft', 'Draft'),
('published', 'Published'),
)
title = models.CharField(max_length=200)
slug = models.SlugField(max_length=200, default="")
author = models.ForeignKey('auth.User', on_delete=models.CASCADE)
body = models.TextField()
publish = models.DateTimeField(default=timezone.now)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
status = models.CharField(max_length=10, choices=STATUS_CHOICES, default='draft')
class Meta:
ordering = ('-publish',)
def __str__(self):
return self.title
views.py
class BlogHomePageView(ListView):
model = Post
template_name = 'blog/index.html'
context_object_name = 'posts'
class PostDetailView(DetailView):
model = Post
template_name = 'blog/post.html'
context_object_name = 'post'
blog/urls.py:
urlpatterns = [
path('', BlogHomePageView.as_view(), name='blog_home'),
path('post/<slug:slug>/', PostDetailView.as_view(), name='blog_post'),
]
list page(index.html):
{% extends 'blog/base.html' %}
{% block title %}Home{% endblock %}
<!-- Page Header -->
{% block page_header %}
<div class="site-heading">
<h1>Toluwalemi's Blog</h1>
<span class="subheading">Official Blog</span>
</div>
{% endblock %}
<!-- Main Content -->
{% block content %}
{% for post in posts %}
<div class="post-preview">
<a href="{% url 'blog:blog_post' post.slug %}">
<h2 class="post-title">
{{ post.title }}
</h2>
How to Save Slug Automatic in Django?
exclude
the slug
field from Django Admin by creating a ModelAdmin class as below,
# admin.py
class ArticleAdmin(admin.ModelAdmin):
exclude = ('slug',)
admin.site.register(Article, ArticleAdmin)
Related Topics
Matplotlib Semi-Log Plot: Minor Tick Marks Are Gone When Range Is Large
Why Does Indexing Numpy Arrays with Brackets and Commas Differ in Behavior
Recursive Definitions in Pandas
Prevent Python from Caching the Imported Modules
Why Does Appending to One List Also Append to All Other Lists in My List of Lists
Downloading a Directory Tree with Ftplib
Weighted Choice Short and Simple
Pygame 2 Dimensional Movement of an Enemy Towards the Player, How to Calculate X and Y Velocity
When Do You Use 'Self' in Python
Selenium Webdriver: How to Download a PDF File with Python
How to Create Collapsible Box in Pyqt
Error Loading Dll in Python, Not a Valid Win32 Application
Customising Code of Qt Designer Widget
The Main() Function Appears to Not Work
Matplotlib Semi-Log Plot: Minor Tick Marks Are Gone When Range Is Large