Is there an easy way to populate SlugField from CharField?

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: Clark501 | Posted: 01-10-2021






Answer 1

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: Miranda919 | Posted: 02-11-2021



Answer 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().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: Kimberly118 | Posted: 02-11-2021



Answer 3

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: Chloe238 | Posted: 02-11-2021



Answer 4

For pre-1.0:

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

should work just fine

For 1.0, use camflan's

Answered by: Wilson271 | Posted: 02-11-2021



Answer 5

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: Andrew890 | Posted: 02-11-2021



Answer 6

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: Sienna472 | Posted: 02-11-2021



Answer 7

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

Answered by: Wilson327 | Posted: 02-11-2021



Answer 8

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

Answered by: John710 | Posted: 02-11-2021



Similar questions

python - Django SlugField pretty SEO URL

I want to create SEO friendly product URLS:- Following is my url:- url(r'^ad/(?P<slug>[-\w\d]+),(?P<pk>\d+)/$', (views.AdDetail.as_view()), name='item_detail'), My views:- class AdDetail(View): template_name = 'ads/ad_detail.html' def get(self, request, slug, pk, *args, **kwargs): ad = AdDetailAPI.get_ad(pk) return render(request...


python - How do you create links using slugfield in Django generic listview class?

How to you create links (i.e. href) using SlugField for the output of Django's ListView generic class? Right now I can list all persons in the database using the code below but I want links using slug when clicked will show the person's description. models.py class Person(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=30) slug = models.SlugFie...


python - What type of options apply to the SlugField?

If we see the documentation of Django, we see this; SlugField class SlugField(max_length=50, **options) **options : is a kwargs but Django doesn't show me anything about of what other parameter I can use it. I appreciate if somebody help me.


python - Django PK to slugfield

I want to change my urls from PK to slugfields, but on one field this is not working. urlpatterns = [ ... url(r'^indexed/$', views.QuestionsIndexListView.as_view(), name='index_all'), url(r'^ask-question/$', views.CreateQuestionView.as_view(), name='ask_question'), url(r'^(?P<slug>[-\w]+)/$', views.QuestionDetailView.as_view(), name='detail'), url(r'^propose-answer/(?P<question_...


python - Have slugfield be as the same value as other field

I am trying to get a Slugfield saved with the same value as another field. I can't get this to work.. I trie the following (as well as countless of others like changing the datacenter textfield to a slugfield.. Didn't work at all) # View that saves the model to the database: class save_device(CreateView): model = AddDevice form = add_device fields = ['merk', 'model', 'locatie', 'datace...






Still can't find your answer? Check out these communities...



PySlackers | Full Stack Python | NHS Python | Pythonist Cafe | Hacker Earth | Discord Python



top