인프런 커뮤니티 질문&답변

뤀쪼님의 프로필 이미지
뤀쪼

작성한 질문수

파이썬/장고 웹서비스 개발 완벽 가이드 with 리액트

instagram 앱 생성과 포스팅 쓰기 구현

공식 문서에서 get_or_create 관련 궁금한 점이 있습니다.

작성

·

195

0

안녕하세요 강사님.
다음은 get_or_create 관련 공식 문서의 예제?입니다.

class
Chapter(models.Model): title = models.CharField(max_length=255, unique=True) class Book(models.Model): title = models.CharField(max_length=256) chapters = models.ManyToManyField(Chapter)

You can use get_or_create() through Book’s chapters field, but it only fetches inside the context of that book:

>>> book = Book.objects.create(title="Ulysses")
>>> book.chapters.get_or_create(title="Telemachus")
(<Chapter: Telemachus>, True)
>>> book.chapters.get_or_create(title="Telemachus")
(<Chapter: Telemachus>, False)
>>> Chapter.objects.create(title="Chapter 1")
<Chapter: Chapter 1>
>>> book.chapters.get_or_create(title="Chapter 1")
# Raises IntegrityError

해당 부분에서 마지막에 IntegrityError가 발생하는데 이부분은
class Chapter의 title이 unique=True로 지정되어 있으나,
위에서 Chapter.objects.create(title="Chapter 1")를 진행해줘서 발생한 에러인가요?

그렇다면 unique=True를 없애준다면, (<Chapter: Chapter 1>, False)을 반환하리라 기대해도 좋을까요?

강사님 때문에 코딩이 재밌습니다ㅎㅎ 미래는 불투명하지만 화이팅하겠습니다!

 

답변 2

0

이진석님의 프로필 이미지
이진석
지식공유자

그리고, 장고 settings에 다음 로깅 설정을 추가하시고 장고 쉘을 다시 여시면, 각 ORM 코드 실행마다 수행되는 SQL 내역이 출력이 됩니다. 그럼 각 ORM 동작을 이해하시는 데에 큰 도움이 됩니다. // 저도 이 설정을 추가하여 질문주신 내용을 보다 정확하게 파악할 수 있었습니다.

단, 위 코드는 DEBUG=True 시에만 동작시켜주세요.

화이팅입니다. :D

0

이진석님의 프로필 이미지
이진석
지식공유자

안녕하세요.

1단계) Chapter.objects.create(title="Chapter 1") 코드를 통해 book 지정이 없이 Chapter가 생성이 된 상태이구요.

2단계) book.chapters.get_or_create(title="Chapter 1") 코드는
- book을 가지면서 title="Chapter 1" 인 Chapter를 찾아보고 (get 동작) 없으면 생성 (create 동작) 합니다.
- book을 가지면서 title="Chapter 1"인 Chapter는 현재 없습니다. 1단계의 코드는 book 지정이 없으니까 위 Row는 get 동작에서는 무시되는 거죠. 그래서 book도 지정하고 title="Chapter 1"인 Row를 생성할려고 DB에 insert 쿼리를 던졌는 데, title 필드가 unique=True 여서 title="Capter 1"이 중복이여서 오류가 발생하는 상황입니다.

그런데 Chapter 모델에서는 title 필드에 대해 unique=True 제약사항이 꼭 필요해보입니다. 그러니 ManyToManyField 에서는 아래와 같이 써보세요.

# Chapter에 대해 get_or_create를 해주시고
chapter, is_created = Chapter.objects.get_or_create(title="Chapter 1")
# M2M 필드에 대해서는 다음과 같이 add를 해주세요. add는 여러번 수행되더라도 관계를 1회만 저장됩니다.
book.chapters.add(chapter)

코딩에 재미를 느껴주셔서 감사해요. 화이팅입니다. :-)

뤀쪼님의 프로필 이미지
뤀쪼

작성한 질문수

질문하기