tags:

views:

5861

answers:

4

I am trying to create a SlugField in Django.

I created this simple model:

from django.db import models

class test(models.Model):
    q = models.CharField(max_length=30)
    s = models.SlugField()

I then do this:

>>> from mysite.books.models import test
>>> t=test(q="aa a a a", s="b b b b")
>>> t.s
'b b b b'
>>> t.save()
>>> t.s
'b b b b'
>>>

I was expecting b-b-b-b

+22  A: 

You will need use the slugify function.

>>> from django.template.defaultfilters import slugify
>>> slugify("b b b b")
u'b-b-b-b'
>>>

So this should work, but I have not tested it yet:

class test(models.Model):
    q = models.CharField(max_length=30)
    s = models.SlugField()

    def save(self):
        self.s = slugify( self.q )
        super( test, self ).save()
Buddy
shy have a special model type? why not just slugify CharFields?
Johnd
SlugFields set db_index=True by default, and also use a form field by default that has a validation regex to require valid slugs (if represented in a ModelForm or in the admin). You can do those things manually with a CharField if you prefer, it just makes the intention of your code less clear. Also, don't forget the prepopulate_fields ModelAdmin setting, if you want JS-based auto-prepopulate in the admin.
Carl Meyer
As Dingle said below in his answer, you'll need to replace `def save(self):` with `def save(self, *args, **kwargs):` in order to avoid errors from being thrown when writing something like `test.objects.create(q="blah blah blah")`.
Liam
+7  A: 

If you're using the admin interface to add new items of your model, you can set up a ModelAdmin for it in your admin.py, which automates the entering of a slug:

class ClientAdmin(admin.ModelAdmin):
    prepopulated_fields = {'slug': ('name',)}
admin.site.register(Client, ClientAdmin)

Here, when the user enters a value in the admin form for the name field, the slug will be automatically populated with the correct slugified name.

henrym
+5  A: 

In most cases the slug should not change, so you really only want to calculate it on first save:

class test(models.Model):
    q = models.CharField(max_length=30)
    s = models.SlugField(editable=False) # hide from admin

    def save(self):
        if not self.id:
            self.s = slugify(self.q)

        super(test, self).save()
thepeer
+9  A: 

A small correction to Thepeer's answer: To override save() function in model classes, better add arguments to it:

def save(self, *args, **kwargs):
    if not self.id:
        self.s = slugify(self.q)

    super(test, self).save(*args, **kwargs)

Otherwise, test.objects.create(q="blah blah blah") will result in a force_insert error (unexpected argument).

Dingle
You're absolutely right! Thanks for the correction.
thepeer