작성
·
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)
코딩에 재미를 느껴주셔서 감사해요. 화이팅입니다. :-)