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.
You will need to use the slugify function.
>>> from django.template.defaultfilters import slugify
>>> slugify("b b b b")
u'b-b-b-b'
>>>
You can call slugify automatically by overriding the save method:
class Test(models.Model):
q = models.CharField(max_length=30)
s = models.SlugField()
def save(self, *args, **kwargs):
self.s = slugify(self.q)
super(Test, self).save(*args, **kwargs)
Be aware that the above will cause your URL to change when the q field is edited, which can cause broken links. It may be preferable to generate the slug only once when you create a new object:
class Test(models.Model):
q = models.CharField(max_length=30)
s = models.SlugField()
def save(self, *args, **kwargs):
if not self.id:
# Newly created object, so set slug
self.s = slugify(self.q)
super(Test, self).save(*args, **kwargs)
There is corner case with some utf-8 characters
Example:
>>> from django.template.defaultfilters import slugify
>>> slugify(u"test ąęśćółń")
u'test-aescon' # there is no "l"
This can be solved with Unidecode
>>> from unidecode import unidecode
>>> from django.template.defaultfilters import slugify
>>> slugify(unidecode(u"test ąęśćółń"))
u'test-aescoln'
A small correction to Thepeer's answer: To override save() function in model classes, better add arguments to it:
from django.utils.text import slugify
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).
If you're using the admin interface to add new items of your model, you can set up a ModelAdmin in your admin.py and utilize prepopulated_fields to automate 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.
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()
Use prepopulated_fields in your admin class:
class ArticleAdmin(admin.ModelAdmin):
prepopulated_fields = {"slug": ("title",)}
admin.site.register(Article, ArticleAdmin)
If you don't want to set the slugfield to Not be editable, then I believe you'll want to set the Null and Blank properties to False. Otherwise you'll get an error when trying to save in Admin.
So a modification to the above example would be::
class test(models.Model):
q = models.CharField(max_length=30)
s = models.SlugField(null=True, blank=True) # Allow blank submission in admin.
def save(self):
if not self.id:
self.s = slugify(self.q)
super(test, self).save()
I'm using Django 1.7
Create a SlugField in your model like this:
slug = models.SlugField()
Then in admin.py define prepopulated_fields;
class ArticleAdmin(admin.ModelAdmin):
prepopulated_fields = {"slug": ("title",)}
You can look at the docs for the SlugField to get to know more about it in more descriptive way.
来源:https://stackoverflow.com/questions/837828/how-do-i-create-a-slug-in-django