Reputation: 2238
I have followed the basic polls tutorial and I have tried to modify it to make it work for slugs but it's not working. I went from this in my views.py
def detail(request, article_id):
details = "blog/detail.html"
context = {
"article": get_object_or_404(Article, pk=article_id)
}
return render(request, details, context)
and
url(r'^(?P<article_id>[0-9]+)/$', views.detail, name='detail'),
to this in my views.py
def detail(request, slug):
details = "blog/detail.html"
context = {
"article": get_object_or_404(Article, slug)
}
return render(request, details, context)
and
url(r'^(?P<slug>[\w-]+)/$', views.detail, name='detail'),
this is my models.py
from django.db import models
from django.contrib.auth.models import User
class Article(models.Model):
author = models.ForeignKey(User)
title = models.CharField(max_length=250)
slug = models.SlugField()
body = models.TextField()
created = models.DateTimeField(auto_now=True)
def __str__(self):
return self.title
this is my admin.py
from django.contrib import admin
from .models import Article
@admin.register(Article)
class ArticleAdmin(admin.ModelAdmin):
prepopulated_fields = {"slug": ("title",)}
but it's not working. How Do I get the slugs to show in my url
Upvotes: 4
Views: 7269
Reputation: 10564
You're missing the parameter name in get_object_or_404
. Assuming that your Article
model has a SlugField
named slug
:
get_object_or_404(Article, slug=slug)
EDIT: User update the question providing the model. This part is no longer needed.
Since you didn't posted your Article
model, I'm gonna provide an example of how you should code it to make it compatible with my example:
from django.utils.text import slugify
from django.db import models
class Article(models.model):
#…
slug = models.SlugField(unique=True)
def save(self, *args, **kwargs):
self.slug = slugify(self.slug)
super(Article, self).save(*args, **kwargs)
Copied from this answer. Notice how we override the save method to automatically generate the slug. Might not be a good idea depending on your architecture. I'd recommend to call slugify
in a view or in a modelform like in this tutorial.
Upvotes: 1
Reputation: 47856
In your views, you need to pass slug
argument.
def detail(request, slug):
details = "blog/detail.html"
context = {
"article": get_object_or_404(Article, slug=slug) # pass slug
}
return render(request, details, context)
If you are creating Articles
using admin, then the slug
will get prepopulated using title
field. But, if you want to create an article
other than doing it in admin, you need to call slugify()
function explicitly in your model's save()
and assign it to the article
object before saving it.
You can do something like:
class Article(models.Model):
def save(self, *args, **kwargs):
self.slug = slugify(self.title) # set the slug explicitly
super(Article, self).save(*args, **kwargs) # call Django's save()
Note: Since you are using slug
instead of id
for detail
view, this means that no 2 articles should have the same slug
i.e. the same title
. Add unique=True
constraint in your model for handling this.
Upvotes: 5