Is there an easy way to populate SlugField from CharField?

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.

Asked By: ashchristopher

||

Answers:

For pre-1.0:

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

should work just fine

For 1.0, use camflan’s

Answered By: Nick Sergeant

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

Answered By: camflan

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.

Answered By: AdamKG

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

Answered By: carefulweb

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

Answered By: Jon Lemmon

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().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.

Answered By: Andreas Bergström

Auto-populating slugfields at model-level with the built-in django slugify:

models.py

from django.db import models


class Place:
    name = models.CharField(max_length=50)
    slug_name = models.SlugField(max_length=50)

signals.py

from django.db.models.signals import pre_save
from django.dispatch import receiver
from django.template.defaultfilters import slugify as django_slugify

from v1 import models


@receiver(pre_save, sender=models.Place)
def validate_slug_name(sender, instance: models.Place, **kwargs):
    instance.slug_name = django_slugify(instance.name)

Credits to: https://github.com/justinmayer/django-autoslug/blob/9e3992296544a4fd7417a833a9866112021daa82/autoslug/utils.py#L18

Answered By: Iasmini Gomes
prepopulated_fields = {'slug': ('title',), }
Answered By: RockEpz
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.