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!
Thank you!