slugify
フィルターが非ASCII英数字を削除しないようにするにはどうすればよいですか? (私はDjango 1.0.2)を使用しています
cnprog.com 質問のURLに漢字があるので、それらのコードを調べました。テンプレートでslugify
を使用しておらず、代わりにQuestion
モデルでこのメソッドを呼び出してパーマリンクを取得しています
def get_absolute_url(self):
return '%s%s' % (reverse('question', args=[self.id]), self.title)
彼らはURLをスラッグ化しているかどうか?
私がaskbotQ&Aフォーラムに採用したpythonパッケージ nidecode があります。これはラテン語ベースのアルファベットでうまく機能し、ギリシャ語でも妥当に見えます。
>>> import unidecode
>>> from unidecode import unidecode
>>> unidecode(u'διακριτικός')
'diakritikos'
それはアジアの言語で奇妙なことをします:
>>> unidecode(u'影師嗎')
'Ying Shi Ma '
>>>
これは意味がありますか?
Askbotでは、次のようにスラッグを計算します。
from unidecode import unidecode
from Django.template import defaultfilters
slug = defaultfilters.slugify(unidecode(input_text))
Mozilla Webサイトチームは実装に取り組んでいます: https://github.com/mozilla/unicode-slugify サンプルコード http://davedash.com/2011/03/ 24/how-we-slug-at-mozilla /
また、slugifyのDjangoバージョンはre.UNICODEフラグを使用しないため、非ASCIIに関連するため、\w\s
の意味を理解しようとさえしません。文字。
このカスタムバージョンは私にとってうまく機能しています:
def u_slugify(txt):
"""A custom version of slugify that retains non-ascii characters. The purpose of this
function in the application is to make URLs more readable in a browser, so there are
some added heuristics to retain as much of the title meaning as possible while
excluding characters that are troublesome to read in URLs. For example, question marks
will be seen in the browser URL as %3F and are thereful unreadable. Although non-ascii
characters will also be hex-encoded in the raw URL, most browsers will display them
as human-readable glyphs in the address bar -- those should be kept in the slug."""
txt = txt.strip() # remove trailing whitespace
txt = re.sub('\s*-\s*','-', txt, re.UNICODE) # remove spaces before and after dashes
txt = re.sub('[\s/]', '_', txt, re.UNICODE) # replace remaining spaces with underscores
txt = re.sub('(\d):(\d)', r'\1-\2', txt, re.UNICODE) # replace colons between numbers with dashes
txt = re.sub('"', "'", txt, re.UNICODE) # replace double quotes with single quotes
txt = re.sub(r'[?,:!@#~`+=$%^&\\*()\[\]{}<>]','',txt, re.UNICODE) # remove some characters altogether
return txt
最後の正規表現の置換に注意してください。これは、次のpythonに示すように、一部の非ASCII文字を削除するか、誤って再エンコードするように見える、より堅牢な式r'\W'
の問題の回避策です。 =通訳セッション:
Python 2.5.1 (r251:54863, Jun 17 2009, 20:37:34)
[GCC 4.0.1 (Apple Inc. build 5465)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import re
>>> # Paste in a non-ascii string (simplified Chinese), taken from http://globallives.org/wiki/152/
>>> str = '您認識對全球社區感興趣的中國攝影師嗎'
>>> str
'\xe6\x82\xa8\xe8\xaa\x8d\xe8\xad\x98\xe5\xb0\x8d\xe5\x85\xa8\xe7\x90\x83\xe7\xa4\xbe\xe5\x8d\x80\xe6\x84\x9f\xe8\x88\x88\xe8\xb6\xa3\xe7\x9a\x84\xe4\xb8\xad\xe5\x9c\x8b\xe6\x94\x9d\xe5\xbd\xb1\xe5\xb8\xab\xe5\x97\x8e'
>>> print str
您認識對全球社區感興趣的中國攝影師嗎
>>> # Substitute all non-Word characters with X
>>> re_str = re.sub('\W', 'X', str, re.UNICODE)
>>> re_str
'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\xa3\xe7\x9a\x84\xe4\xb8\xad\xe5\x9c\x8b\xe6\x94\x9d\xe5\xbd\xb1\xe5\xb8\xab\xe5\x97\x8e'
>>> print re_str
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX?的中國攝影師嗎
>>> # Notice above that it retained the last 7 glyphs, ostensibly because they are Word characters
>>> # And where did that question mark come from?
>>>
>>>
>>> # Now do the same with only the last three glyphs of the string
>>> str = '影師嗎'
>>> print str
影師嗎
>>> str
'\xe5\xbd\xb1\xe5\xb8\xab\xe5\x97\x8e'
>>> re.sub('\W','X',str,re.U)
'XXXXXXXXX'
>>> re.sub('\W','X',str)
'XXXXXXXXX'
>>> # Huh, now it seems to think those same characters are NOT Word characters
上記の問題が何であるかはわかりませんが、「 nicode文字プロパティデータベースで英数字として分類されているものは何でも 」とその実装方法に起因していると思います。 python 3.xはUnicodeの処理を改善することを優先していると聞いたので、これはすでに修正されている可能性があります。または、正しいかもしれませんpython 、および私はユニコードおよび/または中国語を誤用しています。
今のところ、回避策は文字クラスを避け、明示的に定義された文字セットに基づいて置換を行うことです。
Django> = 1.9の場合、 Django.utils.text.slugify
にはallow_unicode
パラメータ:
>>> slugify("你好 World", allow_unicode=True)
"你好-world"
Django <= 1.8(2018年4月以降は使用しないでください)を使用する場合、次のことができます Django 1.9 からコードを取得します=。
Django docsはこれを明示的に述べていませんが、Djangoのslugの定義はasciiを意味するのではないかと思います。これがslugifyのdefaultfiltersのソースです...値がわかりますエラーの場合は「ignore」オプションを使用して、ASCIIに変換されています。
import unicodedata
value = unicodedata.normalize('NFKD', value).encode('ascii', 'ignore')
value = unicode(re.sub('[^\w\s-]', '', value).strip().lower())
return mark_safe(re.sub('[-\s]+', '-', value))
これに基づくと、cnprog.comは公式のslugify
関数を使用していないと思います。別の動作が必要な場合は、上記のDjangoスニペットを適応させることをお勧めします。
ただし、URLのRFCには、ASCII以外の文字(より具体的には、英数字と$ -_。+!* '()以外のもの)は%hex表記を使用してエンコードする必要があると記載されています。 。ブラウザが送信する実際の生のGETリクエストを見ると(たとえば、Firebugを使用して)、送信される前に漢字が実際にエンコードされていることがわかります...ブラウザはディスプレイ上できれいに見えるようにします。これが、slugifyがASCIIのみを主張する理由だと思います。
あなたは見たいかもしれません: https://github.com/un33k/Django-uuslug
それはあなたのために両方の「U」の世話をします。 [〜#〜] u [〜#〜]一意で[〜#〜] u [〜# Unicodeでは〜]。
それはあなたのための仕事を手間をかけずに行います。
これは私が使用するものです:
http://trac.Django-fr.org/browser/site/trunk/djangofr/links/slughifi.py
SlugHiFiは、通常のslugifyのラッパーですが、国別の文字を対応する英語のアルファベットに置き換えるという違いがあります。
したがって、「Ą」の代わりに「Ł」=>「L」の代わりに「A」を取得します。
スラッグにASCII文字のみを許可することに興味があります。これが、同じ文字列に対して使用可能なツールのいくつかをベンチマークしようとした理由です。
In [5]: %timeit slugify('Παίζω τρέχω %^&*@# και γ%^(λώ la fd/o', only_ascii=True)
37.8 µs ± 86.7 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
'paizo-trekho-kai-glo-la-fdo'
In [3]: %timeit slugify('Παίζω τρέχω %^&*@# και γ%^(λώ la fd/o')
35.3 µs ± 303 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
'paizo-trekho-kai-g-lo-la-fd-o'
In [3]: %timeit slugify('Παίζω τρέχω %^&*@# και γ%^(λώ la fd/o')
47.1 µs ± 1.94 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
'Paizo-trekho-kai-g-lo-la-fd-o'
In [3]: %timeit slugify('Παίζω τρέχω %^&*@# και γ%^(λώ la fd/o')
24.6 µs ± 122 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
'paizo-trekho-kai-g-lo-la-fd-o'
Django.utils.text.slugify
with nidecode :
In [15]: %timeit slugify(unidecode('Παίζω τρέχω %^&*@# και γ%^(λώ la fd/o'))
36.5 µs ± 89.7 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
'paizo-trekho-kai-glo-la-fdo'