-
ManyToManyField 사용법 및 장점Django 2022. 1. 9. 20:16
기존의 모델링 1차 프로젝트 진행 중에 팀원분께서 제품 상세페이지를 맡아서 진행 중이셨는데 위의 products 테이블의 id 값을 받아서 sizes 테이블의 값 불러오는 것을 어려워하셨습니다.
위의 모델링을 기반으로 하여 사이즈 값을 가져오려면 아래처럼 복잡한 과정을 거쳐야 가능하다고 생각합니다.
products 테이블의 id 값을 통해서 sizes 테이블의 값을 가져오는 과정 주의해야 할 부분
1. 조건에 해당하는 결괏값들이 여러 개일 거라 생각해서 filter를 사용했으니 기본적으로 QuerySet으로 나올 것이라고 예상해야 합니다. QuerySet의 경우에 어떻게 QuerySet을 제거하고 안에 든 값만 뺄 수 있을까 엄청 고민하면서 이것저것 시도해보다가 위와 같은 경우에서는 product_list[0]을 찍어보는 게 도움이 되었습니다. QuerySet에 대해 공부하셔도 헷갈리시다면 저처럼 하는 방법도 있다는 것을 알려드리고 싶네요.
2. 여기서 제가 제일 헷갈리고 어려워했던 부분이 Size.objects.get(id= ***)에서 ***로 표시한 부분입니다.
id는 int이기에 sizes 테이블에서 원하는 사이즈의 id 값이 1 이라면 id=1 이라고 하면 문제없이 연결될 것이라고 생각하고 했었는데 매번 instance(객체)를 입력하라는 에러 메시지를 마주했던 기억이 납니다.
Foreign Key로 연결된 경우에는 그에 해당하는 어떤 값이 아니라 객체(어떤 변수에 담아서)를 입력해야 합니다.
이렇게 product의 id 값을 통해서 size 값을 가져올 수는 있겠지만 너무 복잡합니다.
그래서 products_options를 중간테이블로 사용하기 위해서 아래처럼 모델링을 조금 수정했습니다.
products 테이블에 sizes라는 컬럼을 추가하고 이를 products_options 테이블의 id와 연결했습니다.
products 테이블의 sizes가 1 이고 products_options 테이블의 id가 다(N)를 의미합니다. (1:N)
모델링 수정 후 29번째 줄에 ManyToManyField를 설정하고 through=ProductOption(중간테이블)을 통해서 바로 Size 값에 접근할 수 있게 되었습니다.
모델링 수정 후 models.py 필수는 아니지만, 권장 사항으로는 ManyToManyField 필드명은, 관계된 모델 객체의 복수형으로 표현합니다.
ManyToManyField 적용하기 이전에 Size 테이블로 바로 접근하려고 하니 AttributeError가 발생한 상황 ManyToManyField 설정하기 이전과 달리
이제는 아래처럼 쉽게 사이즈 값에 접근할 수 있습니다.
ManyToManyField의 중간테이블을 'ProductOption'로 지정해서 '.sizes'를 통해서 바로 값에 접근할 수 있습니다. 정리 및 요약
1. 왜 Product와 Size를 다대다 관계로 설정했는가?
- 각 제품마다 XS, S, M, L, XL의 사이즈를 가지고 있기 때문에 (반대로 봐도 5개의 사이즈가 다른 모든 제품에도 적용이 되기 때문에)
2. size 정보를 알고 있을 때 어떻게 product 데이터를 가져올 수 있을까?
터미널에서 테스트한 것처럼 해당 size 조건에 맞는 객체를 가져와서 그 객체의 역참조를 활용해서 역참조 되는 테이블의 속성을 조건으로 명시하여 그에 해당하는 데이터가 없거나 여러 개일 경우에 filter를 쓰기에 리턴되는 데이터의 타입이 QuerySet이기에 for문을 통해서 해당 데이터의 테이블의 속성 중에 필요한 데이터만을 뽑아내면 됩니다.
역참조 예시 ManyToManyField를 이해하기 위해 참고한 글들입니다. 같이 보신다면 이해하시기 더 쉬울 것 같아서 공유합니다.
https://velog.io/@jiffydev/Django-9.-ManyToManyField-1
Django 9. ManyToManyField 1
1. Many-to-Many relationship 데이터베이스의 Many-to-Many relationship(이하 다대다 관계)는 처음 접하는 사람들을 힘들게 한다. 한 테이블의 여러 레코드가 다른 테이블의 여러 레코드와 연결되어 있는 관계
velog.io
https://fierycoding.tistory.com/66?category=983255
[MySQL, Django]ManyToManyField를 쓰는 이유
👇 전반적인 예시 모델 class User(models.Model): email = models.EmailField(max_length=100) password = models.CharField(max_length=500) created_at = models.DateTimeField(auto_now_add=True) updated_at..
fierycoding.tistory.com
'Django' 카테고리의 다른 글
카카오 소셜 로그인 API - update_or_create() (0) 2022.01.15 ValueError: The QuerySet value for an exact lookup must be limited to one result using slicing (0) 2022.01.09 TypeError : Field 'id' expected a number but got <User : User object (1)> (0) 2022.01.05 Django 테이블 이름 변경 및 삭제 후 마이그레이션시 에러 (0) 2021.12.28 Login의 View 작성시 피해야 할 코드 작성법 (0) 2021.12.23