본문 바로가기
관리자

Programming-[Backend]/Django

[TIL] Django soft delete cascade (SafeDeleteModel), deleted null 아닌 항목만 찾기

728x90
반응형

soft Delete

 

연관관계가 있는 모델끼리는 SafeDeleteModel을 상속받고, Cascade 옵션이 적용되어 있다면 soft delete도 cascade 된다.SafeDeleteModelsoft_delete_cascade_policy_action() 메서드를 사용하는 경우 적용된다.

 

Post : RelatePost = 1 : N인 관계가 있고, RelatePost에서 post를 FK로 갖고 있을 때, 아래와 같이 SafeDeleteModel을 상속받고 FK로 CASCADE 옵션이 지정된 상황이라고 가정한다.

class RelatePost(SafeDeleteModel):
	post = ForeignKey(
    	Post,
        on_delete=CASCADE,
        related_name="relate_post"
        )

 

Post도 SafeDeleteModel을 상속받고 있다면 아래와 같이 사용할 수 있다.

Post.soft_delete_cascade_policy_action()

 

만약 post_id = 1 이 relate_post_id = [1, 2, 3] 3개와 연관 관계를 갖는 경우, 위처럼 soft_Delete_cascade_policy_action을 적용하면 relate_post 3개도 모두 soft-delete 된다.

 

 

1depth 까지만 적용

**다만 cascade 옵션은 1 depth 까지만 적용된다! post -> relate_post -> comment 로 이어지는 구조라면 post를 delete 했을 때 comment 까지 deleted 처리되지는 않음을 기억하자


 

safeDeleteModel을 보면 추가적인 메서드들이 있는 것을 볼 수 있다. delete의 정책을 결정해서 soft-delete를 할 수 있다.

 

SafeDeleteModel의 _delete 코드 일부:

        if current_policy == NO_DELETE:
            # Don't do anything.
            return
        elif current_policy == SOFT_DELETE:
            self.soft_delete_policy_action(**kwargs)
        elif current_policy == HARD_DELETE:
            self.hard_delete_policy_action(**kwargs)
        elif current_policy == HARD_DELETE_NOCASCADE:
            self.hard_delete_cascade_policy_action(**kwargs)
        elif current_policy == SOFT_DELETE_CASCADE:
            self.soft_delete_cascade_policy_action(**kwargs)

 

 


deleted 아닌 항목만 찾기

 

SafeDeleteModel이 적용된 모델은 django orm으로 쿼리를 날려도 결과에 포함되지 않는다. 그리고 deleted__isnull=False와 같이 필터에 옵션을 주더라도 deleted된 항목을 가져오지 못한다.

 

Post.objects.filter(deleted__isnull=False)
# X

 

이것은 objects를 구현하는 Manager 클래스를 SafeDeleteManager가 override하여 objects를 처리할 때 deleted 되지 않은 항목만 나오도록 하기 때문이다.

 

SafeDeleteManager의 코드 중 일부는 다음과 같다.

#...중략
_safedelete_policy = SOFT_DELETE

objects = SafeDeleteManager()
all_objects = SafeDeleteAllManager()
deleted_objects = SafeDeleteDeletedManager()

여기서 all_objects를 적용하면 deleted와 상관없이 모든 레코드를 불러올 수 있고, deleted_objects를 적용하면 deleted 처리된 항목들만 불러올 수 있다.

728x90
반응형