How to prepopulate a slug field from a foreign key in Django


01.29.12 Posted in The Web by

The Emma Frost Comic Book Database was my first Django project when I was familiarizing myself with the web framework and the Python programming language.

The models for the comic book database seemed relatively easy, but I came across problems that I didn’t consider, such as prepopulating a slug field from a foreign key. The comic book Title is a foreign key that goes into the Issue model. Selecting a title from a drop-down list should automatically prepopulate the slug field if defined in the admin.py, right? Nope, it comes up blank and will only prepopulate character fields – which is most likely a front-end Javascript issue.

Thanks to Justin Myers, he came up with a simple, bang-your-head-on-the-desk solution for generating slugs from foreign keys that I’d like to share since it is a common question.

Here’s how to do it, given an abbreviated example of my models.py file:

[code lang="python"]class Title(models.Model):
    title = models.CharField(max_length=64)
    slug = models.SlugField()
    def get_absolute_url(self):
        return "/titles/%s" % self.slug
    def __unicode__(self):
        return self.title

class Issue(models.Model):
    title = models.ForeignKey(Title)
    number = models.CharField(max_length=20)
    slug = models.SlugField(blank=True)
    def __unicode__(self):
        return u'%s #%s' % (self.title, self.number)

    # Here is where the code you need starts.
    def save(self, *args, **kwargs):
    # Creates the slug, including the foreign key's slug.
        self.slug = str(self.title.slug)
        # Calls the parent save()
        super(Issue, self).save(*args, **kwargs)
        # Adds the number
        self.slug = str(self.title.slug) + '-' + str(self.number)
        # Calls the parent save() again
        super(Issue, self).save(*args, **kwargs)[/code]

So, for example, when you save the Issue model in the Django admin, the slug field generates something like this, comics.emmafrostfiles.com/issues/astonishing-x-men-12 – which, by the way, has one of my favorite variant covers!

I had about 900 issues that needed to be “slugged.” Of course, I didn’t click “save” on each issue 900 times – that would have been too tedious. Login to SSH and save all the objects in the model you need slugged:

>>> from myproject.comics.models import Issue
>>> for issue in Issue.objects.all():
... issue.save()

I actually ran into a problem that did not throw me an error – but it was a simple fix. Make sure your character length for the slugs are right. You’ll have to go into your database admin to edit the length.

Good luck!



One Response to “How to prepopulate a slug field from a foreign key in Django”

  1. Yavo says:

    Thank you!

Leave a Reply