본문 바로가기

개발/장고

[해설과 함께 읽는 Django 문서] Models - 다 대 일 관계

반응형
Models_5_many_to_one

원문 링크

한국어로 옮기기 어색한 단어들은 영문으로 혹은 해석이 애매한 구절은 직역한 그대로 사용 하였습니다.

다 대 일 관계

다 대 일 관계를 정의하기 위해서는 django.db.models.ForeignKey 를 사용해야한다. 당신은 다른 Field type을 사용했던 것처럼 사용할 수 있다:당신의 모델의 클래스 속성으로 포함하는 방법으로 사용가능하다

외래키는 positional argument를 요구한다.:모델과 관련된 클래스

예를 들면, 만약에 Car 모델이 Manufacturer 를 가지고 있다면 -즉, Manufacturer 가 여러개의 자동차를 만들 수 있으나 각각의 Car 는 오직 1개의 Manufacturer 를 가진다- 아래와 같이 정의할 수 있다.

당신은 재귀적인 관계와(다대일 관계가 있는 객체), 모델에 정의되지 않은 관계를 생성할 수 있다.;자세한 내용은 모델 필드 레퍼런스를 보자

외래키 필드의 이름 (위 예의 manufacturer)은 모델 이름 (소문자)이 권장되지만 필수는 아니다. 당신은 원하는대로 필드를 호출 할 수 있다.(company_that_makes_it 처럼) 예를들면,

See also

외래키 필드는 모델 필드 레퍼런스 에 설명되어있는 추가적인 argument 몇개를 허락한다. 이러한 옵션들은 어떻게 관계가 동작해야하는지 정의하는 것을 도와준다: 모든 것은 선택적으로 사용가능하다

역관계 객체에 접근하는 자세한 방법은 Following relationships backward example 를 보자

샘플코드가 필요하다면, 다대일 관계 모델 예제 를 보자


내 마음대로 해설

위 글은 전형적인 다대일 관계를 어떻게 설정하는지에 대해서 적혀 있다. 요약하면 다음과 같다.

1.제조사와 자동차의 관계, 글과 댓글의 관계 등등 어떤 모델이 N개의 모델을 가질 수 있으나, 반대로는 성립하지 않을 때 다대일 관계로 본다

2.이때, django.db.models.ForeignKey 를 사용해라

윗 내용이 가장 중요한 내용이고, 외래키 필드의 이름이 소문자가 필수가 아니라고 나와있지만, 소문자가 아닌 필드명을 본적이 없는 것 같다. 그냥 권장하는 대로 사용하자.

위 설명 중 좀 애매하게 나와있는 부분은 아래 2가지 일 것 같다.

1.재귀적인 관계(다대일 관계가 있는 객체)

2.모델에 정의되지 않은 관계

이 부분에 대해서 조금 자세히 살펴보기 위해서 위의 설명대로 모델 필드 레퍼런스를 보면 아래와 같은 내용을 확인할 수 있다


1.재귀적인 관계

원문 상에서는 models.ForeignKey('self', on_delete=models.CASCADE) 를 사용하는 것이라고 나와있다.

이와 같은 코드를 활용하는 시기는 부모와 자식 노드 간에 동일한 모델 구조 가지길 원할 때 사용한다. 가장 쉬운 예는 대댓글을 구현할 때를 생각해볼 수 있다.

예제 코드는 아래와 같다.

 

위의 상태에서, 부모 댓글 1개와 그 대댓글인 자식 댓글 2개를 생성하였을 때 아래와 같이 테이블에 값이 쌓여있을 것이다.

이런 경우를 표현할 때, models.ForeignKey('self', on_delete=models.CASCADE) 가 유용하게 사용될 수 있다.

2.모델에 정의되지 않은 관계

모델에서 외래키를 이용해서 관계를 설정하는 방법은 2가지가 있다.

(1)

(2)

(1), (2) 을 모았을 때, 단순히 순서만 변경된 것으로 보이지만 사실은 Manufacturer 를 클래스 그대로 받느냐, 문자열 자체로 받느냐의 차이가 있다.

모델에 정의되지 않은 관계 여기서 (1) 에 해당된다. 이게 뭐 중요한가? 라고 생각할 수 있지만, (2) 코드에서 모델이 정의된 순서를 바꾸면, 에러가 발생한다. 그리고 이런 경우가 생각보다 되게 많다.

파이참에서 보면, 아래와 같이 에러가 발생하는 것을 확인할 수 있다.

스크린샷 2021-01-27 오전 1.35.59

즉, 정의된 순서와 상관없이, 외래키 관계 설정을 하고 싶다면, 그냥 문자열 그대로 써주면 된다. 개인적으로는 문자열을 그대로 써주는 편이 더 좋은 듯하다. 그렇지 않다면 일일이 정의된 순서를 모두 따져주어야 하기 때문이다.

참조

https://stackoverflow.com/a/13182912/11735129

 

반응형