CharFieldからSlugFieldを作成する簡単な方法はありますか?
質問
class Foo(models.Model):
title = models.CharField(max_length=20)
slug = models.SlugField()
タイトルに基づいてスラッグフィールドを自動入力する組み込みの方法はありますか?おそらく管理者と管理者の外部で。
解決
Django 1.0以降の管理者には、使用する必要があります
prepopulated_fields = {'slug': ('title',), }
admin.pyで
prepopulated_fields辞書のキーは入力するフィールドであり、値は連結するフィールドのタプルです。
adminの外部では、ビューで slugify
関数を使用できます。テンプレートでは、 | slugify
フィルターを使用できます。
これを自動的に処理するこのパッケージもあります: https://pypi.python .org / pypi / django-autoslug
他のヒント
管理者以外の方は、このdjangoスニペットをご覧ください。それを .save()
に入れると、プログラムで作成されたオブジェクトで動作します。管理者の内部では、他の人が言ったように、 prepopulated_fields
を使用します。
1.0より前の場合:
slug = models.SlugField(prepopulate_from=('title',))
正常に動作するはずです
1.0では、 camflan's を使用しますa>
また、pre_save djangoシグナルを使用して、django管理者コードの外部にスラッグを追加することもできます。 Djangoシグナルドキュメントを参照してください。
Ajaxスラッグの一意性検証も有用です。 As-You-Typeスラッグの一意性検証@ Irrational Exuberance
autoslug は、過去に私にとって非常にうまく機能しました。管理アプリで使用しようとしたことはありませんが。
言及された落とし穴を含む完全かつ最新の答えを追加すると思いました:
1。 Django Adminでのフォームの自動入力
管理者のデータの追加と更新のみに関心がある場合は、単に prepopulated_fields 属性
class ArticleAdmin(admin.ModelAdmin):
prepopulated_fields = {"slug": ("title",)}
admin.site.register(Article, ArticleAdmin)
2。テンプレートにカスタムフォームを自動入力する
フォームを使用して独自のサーバーレンダリングインターフェイスを構築している場合は、 | slugify tamplateフィルターまたは slugify ユーティリティ(フォームの保存時)(is_valid)。
3。 django-autoslugを使用したモデルレベルでのスラグフィールドの自動入力
上記のソリューションは、これらのインターフェイス(管理者またはカスタムフォーム)を介してデータが操作された場合にのみ、slugfield(または任意のフィールド)を自動入力します。 API、管理コマンド、またはデータを操作するその他のものがある場合は、モデルレベルにドロップダウンする必要があります。
django-autoslug は、SlugFieldを拡張して設定できるAutoSlugField-fieldsを提供します。どのフィールドをきれいにスラッグする必要があります:
class Article(Model):
title = CharField(max_length=200)
slug = AutoSlugField(populate_from='title')
フィールドはpre_saveおよびpost_save信号を使用してその機能を実現しているため、この回答の下部にある注意事項のテキストを参照してください。
4。 save()をオーバーライドしてモデルレベルでスラグフィールドを自動生成する
最後のオプションは、これを自分で実装することです。これには、デフォルトのsave()メソッドのオーバーライドが含まれます。
class Article(Model):
title = CharField(max_length=200)
slug = SlugField()
def save(self, *args, **kwargs):
self.slug = slugify(self.title)
super(Job, self).save(*args, **kwargs)
注:一括更新はコード(信号を含む)をバイパスします
これは、Djangoの初心者による一般的な誤解です。まず、pre_saveおよびpost_saveシグナルがsave()メソッドに直接関連していることを知っておく必要があります。第二に、Djangoで一括更新を行うさまざまな方法はすべて、SQLレイヤーで直接操作することで、save()メソッドを回避して高いパフォーマンスを実現します。つまり、上記のソリューション3または4で使用されているサンプルモデルの場合:
- Article.objects.all()。update(title = 'New post')は、記事のスラッグをしない更新しません
- bulk_create または bulk_update の記事モデルは NOT 記事のスラッグを更新します。
- save()メソッドが呼び出されないため、 pre_saveまたはpost_saveシグナルは送信されません。
一括更新を行い、コードレベルの制約を引き続き使用する唯一の解決策は、オブジェクトを1つずつ繰り返し、save()メソッドを呼び出すことです。これは、SQLレベルの一括操作よりも大幅にパフォーマンスが低下します。もちろん、データベースでトリガーを使用することもできますが、それはまったく異なるトピックです。