web-dev-qa-db-ja.com

Djangoフィールドにpre_save()?

class TodoList(models.Model):
    title = models.CharField(maxlength=100)
    slug = models.SlugField(maxlength=100)
    def save(self):
        self.slug = title
        super(TodoList, self).save()

タイトルがテーブルTodoListに挿入されたときにスラッグを作成して保存する方法は上記のようであると想定していますが、そうでない場合は修正してください!

とにかく、私はこれを行う別の方法としてpre_save()を検討していましたが、それがどのように機能するのかわかりません。 pre_save()でどのように行うのですか?

みたいですか

def pre_save(self):
     self.slug = title

私は推測しています。これを行うコードは何ですか?

ありがとう!

46
Derek

ほとんどの場合、 Djangoの_pre_save_ signal を参照しています。次のような設定ができます。

_from Django.db.models.signals import pre_save
from Django.dispatch import receiver
from Django.template.defaultfilters import slugify

@receiver(pre_save)
def my_callback(sender, instance, *args, **kwargs):
    instance.slug = slugify(instance.title)
_

@receiver(pre_save, sender=MyModel)のように、sender引数をデコレータに含めない場合、コールバックはすべてのモデルに対して呼び出されます。

アプリの実行中に解析される任意のファイルにコードを配置できます。_models.py_が適切な場所です。

72
@receiver(pre_save, sender=TodoList)
def my_callback(sender, instance, *args, **kwargs):
    instance.slug = slugify(instance.title)
23
Leandro Souza

Django signals.pre_save:

from Django.db.models.signals import post_save, post_delete, pre_save

class TodoList(models.Model):
    @staticmethod
    def pre_save(sender, instance, **kwargs):
        #do anything you want

pre_save.connect(TodoList.pre_save, TodoList, dispatch_uid="sightera.yourpackage.models.TodoList") 
11
Eyal Ch

pre_save() signal hook は、多数のモデルのスラッグ化を処理するのに最適な場所です。トリックは、どのモデルがナメクジを生成する必要があるか、どのフィールドがナメクジ値の基礎になるべきかを知ることです。

このためにクラスデコレータを使用します。このクラスデコレータは、モデルを自動スラッグ生成用にマークできるようにするものであり、どのフィールドに基づいているかを示します。

_from Django.db import models
from Django.dispatch import receiver
from Django.utils.text import slugify

def autoslug(fieldname):
    def decorator(model):
        # some sanity checks first
        assert hasattr(model, fieldname), f"Model has no field {fieldname!r}"
        assert hasattr(model, "slug"), "Model is missing a slug field"

        @receiver(models.signals.pre_save, sender=model)
        def generate_slug(sender, instance, *args, raw=False, **kwargs):
            if not raw and not instance.slug:
                source = getattr(instance, fieldname)
                slug = slugify(source)
                if slug:  # not all strings result in a slug value
                    instance.slug = slug
        return model
    return decorator
_

これにより、特定のモデルのみにシグナルハンドラが登録され、モデルごとにソースフィールドを変更できます。

_@autoslug("name")
class NamedModel(models.Model):
    name = models.CharField(max_length=100)
    slug = models.SlugField()

@autoslug("title")
class TitledModel(models.Model):
    title = models.CharField(max_length=255)
    slug = models.SlugField()
_

uniqueスラッグ値の生成は試行されないことに注意してください。それには、トランザクション内の整合性例外をチェックするか、衝突を起こさないように十分な大きさのプールからスラッグ内のランダム化された値を使用する必要があります。整合性例外チェックは、save()メソッドでのみ実行でき、シグナルフックでは実行できません。

1
Martijn Pieters

レシーバー関数は次のようにする必要があります。

def my_callback(sender, **kwargs):
    print("Request finished!")

関数はsender引数とワイルドカードキーワード引数(** kwargs);すべてのシグナルハンドラはこれらの引数を取る必要があります。

すべてのシグナルはキーワード引数を送信し、これらのキーワード引数はいつでも変更できます。

参照 ここ

0
Rockallite