Add slug field to Django Model

Python Methods and Functions

Suppose we have a blog post titled "Django's Book by Geeksforgeeks" with primary key id = 2. We could link to this post at www.python.engineering/posts/2 ... Or we can refer to the title, for example www.python.engineering/posts/The Django book by Geeksforgeeks
But the problem space is invalid in the URL, they should be replaced with by% 20, is ugly, which makes it the following www.python.engineering/posts/The%20Django%20book% 20by% 20pythonengineering but does not resolve the meaning of the URL. Another option could be www.python.engineering/posts/the-django-book-by-pythonengineering
So the slug is now the-django-book-by-pythonengineering . All letters are lowercase and spaces are replaced with hyphens -.

Let's assume our blog models look something like this.

STATUS_CHOICES = (

( 'draft' , ' Draft' ),

( 'published' , ' Published' ),

)

  

class Post (models.Model):

title   = models.CharField (max_length = 250 )

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

text = models.TextField ()

published_at = models.DateTimeField (auto_now_add = True )

updated = models.DateTimeField (auto_now = True )

 

status = models .CharField (max_length = 10 , choices = STATUS_CHOICES,

default = ' draft' )

 

 

  class Meta:

  ordering = ( '-published_at' ,)

  

def __ str __ ( self ):

return self . title

Adding Slugify to our project:
Now we need to find a way to automatically convert the title to a slug.

Note. Add a new util.py file in the same directory where you saved settings.py .

M We want this script to run every time a new instance of the Post model is created. For this we will use signals.

import string

from django.utils.text import slugify

 

def random_string_generator (size = 10 , chars = string.ascii_lowercase + string.digits):

return '' .join (random.choice (chars) for _ in   range (size))

 

def unique_slug_generator (instance, new_slug = None ):

if new_slug is not None :

slug = new_slug

  else :

slug = slugify (instance.title)

  Klass = instance .__ class__

qs_exists = Klass.objects. filter (slug = slug) .exists ()

 

if qs_exists:

new_slug = " {slug} - {randstr} " . format (

slug = slug, randstr = random_string_generator (size = 4 ))

 

return unique_slug_generator (instance, new_slug = new_slug)

return slug

Signals in Django:
In many cases, when there is a change in the model instance, we need to take some action. Django provides us with an elegant way to handle these situations. Signals — these are utilities that allow you to associate events with actions. We can develop a function that will run when the signal is called.

In the models.py file of the posts app where the Post model was defined, add it to the same file:

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

if not instance.slug:

instance.slug = unique_slug_generator (instance)

 

 

pre_save.connect (pre_save_receiver, sender = Post)

The pre_save_receiver function must be placed separately outside the Post model.

Note: in urls.py edit the detail path with path (& # 39; posts / & # 39 ;, detail) . In views.py edit the detail function with

def detail (request , slug):

q = Post.objects. filter (slug__iexact = slug)

if q.exists ():

  q = q.first ()

  else :

  return HttpResponse ( '& lt; h1 & gt; Post Not Found & lt; / h1 & gt;' )

context = {

 

'post' : q

  }

return render (request, ' posts / details.html' , context)

The final step is to add the link to the HTML file & lt; a href = Location / posts / layout career program a .slug} Object class being asserted = managed btn-primarytially & gt; View & lt; / a & gt ;. We are now ready to go to 127.0.0.1:8000/posts/title-you-have-added and it will show you the details.html page.





Tutorials