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
|
||||
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/
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
41
README.md
41
README.md
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
0
uuslug/tests/__init__.py
Normal 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
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