added save_order option, added django 1.8, dropped unsupported django version

This commit is contained in:
Val Neekman 2015-04-11 23:26:36 -04:00
parent 471908cc28
commit e283a1c3ee
9 changed files with 170 additions and 69 deletions

58
.gitignore vendored
View file

@ -1,5 +1,57 @@
*.pyc
MANIFEST
dist/
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
# C extensions
*.so
# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*,cover
# Translations
*.mo
*.pot
# Django stuff:
*.log
# Sphinx documentation
docs/_build/
# PyBuilder
target/

View file

@ -1,3 +1,11 @@
## 1.0.4
Enhancement:
- Added option to save word order
- Added more tests
- Added Django 1.8 and dropped unsupported Django
## 1.0.3
Enhancement:

View file

@ -78,11 +78,15 @@ Unicode Test
self.assertEqual(r, "jaja-lol-a")
txt = 'jaja---lol-méméméoo--a'
r = slugify(txt, max_length=19, word_boundary=True)
r = slugify(txt, max_length=17, word_boundary=True)
self.assertEqual(r, "jaja-lol-mememeoo")
txt = 'jaja---lol-méméméoo--a'
r = slugify(txt, max_length=20, word_boundary=True)
r = slugify(txt, max_length=18, word_boundary=True)
self.assertEqual(r, "jaja-lol-mememeoo")
txt = 'jaja---lol-méméméoo--a'
r = slugify(txt, max_length=19, word_boundary=True)
self.assertEqual(r, "jaja-lol-mememeoo-a")
txt = 'jaja---lol-méméméoo--a'
@ -101,6 +105,22 @@ Unicode Test
r = slugify(txt)
self.assertEqual(r, "this-is-a-test")
txt = 'one two three four five'
r = slugify(txt, max_length=13, word_boundary=True, save_order=True)
self.assertEqual(r, "one-two-three")
txt = 'one two three four five'
r = slugify(txt, max_length=13, word_boundary=True, save_order=False)
self.assertEqual(r, "one-two-three")
txt = 'one two three four five'
r = slugify(txt, max_length=12, word_boundary=True, save_order=False)
self.assertEqual(r, "one-two-four")
txt = 'one two three four five'
r = slugify(txt, max_length=12, word_boundary=True, save_order=True)
self.assertEqual(r, "one-two")
Uniqueness Test
@ -156,14 +176,14 @@ Uniqueness Test
# Let's test it
name = 'jaja---lol-méméméoo--a'
obj = SmartTruncatedSlug.objects.create(name=name)
print obj.slug # "jaja-lol-mememeoo" --- where 19 is max_length (first slug, no duplicate yet)
obj = SmartTruncatedExactWordBoundrySlug.objects.create(name=name)
self.assertEqual(obj.slug, "jaja-lol-mememeoo-a") # 19 is max_length
obj = SmartTruncatedSlug.objects.create(name=name)
print obj.slug # "jaja-lol-mememeoo-9" --- where 19 is max_length, start_no = 9
obj = SmartTruncatedExactWordBoundrySlug.objects.create(name=name)
self.assertEqual(obj.slug, "jaja-lol-mememeoo-9") # 19 is max_length, start_no = 9
obj = SmartTruncatedSlug.objects.create(name=name)
print obj.slug # "jaja-lol-mememeo-10" -- where 19 is max_length, smart appending "-10"
obj = SmartTruncatedExactWordBoundrySlug.objects.create(name=name)
self.assertEqual(obj.slug, "jaja-lol-mememeo-10") # 19 is max_length, readjust for "-10"
Running the tests
@ -177,15 +197,14 @@ To run the tests against the current environment:
License
====================
Protected by ([BSD](LICENSE.md))
Released under a ([BSD](LICENSE.md)) license.
[build-status-image-travis]: https://secure.travis-ci.org/un33k/django-uuslug.png?branch=master
[travis]: http://travis-ci.org/tomchristie/django-uuslug?branch=master
[travis]: http://travis-ci.org/un33k/django-uuslug?branch=master
[build-status-image-fury]: https://badge.fury.io/py/django-uuslug.png
[fury]: http://badge.fury.io/py/django-uuslug
[build-status-image-pypi]: https://pypip.in/d/django-uuslug/badge.png
[pypi]: https://crate.io/packages/django-uuslug?version=latest

View file

@ -3,8 +3,6 @@ import os
import sys
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "uuslug.testsettings")
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "uuslug.tests.testsettings")
from django.core.management import execute_from_command_line
execute_from_command_line(sys.argv)

View file

