74👍
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
8👍
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.
- [Django]-Django models avoid duplicates
- [Django]-How to use the 'reverse' of a Django ManyToMany relationship?
- [Django]-In a Django QuerySet, how to filter for "not exists" in a many-to-one relationship
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
.
- [Django]-Django admin and showing thumbnail images
- [Django]-Using Basic HTTP access authentication in Django testing framework
- [Django]-Django South – table already exists
3👍
For pre-1.0:
slug = models.SlugField(prepopulate_from=('title',))
should work just fine
For 1.0, use camflan’s
- [Django]-Django: dependencies reference nonexistent parent node
- [Django]-How to make two django projects share the same database
- [Django]-Model not showing up in django admin
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
- [Django]-Sending an SMS to a Cellphone using Django
- [Django]-Constructing Django filter queries dynamically with args and kwargs
- [Django]-Django REST Framework : "This field is required." with required=False and unique_together
- [Django]-Django or Ruby-On-Rails?
- [Django]-How can I fill up form with model object data?
- [Django]-Django – "Incorrect type. Expected pk value, received str" error
1👍
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)
- [Django]-How can I get MINIO access and secret key?
- [Django]-Django: Fat models and skinny controllers?
- [Django]-Make the first letter uppercase inside a django template
0👍
autoslug has worked quite well for me in the past. Although I’ve never tried using it with the admin app.
- [Django]-What's the difference between ContentType and MimeType?
- [Django]-Django upgrading to 1.9 error "AppRegistryNotReady: Apps aren't loaded yet."
- [Django]-Request.POST.get('sth') vs request.POST['sth'] – difference?