4

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

losee
  • 2,190
  • 3
  • 29
  • 55

2 Answers2

5

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.

Rahul Gupta
  • 46,769
  • 10
  • 112
  • 126
1

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.

Community
  • 1
  • 1
Saturnix
  • 10,130
  • 17
  • 64
  • 120
  • There are some inconsistencies: `reference_slug` vs `slug` vs `s`. Also, I think you wanted to write `slugify(self.title)` or something like that, instead of `slugify(self.slug)` (what's the point of making a slug out of a slug?) – Andrea Corbellini Dec 25 '15 at 18:23
  • @Saturnix your code doesn't work. I've posted my model as well – losee Dec 25 '15 at 18:46
  • @Andrea Corbellini: Very simple: SlugField doesn't automatically slugify your text. SlugField works exactly like a CharField. Ioose: code has been updated considering your newly updated question. – Saturnix Dec 25 '15 at 18:46
  • @Saturnix this is the error I get using your answer Reverse for 'detail' with arguments '(1,)' and keyword arguments '{}' not found. 1 pattern(s) tried: ['blog/(?P[-\\m]+)/$'] – losee Dec 25 '15 at 18:55
  • the url I see in this error (`['blog/(?P[-\\m]+)/$']`) is different from the one I see in your urls.py – Saturnix Dec 25 '15 at 18:56