[django] Django-Model.create () 메서드 재정의?

장고 문서는 단지 오버라이드 (override)에 대한 예제 목록 save()delete(). 그러나 모델 이 생성 될 때만 모델에 대한 추가 처리를 정의하고 싶습니다 . Rails에 익숙한 사람이라면 :before_create필터 를 만드는 것과 같습니다 . 이것이 가능한가?



답변

재정의 __init__()하면 객체의 파이썬 표현이 인스턴스화 될 때마다 코드가 실행됩니다. 레일을 모르지만 :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)


답변

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 /

제 생각에는이 작업에 신호를 사용하는 것이 더 강력하고 읽기 쉽지만 더 길다고 생각합니다.


답변

이것은 오래되었고 작동하는 대답 (Zach ‘s)과 좀 더 관용적 인 대답 (Michael Bylstra ‘s)도 가지고 있지만 여전히 대부분의 사람들이 Google에서 보는 첫 번째 결과이기 때문에 더 많은 모범 사례 modern-django가 필요하다고 생각합니다. 여기 스타일 대답 :

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. 좋은 네임 스페이스를위한 방법을 사용하십시오 (이치가 있다면) … @classmethod대신 @staticmethod코드에서 정적 클래스 멤버를 참조해야 할 가능성이 높기 때문에 대신 표시했습니다.

핵심 Django가 실제 post_create신호를 가지고 있다면 더 깨끗할 것 입니다. (메소드의 동작을 변경하기 위해 부울 인수를 전달해야하는 경우 Imho는 2 개의 메서드 여야합니다.)


답변

문자 그대로 질문에 답하기 위해 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()

이 예에서는 create인스턴스가 실제로 생성되기 전에 몇 가지 추가 처리를 수행하기 위해 Manager의 메서드 메서드를 재정의합니다 .

참고 : 다음 과 같은 코드

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

이 수정 된 create메서드 를 실행 하지만 다음과 같은 코드

my_new_unsaved_instance = MyModel(my_field='my_field value')

하지 않을 것이다.


답변

재정의 __init__()하면 모델이 인스턴스화 될 때 코드를 실행할 수 있습니다. 부모에게 전화하는 것을 잊지 마십시오 __init__().


답변

사용자 지정 관리자로 create 메서드를 재정의하거나 모델 클래스에 클래스 메서드를 추가 할 수 있습니다. https://docs.djangoproject.com/en/1.11/ref/models/instances/#creating-objects


답변

선호하는 대답은 맞지만 모델이 UUIDModel에서 파생 된 경우 개체가 생성되고 있는지 여부를 알려주는 테스트가 작동하지 않습니다. pk 필드에는 이미 값이 있습니다.

이 경우 다음을 수행 할 수 있습니다.

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