26
26
27
27
from django .db import models
28
28
from django .utils .encoding import force_text
29
+ from slugify import 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,37 @@ 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
+ For example, ``release/1.0`` will become ``release-1.0``.
89
+ """
90
+ return re .sub ('[/%!?]' , '-' , content )
91
+
81
92
def slugify (self , content ):
93
+ """
94
+ Make ``content`` a valid slug.
95
+
96
+ It uses ``unicode-slugify`` behind the scenes which works properly with
97
+ Unicode characters.
98
+ """
82
99
if not content :
83
100
return ''
84
101
85
- slugified = content .lower ()
86
- slugified = self .invalid_chars_re .sub (self .placeholder , slugified )
87
- slugified = self .leading_punctuation_re .sub ('' , slugified )
102
+ normalized = self ._normalize (content )
103
+ slugified = slugify (
104
+ normalized ,
105
+ only_ascii = True ,
106
+ spaces = False ,
107
+ lower = True ,
108
+ ok = self .ok_chars ,
109
+ space_replacement = '-' ,
110
+ )
111
+
112
+ # Remove first character wile it's an invalid character for the
113
+ # beginning of the slug
114
+ slugified = slugified .lstrip (self .ok_chars )
88
115
89
116
if not slugified :
90
117
return self .fallback_slug
0 commit comments