장고 시그널 vs. 저장 방법 재정의


89

머리를 감는 데 문제가 있습니다. 지금은 다음과 같은 모델이 있습니다.

 def Review(models.Model)
    ...fields...
    overall_score = models.FloatField(blank=True)

def Score(models.Model)
    review = models.ForeignKey(Review)
    question = models.TextField()
    grade = models.IntegerField()

리뷰에는 여러 "점수"가 있으며, 전체 점수는 점수의 평균입니다. 리뷰 나 점수가 저장되면 전체 점수 평균을 다시 계산해야합니다. 지금은 재정의 된 저장 방법을 사용하고 있습니다. Django의 신호 디스패처를 사용하면 어떤 이점이 있습니까?

답변:


85

저장 / 삭제 신호는 일반적으로 문제의 모델에 완전히 한정되지 않은 변경을 수행해야하거나 공통점이있는 모델에 적용 할 수 있거나 모델간에 사용하도록 구성 할 수있는 상황에서 유리합니다.

재정의 된 save메서드의 일반적인 작업 중 하나 는 모델의 일부 텍스트 필드에서 슬러그를 자동으로 생성하는 것입니다. 여러 모델에 대해 구현해야하는 경우 pre_save신호 처리기가 슬러그 필드의 이름과 슬러그를 생성 할 필드의 이름을 가져올 수 있는 신호 를 사용하여 이점을 얻을 수있는 예입니다. 이와 같은 기능이 있으면 모든 모델에도 적용됩니다. 예를 들어 문제의 모델 유형에 대해 추가하려는 슬러그를 찾아 고유성을 보장합니다.

재사용 가능한 애플리케이션은 종종 신호 사용의 이점을 얻습니다. 제공하는 기능을 모든 모델에 적용 할 수있는 경우 일반적으로 (피할 수없는 경우가 아니라면) 사용자가 이점을 얻기 위해 모델을 직접 수정하지 않아도됩니다.

함께 장고 - mptt , 예를 들어, 내가 사용하는 pre_save약을 만들거나 업데이트 할 수있는 모델과에 대한 트리 구조 설명 필드의 집합을 관리하기 위해 신호를 pre_delete삭제되는 개체에 대한 트리 구조의 세부 사항을 제거하는 신호를 그 전체를 그 이전의 개체의 하위 트리 및 삭제됩니다. 시그널을 사용하기 때문에 사용자 는 이러한 관리를 수행하기 위해 모델에 save또는 delete메소드 를 추가하거나 수정할 필요가 없으며, 관리 할 모델을 django-mptt에게 알려 주기만하면됩니다.


신호 처리기가 예외를 트리거하면 어떻게됩니까? 나는 그들이 예외를 유발해서는 안된다고 생각합니다. 그렇지 않으면 그들은 적합하지 않습니다. 내가 잘못?
x-yuri

20

질문 :

Django의 신호 디스패처를 사용하면 어떤 이점이 있습니까?

장고 문서에서 이것을 찾았습니다.

재정의 된 모델 메서드는 대량 작업에서 호출되지 않습니다.

개체에 대한 delete () 메서드는 QuerySet을 사용하여 대량으로 개체를 삭제할 때 또는 계단식 삭제의 결과로 반드시 호출되는 것은 아닙니다. 사용자 정의 된 삭제 로직이 실행되도록하려면 pre_delete 및 / 또는 post_delete 신호를 사용할 수 있습니다.

아쉽게도 save (), pre_save 및 post_save가 호출되지 않기 때문에 대량으로 개체를 생성하거나 업데이트 할 때 해결 방법이 없습니다.

From : 미리 정의 된 모델 메서드 재정의


3
Django 관리자 목록보기는 대량 삭제를 사용합니다.이 문제를 발견 할 때까지 혼란 스러웠습니다.
N.Balauro

8
또한 "안타깝게도 save (), pre_save 및 post_save가 호출되지 않았기 때문에 대량으로 객체를 생성하거나 업데이트 할 때 해결 방법이 없습니다."라고 말합니다. -그래서 나는 이것이이 방법들 사이의 절충안이라고 생각하지 않습니다.
Cory

이것은 두 방법 모두에 적용됩니다. 그래서 대답은 "아니요, save방법 을 재정의하는 것과는 반대로 신호를 사용하는 것은 이점이 없습니다 "?
Flimm

3

신호를 사용하는 경우 관련 점수 모델이 저장 될 때마다 리뷰 점수를 업데이트 할 수 있습니다. 그러나 그러한 기능이 필요하지 않다면 이것을 신호에 넣을 이유가 없다고 생각합니다. 그것은 꽤 모델과 관련된 것입니다.



1

대량 삭제에 대한 Django 문서의 작은 추가 ( 객체 .delete()에 대한 메서드 QuerySet) :

가능할 때마다 이것은 순수하게 SQL에서 실행되므로 개별 개체 인스턴스의 delete () 메서드가 프로세스 중에 반드시 호출되는 것은 아닙니다. 모델 클래스에 사용자 정의 delete () 메서드를 제공하고 호출되었는지 확인하려면 해당 모델의 인스턴스를 "수동으로"삭제해야합니다 (예 : QuerySet를 반복하고 다음에서 delete () 호출). QuerySet의 대량 delete () 메서드를 사용하는 대신 각 개체를 개별적으로).

https://docs.djangoproject.com/en/1.11/topics/db/queries/#deleting-objects

대량 업데이트 ( 객체 .update()에 대한 방법 QuerySet) :

마지막으로 update ()는 SQL 레벨에서 업데이트를 수행하므로 모델에서 save () 메소드를 호출하지 않으며 pre_save 또는 post_save 신호 (Model.save (호출의 결과)를 방출하지 않습니다. )). 사용자 정의 save () 메서드가있는 모델의 레코드를 업데이트하려면 루프를 반복하고 save ()를 호출합니다.

https://docs.djangoproject.com/en/2.1/ref/models/querysets/#update


이것은 둘 다에 적용되지 않습니까?
Flimm
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.