Djangoでスラッグを作成するにはどうすればよいですか?


218

SlugFieldDjangoでを作成しようとしています。

私はこの単純なモデルを作成しました:

from django.db import models

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

次にこれを行います:

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

期待していましたb-b-b-b

回答:


413

slugify関数を使用する必要があります。

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

メソッドをslugifyオーバーライドすることで自動的に呼び出すことができます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)

上記の場合、qフィールドを編集するとURLが変更され、リンクが壊れる可能性があることに注意してください。新しいオブジェクトを作成するときにスラグを1回だけ生成することが望ましい場合があります。

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
恥ずかしがり屋の特別なモデルタイプですか?なぜCharFieldsをslugifyしないのですか?
Johnd、2009年

23
SlugFieldsはデフォルトでdb_index = Trueを設定し、有効なスラッグを要求するための検証正規表現を持つフォームフィールドをデフォルトで使用します(ModelFormまたはadminで表されている場合)。必要に応じて、CharFieldを使用してこれらのことを手動で実行できます。コードの意図が不明確になるだけです。また、管理者にJSベースの自動事前入力が必要な場合は、prepopulate_fields ModelAdmin設定を忘れないでください。
カールマイヤー

4
ディングルが彼の回答で以下に述べたように、のようなものを書くときにエラーがスローされないようにするにdef save(self):def save(self, *args, **kwargs):、で置き換える必要がありますtest.objects.create(q="blah blah blah")
リアム

6
このコードは、保存するたびにスラッグを更新することに注意してください。あなたのURLは変化し、「クールなURIは変化しない」w3.org/Provider/Style/URI.html
dzen

18
slugify()django.utils.text.slugifyこれはいつ追加されたかは不明ですが、にも記載されています。
mrmagooey 2013

112

一部のutf-8文字のコーナーケースがあります

例:

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

これはUnidecodeで解決できます

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

7
utf-8はslugify(django 1.8.5)によって正しく処理されるようになりました
Rick

@RickWesteraは、何らかの理由であなたがslugify使用したくない場合は、django.utils.encodingからiri_to_uriをチェックするが、これは今、slugifyによって処理されて言ったように:docs.djangoproject.com/en/2.0/ref/unicode/...を
エルウォル

64

Thepeerの答えの小さな修正:save()モデルクラスの関数をオーバーライドするには、引数を追加することをお勧めします。

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)

それ以外の場合test.objects.create(q="blah blah blah")は、force_insertエラーになります(予期しない引数)。


2
ピアの答えに追加するもう1つの非常にマイナーなこと:最後の行を作成しreturn super(test, self).save(*args, **kwargs)ます。このメソッドはを返すと思いますがNone、変更する予定はわかりませんが、将来変更される可能性がある場合にスーパークラスのメソッドが何を返すかは問題ありません。
ダンカンパークス

このソリューションには、django.utils.textインポートからslugifyが必要であること追加してください。
Routhinator 2016年

1
@Routhinatorがやった
JonasGröger16年

これがまだこれを行うための好ましい方法であるかどうかを尋ねるいくつかの触覚を出す。
sytech 2018年

29

管理インターフェースを使用してモデルの新しい項目を追加している場合は、にを設定して、スラッグの入力を自動化するために利用できModelAdminます。admin.pyprepopulated_fields

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

admin.site.register(Client, ClientAdmin)

ここでは、ユーザーが管理フォームにnameフィールドの値をslug入力すると、に正しいslugifiedが自動的に入力されますname


slugnameフィールドには翻訳があります。翻訳でどうすればよいですか?追加しよう'slug_en':('name_en',)としましたが、属性がモデルに存在しないというエラーが発生しました。
パトリシア

22

ほとんどの場合、スラッグは変更されるべきではないので、最初の保存時にのみ計算する必要があります。

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_fieldsあなたの管理者クラスで使用してください:

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

admin.site.register(Article, ArticleAdmin)

1
説明してもらえますか?管理者はプロジェクトにどのように影響しますか?
ブライス2013年

5

slugfieldを編集不可に設定したくない場合は、NullプロパティとBlankプロパティをFalseに設定する必要があると思います。そうしないと、Adminで保存しようとするとエラーが発生します。

したがって、上記の例を変更すると次のようになります。

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を使用しています

次のようにモデルにSlugFieldを作成します。

slug = models.SlugField()

次に、admin.py定義しますprepopulated_fields

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

まさに私が欲しかったもの
ニック

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.