web-dev-qa-db-ja.com

CharFieldからSlugFieldにデータを入力する簡単な方法はありますか?

class Foo(models.Model):
    title = models.CharField(max_length=20)
    slug = models.SlugField()

タイトルに基づいてスラッグフィールドを自動入力する組み込みの方法はありますか?おそらく、管理者内および管理者の外部。

35
ashchristopher

Django 1.0以降の管理者の場合、使用する必要があります

prepopulated_fields = {'slug': ('title',), }

admin.pyで

Prepopulated_fieldsディクショナリのキーは入力するフィールドであり、値は連結するフィールドのタプルです。

Adminの外部では、ビューでslugify関数を使用できます。テンプレートでは、|slugifyフィルターを使用できます。

これを自動的に処理するこのパッケージもあります: https://pypi.python.org/pypi/Django-autoslug

62
camflan

管理者の外部については、 this Django snippet を参照してください。.save()に入れると、プログラムで作成されたオブジェクトで機能します。管理者の内部、他の人が言っているように、prepopulated_fieldsを使用します。

6
AdamKG

1.0より前の場合:

slug = models.SlugField(prepopulate_from=('title',))

正常に動作するはずです

1.0の場合、 camflan's を使用します

3
Nick Sergeant

Pre_save Djangoシグナルを使用して、Django管理コードの外側にスラッグを設定することもできます。 Djangoシグナルのドキュメント を参照してください。

Ajaxスラッグの一意性の検証も役立ちます。 As-You-Typeスラッグの一意性の検証@ Irrational Exuberance を参照してください。

2
carefulweb

autoslug は、過去に私にとって非常にうまく機能しました。管理アプリで使ってみたことはありませんが。

0
Jon Lemmon

私は言及された落とし穴で完全で最新の答えを追加すると思いました:

1. Django管理者にフォームを自動入力する

管理者でのデータの追加と更新のみに関心がある場合は、 prepopulated_fields 属性を使用できます。

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

admin.site.register(Article, ArticleAdmin)

2.テンプレートにカスタムフォームを自動入力します

フォームを使用して独自のサーバーレンダリングインターフェイスを構築した場合は、フォームの保存時に slugify tamplate filterまたは slugify ユーティリティのいずれかを使用してフィールドに自動入力できます。 (is_valid)。

3.Django-autoslugを使用してモデルレベルでスラッグフィールドを自動入力する

上記のソリューションは、データがこれらのインターフェイス(管理者またはカスタムフォーム)を介して操作される場合にのみ、スラッグフィールド(または任意のフィールド)に自動入力されます。 API、管理コマンド、またはデータを操作するその他のものがある場合は、モデルレベルにドロップダウンする必要があります。

Django-autoslug AutoSlugFieldを提供します-SlugFieldを拡張し、どのフィールドを適切にスラッグ化するかを設定できるフィールド:

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 = '新しい投稿')は[〜#〜] not [〜#〜]スラッグを更新します任意の記事の
  • Articleモデルで bulk_create または bulk_update を使用すると、[〜#〜] not [〜#〜]記事のスラッグを更新します。
  • Save()メソッドが呼び出されないため、pre_saveまたはpost_saveシグナルは発行されません

一括更新を実行し、それでもコードレベルの制約を利用するには、オブジェクトを1つずつ繰り返し、SQLレベルの一括操作よりもパフォーマンスが大幅に低いsave()メソッドを呼び出すことが唯一の解決策です。もちろん、データベースでトリガーを使用することもできますが、それはまったく別のトピックです。

0