AI Briefing

장고 ORM에서 역방향 외래 키 참조 찾기

·2020.11.29 20:00

장고의 `_meta.related_objects`로 역방향 ForeignKey를 모두 찾아 일괄 수정한다.

순방향 ForeignKey는 해당 필드 값만 바꾸면 끝나지만, 역방향 참조는 그 객체를 가리키는 모든 모델의 레코드를 먼저 바꿔야 한다. 예제로는 ProductCategory-Product-Purchase-Sell 구조를 두고, 잘못 분류된 상품의 카테고리를 수정하는 경우와 중복 생성된 상품을 하나로 합치는 경우를 나눈다.

Product의 카테고리 오타처럼 순방향 참조를 고칠 때는 Product.objects.filter(...).update(category=...)처럼 단순하게 처리할 수 있다. 반면 product_2를 삭제하기 전에 PurchaseSell에서 product_2를 참조하는 모든 행을 product_1로 먼저 옮겨야 하며, 같은 앱 안에서만 참조를 확인하는 방식은 다른 앱의 모델을 놓칠 수 있다.

이때 핵심이 **_meta.related_objects**다. 모델 클래스의 _meta에는 관계 메타데이터가 들어 있고, 그중 related_objects를 순회하면 해당 모델을 참조하는 역방향 관계들을 찾을 수 있다.

  • related_object.related_model: 참조하는 모델 클래스
  • related_object.remote_field.name: 외래 키 필드명
  • related_object.get_accessor_name(): 역참조 접근자 이름

예시에서는 Product._meta.related_objects에서 Purchase, Sell, ProductStatistics 같은 관계를 확인할 수 있고, 각 항목은 ManyToOneRel로 표시된다. ManyToOneRel만 골라 model.objects.filter(**{field_name: product_2}).update(**{field_name: product_1})처럼 처리하면, Product를 가리키는 모든 ForeignKey를 빠짐없이 갱신할 수 있다.

_meta.related_objects에는 ManyToOneRel뿐 아니라 OneToOneRel, ManyToManyRel도 섞일 수 있으므로, 이 글의 방식은 ManyToOneRel만 대상으로 제한한다. 관계 타입마다 수정 방식이 다르기 때문에, 같은 패턴으로 처리하기보다 관계별로 맞는 로직을 적용해야 한다.

마지막에는 product_2.delete()로 중복 데이터를 정리하면 된다. 필요하면 SQL 메타데이터를 조회해서 역방향 참조를 확인하는 방법도 있으며, PostgreSQL에서는 Dataedo 문서를 참고할 수 있다.

이 요약은 원문 이해를 돕기 위한 큐레이션입니다. 저작권은 원저작자에게 있으며, 정확한 내용과 맥락은 원문을 확인하세요.

요약 오류, 출처 표기 문제, 삭제 요청은 문의 · 건의로 알려주세요.