web-dev-qa-db-fra.com

Convertissez une chaîne hexadécimale UUID de 32 caractères en un identifiant court "à la YouTube"

J'attribue un GUID à tous mes documents MongoDB à l'aide de uuid.uuid1 (). Je souhaite obtenir un identifiant unique de type YouTube, sensible à la casse, comportant 11 caractères, tel que 

1_XmY09uRJ4 

de la chaîne hexagonale résultante de uuid qui ressemble à

ae0a0c98-f1e5-11e1-9t2b-1231381dac60

Je veux pouvoir faire correspondre l'ID abrégé à l'hex et inversement, de manière dynamique sans avoir à stocker une autre chaîne dans la base de données. Quelqu'un a-t-il un exemple de code ou peut-il m'indiquer le module ou la formule qui peut le faire?

26
zakdances

Convertissez les octets sous-jacents en une valeur base64 en supprimant le remplissage = et la nouvelle ligne.

Vous voudrez probablement utiliser la fonction base64.urlsafe_b64encode() pour éviter d'utiliser / et + (_ et - sont utilisés à la place), afin que la chaîne résultante puisse être utilisée comme élément de chemin d'URL:

>>> import uuid, base64
>>> base64.urlsafe_b64encode(uuid.uuid1().bytes).rstrip(b'=').decode('ascii')
'81CMD_bOEeGbPwAjMtYnhg'

L'inverse:

>>> uuid.UUID(bytes=base64.urlsafe_b64decode('81CMD_bOEeGbPwAjMtYnhg' + '=='))
UUID('f3508c0f-f6ce-11e1-9b3f-002332d62786')

Pour transformer cela en fonctions génériques:

from base64 import urlsafe_b64decode, urlsafe_b64encode
from uuid import UUID

def uuid2slug(uuidstring):
    return urlsafe_b64encode(UUID(uuidstring).bytes).rstrip(b'=').decode('ascii')

def slug2uuid(slug):
    return str(uuid.UUID(bytes=urlsafe_b64decode(slug + '==')))

Cela vous donne une méthode pour représenter l'UUID de 16 octets sous une forme plus compacte. Si vous compressez davantage, vous perdez des informations, ce qui signifie que vous ne pouvez plus les décompresser pour obtenir l’UUID complet.

La chaîne unique de YouTube n'est donc pas basée sur un UUID complet sur 16 octets. Leurs identifiants à 11 caractères sont probablement stockés dans la base de données pour faciliter la recherche et sont basés sur une valeur plus petite.

49
Martijn Pieters

Vous pouvez regarder dans le modèle base64 de Python. Un GUID est essentiellement une représentation en base 16 d'un nombre. Vous pouvez supprimer les traits d'union, décoder à partir de la base 16 et encoder en base 64. Pour inverser, il faut décoder à partir de la base 64, encoder à 16 et insérer les traits d'union aux endroits appropriés.

1
Platinum Azure

Pour ceux qui recherchent spécifiquement un moyen de raccourcir les uuids de manière sécurisée, la réponse vraiment utile de @MartijnPieters peut être simplifiée en utilisant le module base64 pour gérer les caractères non sécurisés, comme le commentaire sur cette réponse de @okoboko (sans quelques bits inutiles).

import base64
import uuid

# uuid to b64 string and back
uuid_to_b64str = base64.urlsafe_b64encode(uuid.uuid1().bytes).decode('utf8').rstrip('=\n')
b64str_to_uuid = uuid.UUID(bytes=base64.urlsafe_b64decode(f'{uuid_to_b64str}=='))

# uuid string to b64 string and back
uuidstr_to_b64str = base64.urlsafe_b64encode(uuid.UUID(str(uuid.uuid1())).bytes).decode('utf8').rstrip('=\n')
b64str_to_uuidstr = str(uuid.UUID(bytes=base64.urlsafe_b64decode(f'{uuidstr_to_b64str}==')))
0
benvc