web-dev-qa-db-fra.com

Comment créer une limace dans Django?

J'essaie de créer un SlugField dans Django.

J'ai créé ce modèle simple:

from Django.db import models

class Test(models.Model):
    q = models.CharField(max_length=30)
    s = models.SlugField()

Je fais alors ceci:

>>> from mysite.books.models import Test
>>> t=Test(q="aa a a a", s="b b b b")
>>> t.s
'b b b b'
>>> t.save()
>>> t.s
'b b b b'

Je m'attendais à b-b-b-b.

207
Johnd

Vous devrez utiliser la fonction slugify.

>>> from Django.template.defaultfilters import slugify
>>> slugify("b b b b")
u'b-b-b-b'
>>>

Vous pouvez appeler slugify automatiquement en redéfinissant la méthode save:

class Test(models.Model):
    q = models.CharField(max_length=30)
    s = models.SlugField()

    def save(self, *args, **kwargs):
        self.s = slugify(self.q)
        super(Test, self).save(*args, **kwargs)

Sachez que ce qui précède entraînera une modification de votre URL lorsque le champ q sera modifié, ce qui peut provoquer des liens rompus . Il peut être préférable de générer le slug une seule fois lorsque vous créez un nouvel objet:

class Test(models.Model):
    q = models.CharField(max_length=30)
    s = models.SlugField()

    def save(self, *args, **kwargs):
        if not self.id:
            # Newly created object, so set slug
            self.s = slugify(self.q)

        super(Test, self).save(*args, **kwargs)
390
Buddy

Il y a un coin avec quelques caractères utf-8

Exemple:

>>> from Django.template.defaultfilters import slugify
>>> slugify(u"test ąęśćółń")
u'test-aescon' # there is no "l"

Ceci peut être résolu avec nidecode

>>> from unidecode import unidecode
>>> from Django.template.defaultfilters import slugify
>>> slugify(unidecode(u"test ąęśćółń"))
u'test-aescoln'
111
DooBLER

Une petite correction à la réponse de Thepeer: pour remplacer save() dans les classes de modèle, il vaut mieux y ajouter des arguments:

from Django.utils.text import slugify

def save(self, *args, **kwargs):
    if not self.id:
        self.s = slugify(self.q)

    super(test, self).save(*args, **kwargs)

Sinon, test.objects.create(q="blah blah blah") entraînera une erreur force_insert (Argument inattendu).

62
Dingle

Si vous utilisez l'interface d'administration pour ajouter de nouveaux éléments à votre modèle, vous pouvez configurer un ModelAdmin dans votre admin.py et utiliser prepopulated_fields pour automatiser l’entrée d’un slug:

class ClientAdmin(admin.ModelAdmin):
    prepopulated_fields = {'slug': ('name',)}

admin.site.register(Client, ClientAdmin)

Ici, lorsque l'utilisateur saisit une valeur dans le formulaire d'administration pour le champ name, le slug sera automatiquement renseigné avec le correct slugified name.

29
henrym

Dans la plupart des cas, le slug ne devrait pas changer, vous ne voulez donc le calculer que lors de la première sauvegarde:

class Test(models.Model):
    q = models.CharField(max_length=30)
    s = models.SlugField(editable=False) # hide from admin

    def save(self):
        if not self.id:
            self.s = slugify(self.q)

        super(Test, self).save()
21
thepeer

Utilisation prepopulated_fields dans votre classe d'admin:

class ArticleAdmin(admin.ModelAdmin):
    prepopulated_fields = {"slug": ("title",)}

admin.site.register(Article, ArticleAdmin)
6
sergey

Si vous ne souhaitez pas définir le slugfield sur Ne pas être éditable, je pense que vous voudrez définir les propriétés Null et Blank sur False. Sinon, vous obtiendrez une erreur en essayant de sauvegarder dans Admin.

Donc, une modification à l'exemple ci-dessus serait ::

class test(models.Model):
    q = models.CharField(max_length=30)
    s = models.SlugField(null=True, blank=True) # Allow blank submission in admin.

    def save(self):
        if not self.id:
            self.s = slugify(self.q)

        super(test, self).save()
5
Streamweaver

J'utilise Django 1.7

Créez un SlugField dans votre modèle comme ceci:

slug = models.SlugField()

Puis dans admin.py définir prepopulated_fields;

class ArticleAdmin(admin.ModelAdmin):
    prepopulated_fields = {"slug": ("title",)}
3
min2bro