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)