26
26
27
27
from django .db import models
28
28
from django .utils .encoding import force_text
29
+ from slugify import slugify as unicode_slugify
29
30
30
31
31
32
def get_fields_with_model (cls ):
@@ -53,13 +54,15 @@ def get_fields_with_model(cls):
53
54
54
55
class VersionSlugField (models .CharField ):
55
56
56
- """Inspired by ``django_extensions.db.fields.AutoSlugField``."""
57
+ """
58
+ Inspired by ``django_extensions.db.fields.AutoSlugField``.
57
59
58
- invalid_chars_re = re . compile ( '[^-._a-z0-9]' )
59
- leading_punctuation_re = re . compile ( '^[-._]+' )
60
- placeholder = '-'
61
- fallback_slug = 'unknown'
60
+ Uses ``unicode-slugify`` to generate the slug.
61
+ """
62
+
63
+ ok_chars = '-._' # dash, dot, underscore
62
64
test_pattern = re .compile ('^{pattern}$' .format (pattern = VERSION_SLUG_REGEX ))
65
+ fallback_slug = 'unknown'
63
66
64
67
def __init__ (self , * args , ** kwargs ):
65
68
kwargs .setdefault ('db_index' , True )
@@ -78,13 +81,42 @@ def get_queryset(self, model_cls, slug_field):
78
81
return model ._default_manager .all ()
79
82
return model_cls ._default_manager .all ()
80
83
84
+ def _normalize (self , content ):
85
+ """
86
+ Normalize some invalid characters (/, %, !, ?) to become a dash (``-``).
87
+
88
+ .. note::
89
+
90
+ We replace these characters to a dash to keep compatibility with the
91
+ old behavior and also because it makes this more readable.
92
+
93
+ For example, ``release/1.0`` will become ``release-1.0``.
94
+ """
95
+ return re .sub ('[/%!?]' , '-' , content )
96
+
81
97
def slugify (self , content ):
98
+ """
99
+ Make ``content`` a valid slug.
100
+
101
+ It uses ``unicode-slugify`` behind the scenes which works properly with
102
+ Unicode characters.
103
+ """
82
104
if not content :
83
105
return ''
84
106
85
- slugified = content .lower ()
86
- slugified = self .invalid_chars_re .sub (self .placeholder , slugified )
87
- slugified = self .leading_punctuation_re .sub ('' , slugified )
107
+ normalized = self ._normalize (content )
108
+ slugified = unicode_slugify (
109
+ normalized ,
110
+ only_ascii = True ,
111
+ spaces = False ,
112
+ lower = True ,
113
+ ok = self .ok_chars ,
114
+ space_replacement = '-' ,
115
+ )
116
+
117
+ # Remove first character wile it's an invalid character for the
118
+ # beginning of the slug
119
+ slugified = slugified .lstrip (self .ok_chars )
88
120
89
121
if not slugified :
90
122
return self .fallback_slug
0 commit comments