@ -1,52 +1,7 @@
# -*- coding: utf-8 -*-
from .uuslug import *
__version__ = '1.0.3'
__author__ = 'Val Neekman @ Neekware Inc. [@vneekman]'
__description__ = 'A Python slugify application that also handles Unicode'
__version__ = '1.0.4'
default_app_config = 'uuslug.apps.AppConfig'
from django.utils import six
if six.PY3:
from django.utils.encoding import smart_str
else:
from django.utils.encoding import smart_unicode as smart_str
from slugify import slugify as pyslugify
__all__ = ['slugify', 'uuslug']
def slugify(text, entities=True, decimal=True, hexadecimal=True, max_length=0, word_boundary=False, separator='-'):
""" Make a slug from a given text """
return smart_str(pyslugify(text, entities, decimal, hexadecimal, max_length, word_boundary, separator))
def uuslug(s, instance, entities=True, decimal=True, hexadecimal=True,
slug_field='slug', filter_dict=None, start_no=1, max_length=0,
word_boundary=False, separator='-'):
""" This method tries a little harder than django's django.template.defaultfilters.slugify. """
if hasattr(instance, 'objects'):
raise Exception("Error: you must pass an instance to uuslug, not a model.")
queryset = instance.__class__.objects.all()
if filter_dict:
queryset = queryset.filter(**filter_dict)
if instance.pk:
queryset = queryset.exclude(pk=instance.pk)
slug = slugify(s, entities=entities, decimal=decimal, hexadecimal=hexadecimal,
max_length=max_length, word_boundary=word_boundary, separator=separator)
new_slug = slug
counter = start_no
while queryset.filter(**{slug_field: new_slug}).exists():
if max_length > 0:
if len(slug) + len(separator) + len(str(counter)) > max_length:
slug = slug[:max_length - len(slug) - len(separator) - len(str(counter))]
new_slug = "%s%s%s" % (slug, separator, counter)
counter += 1
return new_slug

0
uuslug/tests/__init__.py Normal file
View file

View file

@ -61,11 +61,15 @@ class SlugUnicodeTestCase(TestCase):
self.assertEqual(r, "jaja-lol-a")
txt = 'jaja---lol-méméméoo--a'
r = slugify(txt, max_length=19, word_boundary=True)
r = slugify(txt, max_length=17, word_boundary=True)
self.assertEqual(r, "jaja-lol-mememeoo")
txt = 'jaja---lol-méméméoo--a'
r = slugify(txt, max_length=20, word_boundary=True)
r = slugify(txt, max_length=18, word_boundary=True)
self.assertEqual(r, "jaja-lol-mememeoo")
txt = 'jaja---lol-méméméoo--a'
r = slugify(txt, max_length=19, word_boundary=True)
self.assertEqual(r, "jaja-lol-mememeoo-a")
txt = 'jaja---lol-méméméoo--a'
@ -84,6 +88,22 @@ class SlugUnicodeTestCase(TestCase):
r = slugify(txt)
self.assertEqual(r, "this-is-a-test")
txt = 'one two three four five'
r = slugify(txt, max_length=13, word_boundary=True, save_order=True)
self.assertEqual(r, "one-two-three")
txt = 'one two three four five'
r = slugify(txt, max_length=13, word_boundary=True, save_order=False)
self.assertEqual(r, "one-two-three")
txt = 'one two three four five'
r = slugify(txt, max_length=12, word_boundary=True, save_order=False)
self.assertEqual(r, "one-two-four")
txt = 'one two three four five'
r = slugify(txt, max_length=12, word_boundary=True, save_order=True)
self.assertEqual(r, "one-two")
class SlugUniqueTestCase(TestCase):
"""Tests for Slug - Unique"""
@ -149,7 +169,7 @@ class SlugUniqueTestCase(TestCase):
name = 'jaja---lol-méméméoo--a'
obj = SmartTruncatedExactWordBoundrySlug.objects.create(name=name)
self.assertEqual(obj.slug, "jaja-lol-mememeoo") # 19 is max_length
self.assertEqual(obj.slug, "jaja-lol-mememeoo-a") # 19 is max_length
obj = SmartTruncatedExactWordBoundrySlug.objects.create(name=name)
self.assertEqual(obj.slug, "jaja-lol-mememeoo-9") # 19 is max_length, start_no = 9

49
uuslug/uuslug.py Normal file
View file

@ -0,0 +1,49 @@
from slugify import slugify as pyslugify
from django.utils import six
if six.PY3:
from django.utils.encoding import smart_str
else:
from django.utils.encoding import smart_unicode as smart_str
__all__ = ['slugify', 'uuslug']
def slugify(text, entities=True, decimal=True, hexadecimal=True, max_length=0,
word_boundary=False, separator='-', save_order=False):
"""
Make a slug from a given text.
"""
return smart_str(pyslugify(text, entities, decimal, hexadecimal, max_length,
word_boundary, separator, save_order))
def uuslug(s, instance, entities=True, decimal=True, hexadecimal=True,
slug_field='slug', filter_dict=None, start_no=1, max_length=0,
word_boundary=False, separator='-', save_order=False):
""" This method tries a little harder than django's django.template.defaultfilters.slugify. """
if hasattr(instance, 'objects'):
raise Exception("Error: you must pass an instance to uuslug, not a model.")
queryset = instance.__class__.objects.all()
if filter_dict:
queryset = queryset.filter(**filter_dict)
if instance.pk:
queryset = queryset.exclude(pk=instance.pk)
slug = slugify(s, entities=entities, decimal=decimal, hexadecimal=hexadecimal,
max_length=max_length, word_boundary=word_boundary, separator=separator,
save_order=save_order)
new_slug = slug
counter = start_no
while queryset.filter(**{slug_field: new_slug}).exists():
if max_length > 0:
if len(slug) + len(separator) + len(str(counter)) > max_length:
slug = slug[:max_length - len(slug) - len(separator) - len(str(counter))]
new_slug = "{}{}{}".format(slug, separator, counter)
counter += 1
return new_slug