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