Django'da nasıl sülük oluştururum?


218

SlugFieldDjango'da bir tane oluşturmaya çalışıyorum .

Bu basit modeli oluşturdum:

from django.db import models

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

Sonra bunu yaparım:

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

Bekliyordum b-b-b-b.

Yanıtlar:


413

Slugify işlevini kullanmanız gerekecektir.

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

Yöntemi slugifygeçersiz kılarak otomatik olarak çağrı yapabilirsiniz 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)

Yukarıdakilerin qalan düzenlenirken URL'nizin değişmesine neden olacağını ve bu da bozuk bağlantılara neden olabileceğini unutmayın . Yeni bir nesne oluşturduğunuzda sülük yalnızca bir kez oluşturulması tercih edilebilir:

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)

4
utangaç özel bir model türü var mı? neden sadece CharField'leri slugify değil?
Johnd

23
SlugFields varsayılan olarak db_index = True değerini ayarlar ve varsayılan olarak geçerli sümüklü böcekler (bir ModelForm veya admin'de temsil ediliyorsa) için bir doğrulama regex'i olan bir form alanı kullanır. İsterseniz bunları bir CharField ile manuel olarak yapabilirsiniz, sadece kodunuzun amacını daha az netleştirir. Ayrıca, yöneticide JS tabanlı otomatik ön doldurma yapmak istiyorsanız prepopulate_fields ModelAdmin ayarını da unutmayın.
Carl Meyer

4
Derecik onun cevabını aşağıda belirttiğim üzere değiştirmeniz gerekir def save(self):ile def save(self, *args, **kwargs):böyle bir şey yazarken atılmış gelen önlemek hataları için test.objects.create(q="blah blah blah").
Liam

6
Bu kodun her bir tasarrufun bilgi güncellemesini yapacağına dikkat edin. URL'niz değişecek ve "Harika URI'ler değişmiyor" w3.org/Provider/Style/URI.html
dzen

18
slugify()bunun django.utils.text.slugifyne zaman eklendiğini, bunun ne zaman eklendiğini de bilmiyoruz.
mrmagooey

112

Bazı utf-8 karakterleri olan köşe kutusu var

Misal:

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

Bu Unidecode ile çözülebilir

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

7
utf-8 şimdi slugify (django 1.8.5'te) tarafından doğru bir şekilde işleniyor
Rick Westera

@RickWestera'nın bunun artık slugify tarafından işlendiğini belirttiği gibi, eğer herhangi bir nedenle slugify kullanmak istemiyorsanız, django.utils.encoding adresinden iri_to_uri'yi kontrol edin: docs.djangoproject.com/en/2.0/ref/unicode/…
Erwol

64

Thepeer'in cevabına küçük bir düzeltme: save()Model sınıflarındaki işlevi geçersiz kılmak için, ona daha iyi argümanlar ekleyin:

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)

Aksi takdirde, test.objects.create(q="blah blah blah")bir sonuçlanacaktır force_inserthatası (beklenmeyen argüman).


2
İmparatorun cevabına eklemek için çok küçük bir şey daha var: Son satırı yapacağım return super(test, self).save(*args, **kwargs). Bu yöntemin geri döndüğünü düşünüyorum Noneve bunu değiştirmek için herhangi bir plan bilmiyorum, ancak gelecekte bir zaman değişmesi durumunda üst sınıf yönteminin ne yaptığını döndürmek zarar vermez.
Duncan Parkes

Lütfen bu çözüm için django.utils.text import slugify öğesinin gerekli olduğunu ekleyin .
Routhinator

1
@Routhinator yaptı
Jonas Gröger

Bunu hissetmek için hala tercih edilen bir yöntem olup olmadığını sormak için bazı duygular ortaya koymak.
sytech

29

Eğer modelin yeni öğeler eklemek için yönetici arayüzünü kullanıyorsanız, bir kurabilirsiniz ModelAdminGözlerinde farklı admin.pyve kullanmak prepopulated_fieldsbir sümüklü böcek giren otomatik hale getirmek için:

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

admin.site.register(Client, ClientAdmin)

Burada, kullanıcı namealanın yönetici formuna bir değer girdiğinde , slugotomatik olarak doğru bilgi girilir name.


Benim slugve namealanların çevirileri var. Bunu çevirilerle nasıl yapabilirim? Çünkü eklemeye çalıştım 'slug_en':('name_en',)ve öznitelik modelimde olmayan bir hata aldım.
patricia

22

Çoğu durumda sümüklü böcek değişmemelidir, bu yüzden sadece ilk kaydetmede hesaplamak istersiniz:

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

6

prepopulated_fieldsYönetici sınıfınızda kullanın :

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

admin.site.register(Article, ArticleAdmin)

1
Açıklayabilir misiniz? Yönetici projeyi nasıl etkiler?
Bryce

5

Eğer slugfield'ı Düzenlenebilir değil olarak ayarlamak istemiyorsanız, Boş ve Boş özelliklerini Yanlış olarak ayarlamak isteyeceğinize inanıyorum. Aksi takdirde Yönetici'ye kaydetmeye çalışırken bir hata alırsınız.

Yukarıdaki örnekte yapılan bir değişiklik:

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


4

Django 1.7 kullanıyorum

Modelinizde şöyle bir SlugField oluşturun:

slug = models.SlugField()

Sonra admin.pytanımlamak prepopulated_fields;

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

Tam olarak istediğim
Nick

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.