How to add django slug url for blogs



We will start by defining the term slug, A slug is a short label for something, containing only letters, numbers, underscores or hyphens. They’re generally used in URLs. In the initial days of learning django we pass the id to views to get the requested blog and same id is displayed in url e.g. http://example.com/blog/2 - 2 is the id of the blog for which the user has requested, but in production when users are visiting your pages this url must be customized to display some information rather than simply displaying the ids. This we can achieve by using a slug field in our blogs models.py.

We will also add some code to models.py  to make this process of generating slug as automated. So let’s start with models.py. We are expecting that you have your blogs app ready in your django project.

Go to your blogs models.py file and with slug field it should look similar to this

from django.db import models

class Blogs(models.Model):

    Title=models.CharField(max_length=200)

    slug=models.SlugField()

    Body=models.TextField()

    Created=models.DateTimeField(auto_now_add=True)

 

Note: SlugField requires unique value and hence it cannot be Null, so remember if you have already existing migrated model with data in it then set this slug field as below else you will get error while migrating your model.

slug=models.SlugField(null=True,blank=True)

 

With the above model if you try to create a blog post, you have to manually define the slug field every time. And to avoid this we can create a process where this can be automated creating unique slug url for each blog.

from django.db import models

from django.db.models.signals import pre_save

from django.utils.text import slugify

 

class Blogs(models.Model):

    Title=models.CharField(max_length=200)

    slug=models.SlugField(blank=True)

    Body=models.TextField()

    Created=models.DateTimeField(auto_now_add=True)

 

    def __str__(self):

        return self.Title

 

def create_slug(instance, new_slug=None):

    slug=slugify(instance.Title)

    if new_slug is not None:

        slug=new_slug

    qs=Blogs.objects.filter(slug=slug).order_by("-id")

    exists=qs.exists()

    if exists:

        new_slug= "%s-%s"%(slug,qs.first().id)

        return create_slug(instance,new_slug=new_slug)

    return slug

 

def pre_save_blog_receiver(sender, instance, *args, **kwargs):

    if not instance.slug:

        instance.slug=create_slug(instance)

 

pre_save.connect(pre_save_blog_receiver, sender=Blogs)

 

We used Title to make slug, so slugify method will turn the title in lowercase and separate each word with hyphen instead of spaces. For example if your blog title is My First Blog then your slug url created will be my-first-blog.

Add below code in blogs urls.py

from django.urls import path

from . import views

 

urlpatterns = [

    path('blogs/',views.home,name="home"),

    path('blogs/<slug:slug>',views.detail,name="detail"),

]

 

Your views.py should look similar to this

from django.shortcuts import render

from .models import Blogs

 

def home(request):

    items=Blogs.objects.all()

    return render(request,"blogs/home.html",{'items':items})

 

def detail(request,slug):

    item=Blogs.objects.get(slug=slug)

    return render(request, "blogs/detail.html", {'item': item})

 

Now the slug url will look like this.

http://127.0.0.1:8000/blogs/my-first-blog

 

Feel free to post a comment if you have any questions. Thank you!


Published : July 11, 2020