S'assurer qu'un id est unique

L'auteur de ce sujet a trouvé une solution à son problème.
Auteur du sujet

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

Édité par Wizix

Mon projet : OpenPlane, un utilitaire en Java pour les pilotes, les vrais !

+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.

Édité par entwanne

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.

Auteur du sujet

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

Édité par Wizix

Mon projet : OpenPlane, un utilitaire en Java pour les pilotes, les vrais !

+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).

Auteur du sujet

Sinon je modifie l'init non ?

1
2
3
def __init__(self):
        super(Truc, self).__init__()
        self.slug = Truc.genslug(Truc.SLUG_LENGTH)

Ça à l'air de fonctionner selon mes tests. :)

Mon projet : OpenPlane, un utilitaire en Java pour les pilotes, les vrais !

+0 -0
Auteur du sujet

Désolé du double post mais non ça ne fonctionne pas du tout, le slug est généré à chaque fois que l'objet est créé du coup ce n'est jamais le même (je n'y avais pas pensé :-° ).

Du coup comment faire ?

Merci. :)

Mon projet : OpenPlane, un utilitaire en Java pour les pilotes, les vrais !

+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.

Édité par entwanne

Vous devez être connecté pour pouvoir poster un message.
Connexion

Pas encore inscrit ?

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