mirror of
https://github.com/Hopiu/django-uuslug.git
synced 2026-03-16 20:10:24 +00:00
added save_order option, added django 1.8, dropped unsupported django version
This commit is contained in:
parent
471908cc28
commit
e283a1c3ee
9 changed files with 170 additions and 69 deletions
58
.gitignore
vendored
58
.gitignore
vendored
|
|
@ -1,5 +1,57 @@
|
||||||
*.pyc
|
# Byte-compiled / optimized / DLL files
|
||||||
MANIFEST
|
__pycache__/
|
||||||
dist/
|
*.py[cod]
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
env/
|
||||||
build/
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
*.egg-info/
|
*.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/
|
||||||
|
|
|
||||||
|
|
@ -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
|
## 1.0.3
|
||||||
|
|
||||||
Enhancement:
|
Enhancement:
|
||||||
|
|
|
||||||
41
README.md
41
README.md
|
|
@ -78,11 +78,15 @@ Unicode Test
|
||||||
self.assertEqual(r, "jaja-lol-a")
|
self.assertEqual(r, "jaja-lol-a")
|
||||||
|
|
||||||
txt = 'jaja---lol-méméméoo--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")
|
self.assertEqual(r, "jaja-lol-mememeoo")
|
||||||
|
|
||||||
txt = 'jaja---lol-méméméoo--a'
|
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")
|
self.assertEqual(r, "jaja-lol-mememeoo-a")
|
||||||
|
|
||||||
txt = 'jaja---lol-méméméoo--a'
|
txt = 'jaja---lol-méméméoo--a'
|
||||||
|
|
@ -101,6 +105,22 @@ Unicode Test
|
||||||
r = slugify(txt)
|
r = slugify(txt)
|
||||||
self.assertEqual(r, "this-is-a-test")
|
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
|
Uniqueness Test
|
||||||
|
|
||||||
|
|
@ -156,14 +176,14 @@ Uniqueness Test
|
||||||
# Let's test it
|
# Let's test it
|
||||||
name = 'jaja---lol-méméméoo--a'
|
name = 'jaja---lol-méméméoo--a'
|
||||||
|
|
||||||
obj = SmartTruncatedSlug.objects.create(name=name)
|
obj = SmartTruncatedExactWordBoundrySlug.objects.create(name=name)
|
||||||
print obj.slug # "jaja-lol-mememeoo" --- where 19 is max_length (first slug, no duplicate yet)
|
self.assertEqual(obj.slug, "jaja-lol-mememeoo-a") # 19 is max_length
|
||||||
|
|
||||||
obj = SmartTruncatedSlug.objects.create(name=name)
|
obj = SmartTruncatedExactWordBoundrySlug.objects.create(name=name)
|
||||||
print obj.slug # "jaja-lol-mememeoo-9" --- where 19 is max_length, start_no = 9
|
self.assertEqual(obj.slug, "jaja-lol-mememeoo-9") # 19 is max_length, start_no = 9
|
||||||
|
|
||||||
obj = SmartTruncatedSlug.objects.create(name=name)
|
obj = SmartTruncatedExactWordBoundrySlug.objects.create(name=name)
|
||||||
print obj.slug # "jaja-lol-mememeo-10" -- where 19 is max_length, smart appending "-10"
|
self.assertEqual(obj.slug, "jaja-lol-mememeo-10") # 19 is max_length, readjust for "-10"
|
||||||
|
|
||||||
|
|
||||||
Running the tests
|
Running the tests
|
||||||
|
|
@ -177,15 +197,14 @@ To run the tests against the current environment:
|
||||||
License
|
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
|
[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
|
[build-status-image-fury]: https://badge.fury.io/py/django-uuslug.png
|
||||||
[fury]: http://badge.fury.io/py/django-uuslug
|
[fury]: http://badge.fury.io/py/django-uuslug
|
||||||
|
|
||||||
[build-status-image-pypi]: https://pypip.in/d/django-uuslug/badge.png
|
[build-status-image-pypi]: https://pypip.in/d/django-uuslug/badge.png
|
||||||
[pypi]: https://crate.io/packages/django-uuslug?version=latest
|
[pypi]: https://crate.io/packages/django-uuslug?version=latest
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,6 @@ import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
if __name__ == "__main__":
|
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
|
from django.core.management import execute_from_command_line
|
||||||
|
|
||||||
execute_from_command_line(sys.argv)
|
execute_from_command_line(sys.argv)
|
||||||
|
|
|
||||||
|
|
@ -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'
|
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
0
uuslug/tests/__init__.py
Normal file
|
|
@ -61,11 +61,15 @@ class SlugUnicodeTestCase(TestCase):
|
||||||
self.assertEqual(r, "jaja-lol-a")
|
self.assertEqual(r, "jaja-lol-a")
|
||||||
|
|
||||||
txt = 'jaja---lol-méméméoo--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")
|
self.assertEqual(r, "jaja-lol-mememeoo")
|
||||||
|
|
||||||
txt = 'jaja---lol-méméméoo--a'
|
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")
|
self.assertEqual(r, "jaja-lol-mememeoo-a")
|
||||||
|
|
||||||
txt = 'jaja---lol-méméméoo--a'
|
txt = 'jaja---lol-méméméoo--a'
|
||||||
|
|
@ -84,6 +88,22 @@ class SlugUnicodeTestCase(TestCase):
|
||||||
r = slugify(txt)
|
r = slugify(txt)
|
||||||
self.assertEqual(r, "this-is-a-test")
|
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):
|
class SlugUniqueTestCase(TestCase):
|
||||||
"""Tests for Slug - Unique"""
|
"""Tests for Slug - Unique"""
|
||||||
|
|
@ -149,7 +169,7 @@ class SlugUniqueTestCase(TestCase):
|
||||||
name = 'jaja---lol-méméméoo--a'
|
name = 'jaja---lol-méméméoo--a'
|
||||||
|
|
||||||
obj = SmartTruncatedExactWordBoundrySlug.objects.create(name=name)
|
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)
|
obj = SmartTruncatedExactWordBoundrySlug.objects.create(name=name)
|
||||||
self.assertEqual(obj.slug, "jaja-lol-mememeoo-9") # 19 is max_length, start_no = 9
|
self.assertEqual(obj.slug, "jaja-lol-mememeoo-9") # 19 is max_length, start_no = 9
|
||||||
49
uuslug/uuslug.py
Normal file
49
uuslug/uuslug.py
Normal 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
|
||||||
Loading…
Reference in a new issue