Question

I have seen a variety of different methods for generating unique slugs: Ex. 1, Ex.2, Ex. 3, Ex. 4, etc. etc.

I want to create unique slugs upon saving a ModelForm. If my models are like:

class Phone(models.Model):
    user = models.ForeignKey(User)
    slug = models.SlugField(max_length=70, unique=True)
    year = models.IntegerField()
    model = models.ForeignKey('Model')
    series = models.ForeignKey('Series')

Say that the Phone object has the following values (via submitted ModelForm):

Phone.user = dude
Phone.year = 2008
Phone.model = iphone
Phone.series = 4S

I want the url for this object to appear like:

http://www.mysite.com/phones/dude-2008-iphone-4S 

I understand that I should use slugify via either signals or over-riding the save method to make this happen. But if user dude creates a second 2008 iphone 4S object, what the best way to create a unique slug for this object? I want the additional objects's url to look like:

http://www.mysite.com/phones/dude-2008-iphone-4S-2

and

http://www.mysite.com/phones/dude-2008-iphone-4S-3
http://www.mysite.com/phones/dude-2008-iphone-4S-4
#...etc ...

After googling, it seems like there are a variety of different methods for creating slugs in django, which has been confusing when trying to figure out best practices.

Thanks a lot for any advice and clarification on this issue!

Was it helpful?

Solution 2

I ended up using This Django Snippet to over-ride the save method of Phone in my models.py:

def save(self, **kwargs):
    slug_str = "%s %s %s %s" % (self.user, self.year, self.model, self.series)
    unique_slugify(self, slug_str)
    super(Phone, self).save()

But thanks to jpic for the contribution.

OTHER TIPS

First things first, naming a field "Model" is a bad idea it can only create confusion. Finding an alternative would be a good idea.

The easiest solution is to set the slug in a pre_save signal:

from django.db.models.signals import pre_save
from django.template.defaultfilters import slugify


def phone_slug(sender, instance, **kwargs):
    slug = u'%s-%s-%s-%s' % (slugify(instance.user.username), instance.year,
        slugify(instance.model), slugify(instance.series))
    instance.slug = slug

    if instance.pk:
        other_phones = Phone.objects.exclude(pk=instance.pk)
    else:
        other_phones = Phone.objects.all()

    i = 2
    exists = other_phones.filter(slug=instance.slug).count() > 0
    while exists:
        instance.slug = u'%s-%s' % (slug, i)
        i++
pre_save.connect(phone_slug, sender=Phone)

Or maybe use django-autoslug, it would look something like this:

slug = AutoSlugField(unique_with=['user__username', 'year', 'model__name', 'series__name'])
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top