2009-05-08 13 views
182

Sto provando a creare uno SlugField in Django.Come posso creare una lumaca in Django?

Ho creato questo semplice modello:

from django.db import models 

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

allora faccio questo:

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

mi aspettavo b-b-b-b

+15

sono venuto qui da "tango con django";) – kmonsoor

risposta

351

Sarà necessario utilizzare la funzione di slugify.

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

È possibile chiamare slugify automaticamente l'override del metodo 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) 

essere consapevoli che la sopra causerà il vostro URL a cambiare quando il campo q viene modificato, che can cause broken links. Può essere preferibile per generare lo slug solo una volta quando si crea un nuovo oggetto:

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

timido ha un tipo di modello speciale? perché non solo slugify CharFields? – Johnd

+22

SlugFields set db_index = True per impostazione predefinita e utilizza anche un campo modulo per impostazione predefinita che ha un'espressione regolare di convalida per richiedere slug validi (se rappresentati in un ModelForm o nell'admin). Puoi fare queste cose manualmente con un CharField, se preferisci, rende solo l'intenzione del tuo codice meno chiara. Inoltre, non dimenticare l'impostazione ModelAdmin prepopulate_fields, se desideri eseguire il prepopolamento automatico basato su JS nell'admin. –

+4

Come Dingle ha detto in seguito nella sua risposta, dovrai sostituire 'def save (self):' con 'def save (self, * args, ** kwargs):' per evitare che gli errori vengano lanciati durante la scrittura di qualcosa come 'test.objects.create (q =" blah blah blah ")'. – Liam

27

Se si utilizza l'interfaccia di amministrazione per aggiungere nuovi elementi di modello, è possibile impostare un ModelAdmin nella vostra admin.py e utilizzare prepopulated_fields automatizzare inserimento di una lumaca:

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

admin.site.register(Client, ClientAdmin) 

Qui, quando l'utente immette un valore nel modulo di amministrazione per il campo name, il slug verrà popolato automaticamente con il corretto slugified name.

+0

I campi 'slug' e' name' hanno traduzioni. Come posso farlo con le traduzioni? Perché ho provato ad aggiungere ''slug_en' :('name_en',)' e ho ricevuto l'errore che l'attributo non esiste nel mio modello. – patricia

22

Nella maggior parte dei casi la lumaca non dovrebbe cambiare, quindi è davvero solo desidera calcolare su prima salvare:

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

dovrebbe accettare * args e ** kwargs –

57

Una piccola correzione alla risposta di Thepeer: per ignorare save() funzione in classi di modelli, meglio aggiungere argomenti ad esso:

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) 

in caso contrario, test.objects.create(q="blah blah blah") si tradurrà in un force_insert errore (argomento inaspettato).

+2

Un'altra cosa molto piccola da aggiungere alla risposta di thepeer: farei che l'ultima riga 'return super (test, self) .save (* args, ** kwargs)'. Penso che questo metodo restituisca 'None', e non conosco alcun piano per cambiarlo, ma non fa male restituire quello che fa il metodo della superclasse nel caso in cui cambi in futuro. –

+0

Si prega di aggiungere che * da django.utils.text slugify * è richiesto per questa soluzione. – Routhinator

+1

@Routhinator lo ha fatto –

5

Se non si desidera impostare lo slugfield su Non modificabile, credo che si desideri impostare le proprietà Null e Blank su False. In caso contrario, si verificherà un errore quando si tenta di salvare in Admin.

Quindi una modifica nell'esempio precedente sarebbe ::

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

oppure potresti usare editable = False: P – bx2

+0

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

101

C'è caso d'angolo con un po 'utf-8 caratteri

Esempio:

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

Questo può essere risolto con Unidecode

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

Questa è un'aggiunta molto importante che dovrebbe ricevere molta più attenzione (upvotes) per essere notata! –

+6

utf-8 è ora gestito correttamente da slugify (in django 1.8.5) –

+0

@ASz Seguendo le tue istruzioni, ho eseguito il upvoted. : D – learner

2

sto usando Django 1.7

Creare uno SlugField nel modello come questo:

slug = models.SlugField() 

Poi, nel definire admin.pyprepopulated_fields;

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