Question

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.

Was it helpful?

Solution

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

OTHER TIPS

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.

For pre-1.0:

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

should work just fine

For 1.0, use camflan's

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

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

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top