2009-05-08 13 views
182

Estoy tratando de crear un SlugField en Django.¿Cómo creo una babosa en Django?

he creado este modelo simple:

from django.db import models 

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

continuación, hago esto:

>>> 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' 
>>> 

que estaba esperando b-b-b-b

+15

vine de "tango con django";) – kmonsoor

Respuesta

351

Usted tendrá que utilizar la función slugify.

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

Puede llamar slugify automáticamente reemplazando el método 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) 

Tenga en cuenta que la anterior hará que su URL a cambiar cuando se edita el campo q, que can cause broken links. Puede ser preferible generar la babosa sólo una vez cuando se crea un nuevo objeto:

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

¿Tiene un modelo de tipo especial? ¿por qué no simplemente slugify CharFields? – Johnd

+22

Conjunto de SlugFields db_index = True de forma predeterminada, y también utiliza un campo de formulario de forma predeterminada que tiene una expresión regular de validación para exigir babosas válidas (si están representadas en un ModelForm o en el administrador). Puede hacer esas cosas manualmente con un CharField si lo prefiere, solo hace que la intención de su código sea menos clara. Además, no se olvide de la configuración de prepopulate_fields ModelAdmin, si desea prerregulación automática basada en JS en el administrador. –

+4

Como Dingle dijo a continuación en su respuesta, deberá reemplazar 'def save (self):' con 'def save (self, * args, ** kwargs):' para evitar que se produzcan errores al escribir algo como 'test.objects.create (q =" blah blah blah ")'. – Liam

27

Si está utilizando la interfaz de administración para añadir nuevos elementos de su modelo, se puede establecer un ModelAdmin en su admin.py y utilizar prepopulated_fields para automatizar entrada de una babosa:

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

admin.site.register(Client, ClientAdmin) 

Aquí, cuando el usuario introduce un valor en la forma de administración para el campo de name, la slug se rellena automáticamente con el correcto slugified name.

+0

My 'slug' y' name' tienen traducciones. ¿Cómo puedo hacer eso con las traducciones? Porque intenté agregar ''slug_en' :('name_en',)' y obtuve el error de que ese atributo no existe en mi modelo. – patricia

22

En la mayoría de los casos la babosa no debe cambiar, por lo que en realidad sólo quiere calcular en primer salvamento:

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() 
+8

debería aceptar * args y ** kwargs –

57

Una pequeña corrección a la respuesta de Thepeer: Para anular save() función en las clases del modelo, mejor añadir argumentos a la misma:

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) 

de lo contrario, test.objects.create(q="blah blah blah") se traducirá en un force_insert error (argumento inesperado).

+2

Otra cosa muy menor que añadir a la respuesta del ejecutor: Haría que la última línea 'return super (prueba, self) .save (* args, ** kwargs)'. Creo que este método devuelve 'None', y no sé de ningún plan para cambiar eso, pero no hace ningún daño devolver lo que hace el método de la superclase en caso de que cambie en el futuro. –

+0

Agregue que * de django.utils.text import slugify * es necesario para esta solución. – Routhinator

+1

@Routhinator lo hizo –

5

Si no desea configurar el slugfield en No se puede editar, entonces creo que querrá establecer las propiedades nula y en blanco en False. De lo contrario, recibirá un error al intentar guardar en Admin.

lo tanto una modificación en el ejemplo anterior sería ::

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

o podría usar editable = False: P – bx2

+0

Documentos en [editable] (https://docs.djangoproject.com/en/1.11/ref/models/fields/#editable) – surfer190

101

Hay algunos casos esquina con UTF-8 caracteres

Ejemplo:

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

Esto se puede solucionar con Unidecode

>>> from unidecode import unidecode 
>>> from django.template.defaultfilters import slugify 
>>> slugify(unidecode(u"test ąęśćółń")) 
u'test-aescoln' 
+4

¡Esta es una adición muy importante que debería recibir mucha más atención (votos ascendentes) para ser notada! –

+6

utf-8 ahora es manejado correctamente por slugify (en django 1.8.5) –

+0

@ASz Siguiendo sus instrucciones, volví a subir. :RE – learner

2

estoy usando Django 1.7

Crear un SlugField en su modelo como este:

slug = models.SlugField() 

Luego, en admin.py definen prepopulated_fields;

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