S'assurer qu'un id est unique

a marqué ce sujet comme résolu.

Bonjour,

J'aimerais savoir comment m'assurer que le slug généré par le modèle sois bien unique ? Voici le modèle :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
from django.db import models
import uuid

class Truc(models.Model):
    SLUG_LENGTH = 7

    slug    = models.CharField(max_length=SLUG_LENGTH, default=self.genslug(SLUG_LENGTH), editable=False)
    title   = models.CharField(max_length=255)
    content = models.TextField()
    posted  = models.DateTimeField(auto_nom=False, auto_now_add=True)
    edited  = models.DateTimeField(auto_now=True)
    # author

    def genslug(length):
        return str(uuid.uuid4())[:length]

Merci à vous :)

EDIT : en faite mon code ne fonctionne pas, voici ce que me dit Python :

1
2
slug    = models.CharField(max_length=SLUG_LENGTH, default=self.genslug(SLUG_LENGTH), editable=False)
NameError: name 'self' is not defined

Et sans le self :

1
2
slug    = models.CharField(max_length=SLUG_LENGTH, default=genslug(SLUG_LENGTH), editable=False)
NameError: name 'genslug' is not defined
+0 -0

Et en déclarant la fonction/méthode genslug avant les attributs de classe ? (en utilisant la version sans self, qui n'a aucune raison d'exister dans ce scope).

Je te conseille aussi d'ajouter un gensulg = staticmethod(genslug) en toute fin de classe, pour éviter des comportements bizarres si tu essayais d'appeler genslug sur une instance de Truc.

En fait, le corps de la classe est évalué directement, donc seuls sont utilisables les noms qui existent déjà.

Mais les corps des méthodes, par exemple, ne sont évalués que lorsqu'elles sont appelées, donc tu peux y faire référence à des objets qui n'existent pas encore.

Ceci expliquant cela. Merci à toi.

Voici ma solution pour mon problème :

1
2
3
4
5
def genslug(length):
    while True:
        slug = str(uuid.uuid4())[:length]
        if not Truc.objects.filter(slug=slug).exists():
             return slug

Problème :

1
2
if not Truc.objects.filter(slug=slug).exists():
NameError: name 'Truc' is not defined

Là je ne peux pas trop mettre ma méthode avant la déclaration de la classe :D

+0 -0

En effet, tu essaies d'accéder à l'attribut objects du modèle alors que celui-ci n'existe pas encore (il n'existera qu'une fois que le bloc de création de classe aura été évalué).

Je ne connais plus trop bien Django, mais te serait-il possible de redéfinir l'attribut default du Field qu'une fois la classe créée (Truc.slug.default = Truc.getslug(Truc.SLUG_LENGTH))

Mais, en y repensant, ça voudrait dire que le slug par défaut serait commun à tous, je doute que ce soit réellement ce que tu aies envie de faire. Donc il te faudrait voir si tu peux utiliser un paramètre de CharField pour cela, et faire autrement sinon (en créant ton propre type de Field par exemple).

Je te conseille d'éviter d'appeler ton champ "slug" si c'est pas un slug. Un slug est censé être lisible par un être humain et avoir un rapport avec l'objet/le contenu, pas être une chaîne aléatoire.

+0 -0

Je parlais de créer ton propre type de champ parce que c'est ce que j'avais été amené à faire pour générer un UUID dans mes modèles, ce qui semble correspondre à ce que tu demandes.

Le lien que je donne est là à titre d'exemple, c'était sous Django 1.6 donc ça a pu pas mal changer.

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte