How to create a unique slug in Django

mitchf picture mitchf · Sep 28, 2010 · Viewed 26.2k times · Source

I am trying to create a unique slug in Django so that I can access a post via a url like this: http://www.example.com/buy-a-new-bike_Boston-MA-02111_2

The relevant models:

class ZipCode(models.Model):
    zipcode = models.CharField(max_length=5)
    city = models.CharField(max_length=64)
    statecode = models.CharField(max_length=32)

class Need(models.Model):
    title = models.CharField(max_length=50)
    us_zip = models.CharField(max_length=5)
    slug = ?????

    def get_city():
        zip = ZipCode.objects.get(zipcode=self.us_zip)
        city = "%s, %s %s" % (zip.city, zip.statecode, zip.zipcode)
        return city

A sample ZipCode record:

  • zipcode = "02111"
  • city = "Boston"
  • statecode = "MA"

A sample Need record:

  • title = "buy a new bike"
  • us_zip = "02111"
  • slug = "buy-a-new-bike_Boston-MA-02111_2" (desired)

Any tips as to how to create this unique slug? Its composition is:

  • Need.title + "_" + Need.get_city() + "_" + an optional incrementing integer to make it unique. All spaces should be replaced with "-".

NOTE: My desired slug above assumes that the slug "buy-a-new-bike_Boston-MA-02111" already exists, which is what it has the "_2" appended to it to make it unique.

I've tried django-extensions, but it seems that it can only take a field or tuple of fields to construct the unique slug. I need to pass in the get_city() function as well as the "_" connector between the title and city. Anyone solved this and willing to share?

Thank you!

UPDATE

I'm already using django-extensions for its UUIDField, so it would be nice if it could also be usable for its AutoSlugField!

Answer

Srikanth Chundi picture Srikanth Chundi · Sep 28, 2010

I use this snippet for generating unique slug and my typical save method look like below

slug will be Django SlugField with blank=True but enforce slug in save method.

typical save method for Need model might look below

def save(self, **kwargs):
    slug_str = "%s %s" % (self.title, self.us_zip) 
    unique_slugify(self, slug_str) 
    super(Need, self).save(**kwargs)

and this will generate slug like buy-a-new-bike_Boston-MA-02111 , buy-a-new-bike_Boston-MA-02111-1 and so on. Output might be little different but you can always go through snippet and customize to your needs.