web-dev-qa-db-ja.com

Django-Model.create()メソッドをオーバーライドしますか?

Django docs は、save()およびdelete()をオーバーライドする例のみをリストしています。ただし、モデルの追加処理は、作成されたときにのみ定義したいと思います。 Railsに精通している人にとっては、:before_createフィルタ。これは可能ですか?

69
ground5hark

__init__()をオーバーライドすると、pythonオブジェクトの表現がインスタンス化されるたびにコードが実行されます。Railsがわかりませんが、_:before_created_フィルターが鳴りますデータベースにオブジェクトが作成されたときに実行されるコードのように、データベースに新しいオブジェクトが作成されたときにコードを実行する場合は、save()をオーバーライドして、オブジェクトにpk属性かどうか。コードは次のようになります。

_def save(self, *args, **kwargs):
    if not self.pk:
        # This code only happens if the objects is
        # not in the database yet. Otherwise it would
        # have pk
    super(MyModel, self).save(*args, **kwargs)
_
135
Zach

post_saveシグナルを作成する方法の例( http://djangosnippets.org/snippets/500/ から)

from Django.db.models.signals import post_save
from Django.dispatch import receiver

@receiver(post_save, sender=User)
def create_profile(sender, instance, created, **kwargs):
    """Create a matching profile whenever a user object is created."""
    if created: 
        profile, new = UserProfile.objects.get_or_create(user=instance)

ここでは、シグナルを使用するのが最善か、カスタムの保存方法を使用するのが最善かについての思慮深い議論です https://web.archive.org/web/20120815022107/http://www.martin-geber.com/thought/2007/ 10/29/Django-signals-vs-custom-save-method /

私の意見では、このタスクに信号を使用すると、より堅牢で、読みやすくなりますが、より長くなります。

21
Michael Bylstra

これは古く、受け入れられている回答があり(Zach's)、より慣用的な回答(Michael Bylstra's)ですが、ほとんどの人が見ているGoogleでの最初の結果であるため、ここで、よりベストプラクティスのモダンジャンゴスタイルの答えが必要です

from Django.db.models.signals import post_save

class MyModel(models.Model):
    # ...
    @classmethod
    def post_create(cls, sender, instance, created, *args, **kwargs):
        if not created:
            return
        # ...what needs to happen on create

post_save.connect(MyModel.post_create, sender=MyModel)

ポイントはこれです:

  1. シグナルを使用します(詳細は 公式ドキュメントを参照
  2. niceネームスペースのメソッドを使用する(それが理にかなっている場合)...そして、@classmethod の代わりに @staticmethodほとんどの場合、コード内で静的クラスメンバーを参照する必要が生じるためです。

コアDjangoに実際のpost_createシグナル。 (メソッドの動作を変更するためにブール引数を渡す必要がある場合は、2つのメソッドである必要があります。)

14
NeuronQ

質問に文字通り答えるには、モデルのマネージャーのcreateメソッドは、Djangoで新しいオブジェクトを作成する標準的な方法です。オーバーライドするには、次のようにします

_from Django.db import models

class MyModelManager(models.Manager):
    def create(self, **obj_data):
        # Do some extra stuff here on the submitted data before saving...
        # For example...
        obj_data['my_field'] = my_computed_value(obj_data['my_other_field'])

        # Now call the super method which does the actual creation
        return super().create(**obj_data) # Python 3 syntax!!

class MyModel(models.model):
    # An example model
    my_field = models.CharField(max_length=250)
    my_other_field = models.CharField(max_length=250)

    objects = MyModelManager()
_

この例では、Managerのメソッドcreateメソッドをオーバーライドして、インスタンスが実際に作成される前に追加の処理を行います。

注:のようなコード

my_new_instance = MyModel.objects.create(my_field='my_field value')

この変更されたcreateメソッドを実行しますが、次のようなコード

my_new_unsaved_instance = MyModel(my_field='my_field value')

しない。

6
Mark Chackerian

__init__()をオーバーライドすると、モデルがインスタンス化されたときにコードを実行できます。親の__init__()を呼び出すことを忘れないでください。

カスタムマネージャーでcreateメソッドをオーバーライドするか、モデルクラスにclassmethodを追加できます。 https://docs.djangoproject.com/en/1.11/ref/models/instances/#creating-objects

3
Ryan Allen

望ましい答えは正しいですが、オブジェクトが作成されているかどうかを判断するテストは、モデルがUUIDModelから派生している場合は機能しません。 pkフィールドにはすでに値があります。

この場合、これを行うことができます:

already_created = MyModel.objects.filter(pk=self.pk).exists()

1
Julio Carrera