Commits

Andy Mikhailenko committed 13205ad

Added ability to customize `slugify` function and autoincremented index separator within field definition.

Comments (0)

Files changed (3)

autoslug/__init__.py

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

autoslug/fields.py

     AutoSlugField can also perform the following tasks on save:
 
     - populate itself from another field (using `populate_from`),
-    - use custom `slugify` function (can be defined in :doc:`settings`), and
+    - use custom `slugify` function (using `slugify` or :doc:`settings`), and
     - preserve uniqueness of the value (using `unique` or `unique_with`).
 
     None of the tasks is mandatory, i.e. you can have auto-populated non-unique
         as the name of attribute from which to fill the slug. If callable is given,
         it should accept `instance` parameter and return a value to fill the slug
         with.
+    :param sep: string: if defined, overrides default separator for automatically
+        incremented slug index (i.e. the "-" in "foo-2").
+    :param slugify: callable: if defined, overrides `AUTOSLUG_SLUGIFY_FUNCTION`
+        defined in :doc:`settings`.
     :param unique: boolean: ensure total slug uniqueness (unless more precise
         `unique_with` is defined).
     :param unique_with: string or tuple of strings: name or names of attributes
         # autoslugify value from a custom callable
         # (ex. usage: user profile models)
         slug = AutoSlugField(populate_from=lambda instance: instance.user.get_full_name())
+
+        # autoslugify value using custom `slugify` function
+        from autoslug.settings import slugify as default_slugify
+        def custom_slugify(value):
+            return default_slugify(value).replace('-', '_')
+        slug = AutoSlugField(slugify=custom_slugify)
     """
     def __init__(self, *args, **kwargs):
         kwargs['max_length'] = kwargs.get('max_length', 50)
         if isinstance(self.unique_with, basestring):
             self.unique_with = (self.unique_with,)
 
+        self.slugify = kwargs.pop('slugify', slugify)
+        assert hasattr(self.slugify, '__call__')
+
+        self.index_sep = kwargs.pop('sep', SLUG_INDEX_SEPARATOR)
+
         # backward compatibility
         if kwargs.get('unique_with_date'):
             warn('Using unique_with_date="foo" in AutoSlugField is deprecated, '\
                 print 'Failed to populate slug %s.%s from %s' % \
                     (instance._meta.object_name, self.name, self.populate_from)
 
-        slug = slugify(value)
+        slug = self.slugify(value)
 
         if not slug:
             # no incoming value,  use model name
         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:
                 # the slug is not unique; change once more
                 index += 1
                 # ensure the resulting string is not too long
-                tail_length = len(sep) + len(str(index))
+                tail_length = len(self.index_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)
+                data = dict(slug=orig_slug, sep=self.index_sep, index=index)
+                slug = '%(slug)s%(sep)s%(index)d' % data
             except model.DoesNotExist:
                 # slug is unique, no model uses it
                 return slug

autoslug/tests.py

 from django.db.models import Model, CharField, DateField, ForeignKey
 
 # this app
+from autoslug.settings import slugify as default_slugify
 from autoslug.fields import AutoSlugField
 
 
     custom_primary_key = CharField(primary_key=True, max_length=1)
     name = CharField(max_length=200)
     slug = AutoSlugField(populate_from='name', unique=True)
+
+
+custom_slugify = lambda value: default_slugify(value).replace('-', '_')
+class ModelWithCustomSlugifier(Model):
+    """
+    >>> a = ModelWithCustomSlugifier.objects.create(slug='hello world!')
+    >>> b = ModelWithCustomSlugifier.objects.create(slug='hello world!')
+    >>> b.slug
+    'hello_world-2'
+    """
+    slug = AutoSlugField(unique=True, slugify=custom_slugify)
+
+
+class ModelWithCustomSeparator(Model):
+    """
+    >>> a = ModelWithCustomSeparator.objects.create(slug='hello world!')
+    >>> b = ModelWithCustomSeparator.objects.create(slug='hello world!')
+    >>> b.slug
+    'hello-world_2'
+    """
+    slug = AutoSlugField(unique=True, sep='_')
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.