39
class Foo(models.Model):
    title = models.CharField(max_length=20)
    slug = models.SlugField()

Is there a built-in way to get the slug field to autopopulate based on the title? Perhaps in the Admin and outside of the Admin.

gak
  • 29,596
  • 24
  • 111
  • 150
ashchristopher
  • 21,525
  • 16
  • 44
  • 49

6 Answers6

67

for Admin in Django 1.0 and up, you'd need to use

prepopulated_fields = {'slug': ('title',), }

in your admin.py

Your key in the prepopulated_fields dictionary is the field you want filled, and the value is a tuple of fields you want concatenated.

Outside of admin, you can use the slugify function in your views. In templates, you can use the |slugify filter.

There is also this package which will take care of this automatically: https://pypi.python.org/pypi/django-autoslug

Krystian Cybulski
  • 9,717
  • 9
  • 65
  • 94
camflan
  • 14,605
  • 3
  • 20
  • 18
  • https://docs.djangoproject.com/en/dev/ref/models/fields/#slugfield https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.prepopulated_fields – Wtower Feb 10 '17 at 09:29
6

Outside the admin, see this django snippet. Put it in your .save(), and it'll work with objects created programmatically. Inside the admin, as the others have said, use prepopulated_fields.

AdamKG
  • 12,063
  • 2
  • 36
  • 43
3

For pre-1.0:

slug = models.SlugField(prepopulate_from=('title',))

should work just fine

For 1.0, use camflan's

Community
  • 1
  • 1
Nick Sergeant
  • 29,184
  • 12
  • 34
  • 44
2

You can also use pre_save django signal to populate slug outside of django admin code. See Django signals documentation.

Ajax slug uniqueness validation will be useful too, see As-You-Type Slug Uniqueness Validation @ Irrational Exuberance

carefulweb
  • 327
  • 1
  • 4
  • I wonder with this method if this work with bulk insertion? I'm not sure :/ – FlogFR Jul 23 '14 at 11:50
  • 1
    you have to make a workaround for bulk operation, you can check this thread for some insights http://stackoverflow.com/questions/23744795/django-emulate-database-trigger-behavior-on-bulk-insert-update-delete – carefulweb Jul 31 '14 at 09:54
2

Thought I would add a complete and up-to-date answer with gotchas mentioned:

1. Auto-populate forms in Django Admin

If you are only concerned about adding and updating data in the admin, you could simply use the prepopulated_fields attribute

class ArticleAdmin(admin.ModelAdmin):
    prepopulated_fields = {"slug": ("title",)}

admin.site.register(Article, ArticleAdmin)

2. Auto-populate custom forms in templates

If you have built your own server-rendered interface with forms, you could auto-populate the fields by using either the |slugify tamplate filter or the slugify utility when saving the form (is_valid).

3. Auto-populating slugfields at model-level with django-autoslug

The above solutions will only auto-populate the slugfield (or any field) when data is manipulated through those interfaces (the admin or a custom form). If you have an API, management commands or anything else that also manipulates the data you need to drop down to model-level.

django-autoslug provides the AutoSlugField-fields which extends SlugField and allows you to set which field it should slugify neatly:

class Article(Model):
    title = CharField(max_length=200)
    slug = AutoSlugField(populate_from='title')

The field uses pre_save and post_save signals to achieve its functionality so please see the gotcha text at the bottom of this answer.

4. Auto-populating slugfields at model-level by overriding save()

The last option is to implement this yourself, which involves overriding the default save() method:

    class Article(Model):
        title = CharField(max_length=200)
        slug = SlugField()

    def save(self, *args, **kwargs):
        self.slug = slugify(self.title)
        super(Job, self).save(*args, **kwargs)

NOTE: Bulk-updates will bypass your code (including signals)

This is a common miss-understanding by beginners to Django. First you should know that the pre_save and post_save signals are directly related to the save()-method. Secondly the different ways to do bulk-updates in Django all circumvent the save()-method to achieve high performance, by operating directly on the SQL-layer. This means that for the example model used in solution 3 or 4 above:

  • Article.objects.all().update(title='New post') will NOT update the slug of any article
  • Using bulk_create or bulk_update on the Article model will NOT update the slug of any article.
  • Since the save()-method is not called, no pre_save or post_save signals will be emitted.

To do bulk updates and still utilize code-level constraints the only solution is to iterate objects one by one and call its save()-method, which has drastically less performance than SQL-level bulk operations. You could of course use triggers in your database, though that is a totally different topic.

Andreas Bergström
  • 11,092
  • 5
  • 49
  • 46
0

autoslug has worked quite well for me in the past. Although I've never tried using it with the admin app.

Jon Lemmon
  • 3,299
  • 2
  • 21
  • 37