Introduction
By creating an Search engine optimization (SEO) friendly URL, you will structure the pattern of a URL in a more meaningful way and make it easier for your content to be indexed.
To avoid a URL like www.example.com/blog/1/, create a canonical URL (get_absolute_url()) in the models.py file and we can change the URL pattern of the canonical URL to a SEO friendly URL.
Here is the Post model:
# models.py
from django.db import models
from django.urls import reverse
class Post(models.Model):
    title = models.CharField(max_length=250)
    slug = models.SlugField(max_length=250)
    author = models.ForeignKey(
        "account.User", on_delete=models.CASCADE, related_name="blog_posts"
    )
    body = models.TextField()
    def __str__(self):
        return self.title
This code is a function-based view (FBV) to display one single Post instance on the website:
# views.py
from django.shortcuts import render, get_object_or_404
from blog.models import Post
def post_detail(request, pk):
    post = get_object_or_404(
        Post,
        pk=pk
    )
    return render(request, "post/detail.html", {"post": post})
And the url pattern for the view:
# urls.py
from django.urls import path
from blog import views
urlpatterns = [
    path('<int:pk>/', views.post_detail, name='post_detail')
]
Now we create the get_absolute_url() method in the Post model. We will use the model attribute slug to generate the SEO friendly URL. The URL pattern will change from www.example.com/blog/pk/ (www.example.com/blog/1/) (1 is the pk (id) of the post instance) and the new URL will look like: www.example.com/blog/slug/ (www.example.com/blog/name-of-the-post/).
# models.py
from django.db import models
from django.urls import reverse
class Post(models.Model):
    title = models.CharField(max_length=250)
    slug = models.SlugField(max_length=250, unique_for_date="publish")
    author = models.ForeignKey(
        "account.User", on_delete=models.CASCADE, related_name="blog_posts"
    )
    body = models.TextField()
    def __str__(self):
        return self.title
    def get_absolute_url(self):
        return reverse(
            "blog:post_detail",
            args=[self.slug],
        )
The get_absolute_url() method in Django is used to define the canonical URL for a model object, making it easier to refer to specific objects in templates or views. It returns the absolute URL path as a string, which can be used for redirection or linking. We often use the reverse() function inside get_absolute_url() because it resolves the URL based on the view name and arguments, ensuring a reliable and maintainable URL pattern that adapts to changes in the project’s URL configuration.
Now, we update the view, to exchange the pk with the slug:
# views.py
from django.shortcuts import render, get_object_or_404
from blog.models import Post
def post_detail(request, slug):
    post = get_object_or_404(
        Post,
        slug=post
    )
    return render(request, "post/detail.html", {"post": post})
Don't forget to update the url pattern, and pass the slug as an argument:
# urls.py
from django.urls import path
from blog import views
urlpatterns = [
    path('<slug:post>/', views.post_detail, name='post_detail')
]
- Link to the get_absolute_url()method in Django documentation
- Link to the reverse()method in Django documentation
 

 
    
Top comments (0)