Dori's Python Life in Words Journal

Create a canonical URL (get_absolute_url)


Canonicalisation in the context of URLs (a canonical URL) refers to the process of selecting a preferred URL when there are multiple URLs for the same or similar content.

This avoids duplicate content problems as it provides one "canonical" URL for similar or identical content on multiple URL's. If a site is accessible from multiple URLs, search engines may index them separately, which dilutes their SEO value.

In the Django model, we use the get_absolut_url() method to create a canonical URL in Django.

# blog/models.py

from django.db import models
from django.urls import reverse
from django.utils import timezone


class PublishedManager(models.Manager):
    def get_queryset(self):
        return super().get_queryset().filter(status=Post.Status.PUBLISHED)


class Post(models.Model):
    class Status(models.TextChoices):
        DRAFT = "DF", "Draft"
        PUBLISHED = "PB", "Published"

    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()
    publish = models.DateTimeField(default=timezone.now)
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)
    status = models.CharField(max_length=2, choices=Status, default=Status.DRAFT)

    objects = models.Manager()  # The default manager.
    published = PublishedManager()  # Our custom manager.

    class Meta:
        ordering = ["-publish"]
        indexes = [
            models.Index(fields=["publish"]),
        ]

    def __str__(self):
        return self.title

    def get_absolute_url(self):
        return reverse(
            "blog:post_detail",
            args=[self.slug],
        )

Legend:

    • get_absolute_url(): The get_absolute_url() method is used to define a canonical URL for a model instance in Django. By defining this method in a model, you can reference the URL of a specific object consistently throughout your templates and views. This approach centralizes the URL definition, making your code more organized and maintainable.

The get_absolute_url() can be used as a reference to the detail template of a Post instance.

<!-- blog/templates/post/list.html -->

{% extends "base.html" %}

{% block title %} Django Blog {% endblock %}

{% block content %}
  <h1>My Blog</h1>
  {% for post in posts %}
    <h2>
      <a href="{{ post.get_absolute_url }}">
        {{ post.title }}
      </a>
    </h2>
  <p class="date">
    Published {{ post.publish }} by {{ post.author }}
  </p>
  {{ post.body|truncatewords:30|linebreaks }}
  {% endfor %}
{% endblock %}

Legend:

    • <a href="{{ post.get_absolute_url }}">: The equivalent is <a href="{% url 'blog:post_detail' post.slug %}>.


Designed by BootstrapMade and modified by DoriDoro