1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 | import re
import unicodedata
from htmlentitydefs import name2codepoint
from django.utils.encoding import smart_unicode, force_unicode
def slugify(s, entities=True, decimal=True, hexadecimal=True,
instance=None, slug_field='slug', filter_dict=None):
s = smart_unicode(s)
#character entity reference
if entities:
s = re.sub('&(%s);' % '|'.join(name2codepoint), lambda m: unichr(name2codepoint[m.group(1)]), s)
#decimal character reference
if decimal:
try:
s = re.sub('&#(\d+);', lambda m: unichr(int(m.group(1))), s)
except:
pass
#hexadecimal character reference
if hexadecimal:
try:
s = re.sub('&#x([\da-fA-F]+);', lambda m: unichr(int(m.group(1), 16)), s)
except:
pass
#translate
s = unicodedata.normalize('NFKD', s).encode('ascii', 'ignore')
#replace unwanted characters
s = re.sub(r'[^-a-z0-9]+', '-', s.lower())
#remove redundant -
s = re.sub('-{2,}', '-', s).strip('-')
slug = s
if instance:
def get_query():
query = instance.__class__.objects.filter(**{slug_field: slug})
if filter_dict:
query = query.filter(**filter_dict)
if instance.pk:
query = query.exclude(pk=instance.pk)
return query
counter = 1
while get_query():
slug = "%s-%s" % (s, counter)
counter += 1
return slug
|
Comments