article

Sunday, June 21, 2020

How to use Django Slug Field


How to use Django Slug Field

In this tutorial we will add slugs to a Django website.

A slug is a short label for something, containing only letters, numbers, underscores or hyphens. They’re generally used in URLs.


models.py
#models.py
from django.db import models

from django.urls import reverse
from django.utils.text import slugify

class Article(models.Model):
    title = models.CharField(max_length=255)
    body = models.TextField()
    slug = models.SlugField(max_length=200, unique=True)

    def __str__(self):
        return self.title

    def get_absolute_url(self):
        return reverse('article_detail', kwargs={'slug': self.slug})
  
    def save(self, *args, **kwargs):
        value = self.title
        self.slug = slugify(value, allow_unicode=True)
        super().save(*args, **kwargs)
create a migrations file for this change, then add it to our database via migrate.

python manage.py makemigrations myapp
python manage.py migrate

New database table added
CREATE TABLE myapp_article (
    id    INTEGER       NOT NULL
                        PRIMARY KEY AUTOINCREMENT,
    title VARCHAR (255) NOT NULL,
    body  TEXT          NOT NULL,
    slug  VARCHAR (50)  UNIQUE
); urls.py
#urls.py
from django.contrib import admin  
from django.urls import path
from myapp import views  
from django.conf.urls import url

from myapp.views import ArticleListView, ArticleDetailView

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', ArticleDetailView.as_view(), name='article_detail'),
    path('', ArticleListView.as_view(), name='article_list'),
]
admins.py
#admin.py
from django.contrib import admin

from myapp.models import Article

class ArticleAdmin(admin.ModelAdmin):
    list_display = ('title', 'body',)
    prepopulated_fields = {'slug': ('title',)}

admin.site.register(Article, ArticleAdmin)
views.py
#views.py
from django.shortcuts import render, redirect

from django.views.generic import ListView, DetailView

from myapp.models import Article

class ArticleListView(ListView):
    model = Article
    template_name = 'article_list.html'


class ArticleDetailView(DetailView):
    model = Article
    template_name = 'article_detail.html'
templates/article_list.html
#templates/article_list.html
{% extends 'base.html' %}

{% block pagetitle %}Blog{% endblock %}

{% block content %}
<h1>Articles</h1>
{% for article in object_list %}
  <ul>
    <li><a href="{{ article.get_absolute_url }}">{{ article.title }}</a></li>
  </ul>
{% endfor %}
{% endblock %}
templates/article_detail.html
//templates/article_detail.html
{% extends 'base.html' %}

{% block pagetitle %}Blog{% endblock %}

{% block content %}
<div>
  <h2>{{ object.title }}</h2>
  <p>{{ object.body }}</p>
</div>
{% endblock %}
templates/base.html
//templates/base.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" name="viewport" content="width=device-width, initial-scale=1"/>
 <title>{% block title %}How to use Django Slug Field {% endblock %}</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
  <a class="navbar-brand" href="#">Cairocoders</a>
  <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
    <span class="navbar-toggler-icon"></span>
  </button>
  <div class="collapse navbar-collapse" id="navbarNavAltMarkup">
    <div class="navbar-nav">
   <a class="nav-item nav-link active" href="">Home</a>
    </div>
  </div>
</nav>
 <div class="container" style="padding:20px;">
    <div class="col-md-12 well">
        <h3 class="text-primary">How to use Django Slug Field</h3>
        <hr style="border-top:1px dotted #ccc;"/>
  {% block content %} {% endblock %}
    </div>
    </div> 
</body>
</html>

Related Post