Andy Mikhailenko avatar Andy Mikhailenko committed d0933d7

Fixed issue #3: slug can exceed field length if prepopulating from longer field. (Thanks to Ollie Rutherfurd)

Comments (0)

Files changed (6)

 who have submitted patches, reported bugs, added translations and
 generally made django-autoslug better:
 
-* Blake Imsland,
+* Steve Steiner
+* Blake Imsland
+* Ollie Rutherfurd
 * Your Name Here  ;)

autoslug/__init__.py

 __author__  = 'Andy Mikhailenko'
 __license__ = 'GNU Lesser General Public License (GPL), Version 3'
 __url__     = 'http://bitbucket.org/neithere/django-autoslug/'
-__version__ = '1.1.2'
+__version__ = '1.1.3'

autoslug/fields.py

 # app
 from autoslug.settings import slugify
 
+
+SLUG_INDEX_SEPARATOR = '-'    # the "-" in "foo-2"
+
 class AutoSlugField(SlugField):
     """
     AutoSlugField is an extended SlugField able to automatically resolve name
         model = instance.__class__
         field_name = self.name
         index = 1
+        if self.max_length < len(slug):
+            slug = slug[:self.max_length]
         orig_slug = slug
+        sep = SLUG_INDEX_SEPARATOR
         # keep changing the slug until it is unique
         while True:
             try:
                     raise model.DoesNotExist
                 # the slug is not unique; change once more
                 index += 1
-                slug = '%s-%d' % (orig_slug, index)
+                # ensure the resulting string is not too long
+                tail_length = len(sep) + len(str(index))
+                combined_length = len(orig_slug) + tail_length
+                if self.max_length < combined_length:
+                    orig_slug = orig_slug[:self.max_length - tail_length]
+                # re-generate the slug
+                slug = '%s%s%d' % (orig_slug, sep, index)
             except model.DoesNotExist:
                 # slug is unique, no model uses it
                 return slug

Empty file added.

autoslug/tests.py

+# -*- coding: utf-8 -*-
+#
+#  Copyright (c) 2008—2009 Andy Mikhailenko
+#
+#  This file is part of django-autoslug.
+#
+#  django-autoslug is free software under terms of the GNU Lesser
+#  General Public License version 3 (LGPLv3) as published by the Free
+#  Software Foundation. See the file README for copying conditions.
+#
+
+
+from django.db.models import Model, CharField
+from autoslug.fields import AutoSlugField
+
+
+class Foo(Model):
+    name = CharField(max_length=200)
+    slug = AutoSlugField(populate_from='name', unique=True)
+
+__doc__ = """
+>>> long_name = 'x' * 250
+>>> foo = Foo(name=long_name)
+>>> foo.save()
+>>> len(foo.slug)
+50
+>>> bar = Foo(name=long_name)
+>>> bar.save()
+>>> [len(x.slug) for x in Foo.objects.all()]
+[50, 50]
+"""
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+from django.conf import settings
+from django.core.management import call_command
+
+
+settings.configure(
+    INSTALLED_APPS=('autoslug',),
+    DATABASE_ENGINE='sqlite3'
+)
+
+if __name__ == "__main__":
+    call_command('test', 'autoslug')
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.