Регулярно требуется преобразовать какой-либо текст в максимально совместимый текст для URL, имени файла, имени объекта в каком-то софте и тд. Требования совместимости простые: в тексте должны быть только допустимые символы. Обычно это a-z, 0-9 и "_" или "-". То есть, только прописные буквы латинского алфавита и цифры (как пример).
Допустим, нам нужно название статьи в блоге преобразовать в slug для добавления его в URL этой статьи. Как это лучше всего сделать?
В Django по умолчанию есть готовая функция slugify для таких случаев.
Но я её никогда не использую. Почему? Потому что её недостаточно!
Приведём пример
>>> from django.utils.text import slugify
>>> slugify('This is a Title')
'this-is-a-title'
Пока всё отлично
>>> slugify('This is a "Title!"')
'this-is-a-title'
Спец символы удалились, всё хорошо.
>>> slugify('Это заголовок статьи')
''
Вот и приехали 😢. Если текст не английский то буквы просто игнорируются. Можно это поправить
>>> slugify('Это заголовок статьи', allow_unicode=True)
'это-заголовок-статьи'
Но тогда мы не вписываемся в условие. У нас появилась кириллица в тексте.
Так как я часто пишу сайты для русскоязычных пользователей эта проблема весьма актуальна. Я не использую стандартную функцию и всегда пишу свою.
Оригинал я не беру в расчёт и пишу полностью свою функцию. И так, по порядку:
🔸1. Исходный текст:
>>> text = 'Мой заголовок №10 😁!'
Взял специально посложней со специальными символами.
🔸2. Транслит
Необходимо сделать транслит всех символов в латиницу. Здесь очень выручает библиотека unidecode. Помимо простого транслита кириллицы в латиницу она умеет преобразовывать спец символы и иероглифы в текстовые аналоги.
from unidecode import unidecode
>>> unidecode("Ñ Σ ® µ ¶ ¼ 月 山")
'N S (r) u P 1/4 Yue Shan'
Очень крутая библиотека, советую👍
В нашем случае получаем такое преобразование:
>>> text = unidecode(text)
>>> print(text)
'Moi zagolovok No. 10 !'
Отличный транслит. Смайл просто удалился, хотя я ждал что-то вроде :). Ну и ладно, всë равно невалидные символы.
А еще наш код уже поддерживает любой язык, будь то хинди или корейский.
🔸4. Фильтр символов
Unidecode не занимается фильтрацией по недопустимым символам. Это мы делаем в следующем шаге через regex. Просто заменим все символы на "_" если они вне указанного диапазона.
>>> text = re.sub(r'[^a-zA-Z0-9]+', '_', text)
>>> print(text)
'Moi_zagolovok_No_10_'
Символ "+" в паттерне выручает когда несколько недопустимых символов идут рядом. Все они заменяются на один символ "_".
🔸5. Slugify
Осталось удалить лишние символы по краям и сделать нижний регистр
>>> text = text.strip('_').lower()
>>> print(text)
'moi_zagolovok_no_10'
Получаем отличный slug! 😎
🌎 Полный код в виде функции.
______________
PS. Проверку что в строке остался хоть один допустимый символ я бы вынес в отдельную функцию.
#libs#tricks#django
"In a tragic accident, a life was lost in an instant—without any fault of his own.
This heartbreaking event is a stark reminder of how fragile life can be.
It underscores the critical importance of life insurance. To truly protect your loved ones, you should have coverage that's at least 250 times your monthly income.
This ensures that your family's financial stability is preserved, even in your absence.
The best time to secure life insurance was yesterday. The next best time is NOW."
#Accident
🇺🇸🏎 Au moins 27 véhicules se sont heurtés lors d'une course automobile Nascar aux États-Unis. La course a été temporairement suspendue, puis a repris.
#accident#voiture#étatsunis
🏎 Le bolide du pilote français Pierre Gasly s’est retourné lors du Grand Prix de Miami comptant pour le championnat du monde de Formule 1.
Il est entré en collision avec le véhicule du Néo-Zélandais Liam Lawson, de Racing Bulls. Les deux pilotes ont été contraints à abandonner la course.
#formule1#accident
🇮🇷 Un hélicoptère militaire s'est écrasé en Iran dans la province d'Ispahan à cause d'une défaillance technique. En conséquence, quatre personnes sont décédées, a signalé l'agence de presse IRNA.
Le pilote et le copilote sont morts. D’après les pompiers, deux vendeurs ont également péri.
#iran#hélicoptère#accident
🇯🇵 Un accident de la route impliquant plusieurs véhicules, dont un minibus transportant des écoliers, s'est produit dans la préfecture japonaise de Fukushima, a signalé la chaîne NHK.
D’après les informations de la police, l'accident a eu lieu près de la localité d'Inawashiro. En conséquence, au moins une personne est décédée et 26 autres ont été blessées, dont certaines gravement.
#japon#accident#bilan
Série noire en Espagne : un second accident grave ferroviaire 48 h après le drame d'Adamuz.
En Catalogne (Gelida, près de Barcelone), un train de banlieue a heurté un mur de soutènement effondré sur les voies (probablement à cause des pluies), causant 1 mort (le conducteur) et au moins 15 blessés, dont 4 graves.
Cela survient deux jours après la grave catastrophe ferroviaire d'Adamuz (Andalousie), où une collision entre deux trains à grande vitesse a fait 42 morts et plus de 150-292 blessés (dont une quarantaine graves).
Ce drame est la conséquence d'un déraillement dû à un défaut sur les rails (joint de rail cassé ou rupture de 30 cm signalée), possiblement lié à l'usure ou à la hausse du trafic.
L’Espagne est sous le choc.
Trois jours de deuil national.
La population oscille entre deuil, entraide et colère sur la sécurité ferroviaire. Gelida renforce le sentiment d’insécurité nationale.
https://www.lefigaro.fr/international/espagne-un-train-heurte-un-mur-effondre-sur-les-voies-en-catalogne-plusieurs-blesses-20260120
#ferroviaire#Espagne
#accident
Rejoignez-nous 👇
https://t.me/nemesisiam
🇧🇬 En Bulgarie, deux personnes ont été tuées et neuf autres blessées dans un accident de la route impliquant un bus ukrainien, rapporte la télévision nationale bulgare.
Le bus touristique s’est arrêté en raison d’un manque de carburant, et lorsque les passagers sont descendus, il est reparti en marche arrière de manière incontrôlée, les percutant. Les faits se sont produits près du poste-frontière de Malko Tarnovo, non loin de la frontière bulgaro-turque.
#accident#victimes#route
🇮🇳 Au moins 10 personnes ont été tuées plus de 40 autres blessées à la suite d’une explosion dans une centrale thermique de la société Vedanta Limited dans l’État indien du Chhattisgarh, ont fait savoir les autorités de l’État.
Selon les premières informations, l’explosion s’est produite dans une chaudière de la centrale. Une opération de sauvetage est en cours, des personnes pourraient se trouver sous les décombres.
Les blessés ont été transportés dans les hôpitaux voisins. Les autorités de l’État ont commencé à déterminer les causes de la catastrophe.
#inde#accident#morts
#跳伞 有风险,入行续谨慎。网红迪迪跳伞疑似受伤。万幸无大碍 #事故
#Skydiving is risky, proceed with caution. Internet celebrity Didi appeared to be injured during a skydiving incident. Fortunately, he is unharmed. #Accident
🇧🇩 Au moins 18 personnes ont perdu la vie après qu’un bus de passagers est tombé dans le fleuve Padma, dans le centre du Bangladesh, rapporte le journal The Daily Star.
Le bus, transportant environ 40 passagers, est tombé dans le fleuve alors qu’il se trouvait sur un ponton en attente d’embarquement sur un ferry. Onze passagers ont réussi à regagner la rive par leurs propres moyens.
Les secours ont remonté le bus du fond du fleuve six heures après l’accident, retrouvant 18 corps sans vie. Plusieurs passagers sont toujours portés disparus.
#bangladesh#bus#accident
🇧🇮 Les explosions survenues dans la capitale économique du Burundi, Bujumbura, ont été causées par un incendie dans un dépôt de munitions, a rapporté l’Agence France-Presse, citant le porte-parole de l’armée.
Un grave accident électrique dans le magasin des munitions de la FDNB [Force de défense nationale du Burundi] basé à Musaga est à l'origine des explosions entendues en ce moment dans la capitale économique Bujumbura,
a commenté le porte-parole de l'armée burundaise Gaspard Baratuza.
#burundi#explosions#accident