Also, if you look some questions from stackoverflow. You can see they use /question_id/slug-text structure for their URLs. We can find too much examples like this.
I'm going to apply this slug feature for my project that exists. Open models.py in the application folder called blog. Define a new field for Post model as slug:
....
class Post(models.Model):
title = models.CharField(max_length=400)
content = models.TextField()
slug = models.SlugField(unique=True)
pub_date = models.DateTimeField(auto_now_add=True)
categories = models.ManyToManyField(Category)
author = models.ForeignKey(User, on_delete=models.CASCADE)
image = models.ImageField(upload_to='image/', null=True)
def __str__(self):
return self.title
class Meta:
ordering = ['-pub_date',]
...
I set unique as True to avoid url conflicts. However there are another two important points that I want emphazise them here. The first thing is about the posts already exist in the database. If we want to try to update this model in the database, probably it will cause a problem because of the old posts. In this point, we are in the second important thing that is about generating slug automatically. We can solve the problem with this solution. Also, we don't have to type custom slug all the time, this will be optional if you want. Therefore, I will override method called save in the post model:
from django.db import models
from django.contrib.auth.models import User
from django.utils.text import slugify
...
class Post(models.Model):
title = models.CharField(max_length=400)
content = models.TextField()
slug = models.SlugField(blank=True, unique=True)
pub_date = models.DateTimeField(auto_now_add=True)
categories = models.ManyToManyField(Category)
author = models.ForeignKey(User, on_delete=models.CASCADE)
image = models.ImageField(upload_to='image/', null=True, blank=True)
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
super(Post, self).save(*args, **kwargs)
def __str__(self):
return self.title
class Meta:
ordering = ['-pub_date',]
...
After these changes, I will update the database with makemigrations and then migrate command.
I want to update url routing for the post detail view:
from django.urls import path
from .views import *
urlpatterns = [
path('', IndexView.as_view(), name="index"),
path('about', about, name="about"),
path('post/<slug:slug>/', DetailView.as_view(), name="detail"),
]
Probably, we can't open the old posts. So let's update these slug fields of the old posts in the admin panel:
Save them like in the above and then open again old post in blog. I got this error about pk. Probably it's about comment. Because I call comments with pk value of the posts. Let's change it as slug and try again. I changed it DetailView:
....
class DetailView(generic.DetailView):
model = Post
template_name = 'detail.html'
def get_context_data(self,**kwargs):
context = super(DetailView,self).get_context_data(**kwargs)
context['comments']=Comment.objects.all().filter(post = get_object_or_404(Post, slug=self.kwargs['slug']))
return context
def post(self, request, pk):
post = get_object_or_404(Post, pk=pk)
new_comment = Comment(
username= request.POST.get('comment-username'),
content= request.POST.get('comment-textarea'),
post = post
)
new_comment.save()
return redirect(request.META['HTTP_REFERER'])
...
and the result is like this:
So, let's create a new post but don't define a slug for it and yes we got it:
If we try to create post with same the post title, it will be occured error after the save operation. That's because we define slug field as unique. I think we've learned important information about slugs. Good work!
No comments:
Post a Comment