Search code examples
djangoslug

Slugfield URL implementation in Django


So, I am having some difficulty trying to slugify a title field in my model and still have it return the proper information.

Currently, a user can follow the url, if the list in their account exists under this regular expression:

url(r'^user/(?P<username>\w+)/list/(?P<listname>\w+)/$', mylistpage, name='lists'),

The issue I face is that the user can have a list containing spaces, but the regex bases their url off their list name. I am wanting to implement a slug url, but still have it retrieve the correct model/object information.

I am trying to have a slug field and then pre-populate it based on the list name, but I am lost at how this implementation is supposed to work. Much appreciation in advance from any insight.

Model

class newlist(models.Model):


    user = models.ForeignKey(User)
    list_name = models.CharField(max_length = 100,)
    picture = models.ImageField(upload_to='profiles/', default = "/media/profiles/default.jpg")
    slugurl = models.SlugField(default = slugurl(self))

    def __str__(self):
        return self.list_name

    def slugurl(self):
        return slugify(self.list_name)

Views

def mylistpage(request, username, listname):

    context = RequestContext(request)

    #make sure that the user is authenticated
    if username == request.user.username:
        #If the user is authenticated, then perform the following functions to the page
        if request.user.is_authenticated():
            #Store the current user request object into a variable
            user = User.objects.get(username=username)

            #Store the list name to the item that starts with the url input
            listname = request.user.newlist_set.filter(list_name__iexact=listname)

            listitems = request.user.newlist_set.all()
            if not listname:
                return redirect('/notfound')
    else:
        return redirect('/notfound')

    return render_to_response('listview.html', {'lista': listname}, context)

Solution

  • I have used django-autoslug to great success. You can find a live example here.

    SlugField is just a char field with a little syntactic sugar.

    You will want to name your slug just slug so django can find it automatically in the URL resolution and passes the right parameter to views.

    Your amended code would look like:

    from autoslug import AutoSlugField
    from django.db import models
    
    class Newlist(models.Model): # Classes start with uppercase names by default
        user = models.ForeignKey(User)
        list_name = models.CharField(max_length = 100,)
        picture = models.ImageField(upload_to='profiles/', default = "/media/profiles/default.jpg")
        slug = AutoSlugField(populate_from='list_name')
        def __str__(self):
            return self.list_name
    

    Your View:

    def mylistpage(request,username, slug):
    
        context = RequestContext(request)
    
        #make sure that the user is authenticated
        if username == request.user.username:
            #If the user is authenticated, then perform the following functions to the page
            if request.user.is_authenticated():
                #Store the current user request object into a variable
                user = User.objects.get(username=username)
    
                #Store the list name to the item that starts with the url input
                listname = request.user.newlist_set.filter(slug=slug)
    
                listitems = request.user.newlist_set.all()
                if not listname:
                    return redirect('/notfound')
        else:
            return redirect('/notfound')
    
        return render_to_response('listview.html', {'lista': listname}, context)
    

    urls.py

    url(r'^user/(?P<username>\w+)/list/(?P<slug>[\w-]+)/$', mylistpage, name='lists'),