본문 바로가기

WebDev

Django Foreign Key

Django Foreign Key

하… 정말 생각지도 못한 일로 2시간을 고통받고 글을 쓴다.
공식 문서에 Foreign Key에 대한 문서가 잘 되어있었기에 확실히 해결할 수 있었던 문제다.

결론부터 말하자면, Foreign Key는 기본으로 CASCADE정책을 사용한다!!!

문제 설명

class DatePost(models.Model):
    couple = models.ForeignKey(Couple, related_name='dataposts')
    title = models.CharField(max_length=100)
    message = models.CharField(max_length=1000)
    tags = ArrayField(models.CharField(max_length=30), db_index=True)

커플은 데이트를 한다.
데이트를 하고 데이트포스트를 남긴다.

문제는 DatePost를 삭제했더니, Couple까지 사라진다(…???)

이쯤에서 눈치챘어야 하지만… DRF를 쓰는 나는 의심할게 너무 많았다.
특히 Serializer에 read_only=True까지 넣어둔 상황이라 더 그랬다.

살펴본 것은 순서대로 아래와 같다:

  1. Serializer 가장 Model과 찰싹 붙어있는 녀석이므로 의심했으나, 아무 문제 없었다.
  2. ModelViewSet 혹시 이녀석이 문제를 일으키나 했는데, 단순히 Model의 delete()를 부르는 일을 할 뿐이었다.
  3. Model 흘겨봤으나 별 문제를 찾지 못했다.
  4. Model Collector 여기서 찾았다… 여기서 실제로 생성되는 SQL을 볼 수 있기 때문이었다..

4의 결과로 알아낸 것은, 자동 생성된 SQL이 꽤나 비효율적이라는 것과, 내 Couple을 DELETE 2차 쿼리에서 삭제한다는 것이었다.

문제 해결

결국,

couple = models.ForeignKey(Couple, on_delete=models.SET_NULL, null=True, related_name='dataposts')

로 코드를 수정하고 나서 나는 광명을 되찾았다.

이 참에 자주 사용될 on_delete옵션을 정리했다.

  • CASCADE 같이 죽어버린다…
  • SET_NULL null로 값을 바꿔놓는다. 단 null=True로 선언되어 있어야 한다.
  • SET_DEFAULT default value로 값을 바꿔놓는다.
  • SET(value) value로 값을 설정한다. value로는 함수(callable)를 보낼 수도 있다.

Django 1.9부터는 on_delete가 필수 매개변수가 된다고 한다.
Django 2.0부터는 on_delete가 kwargs에서 두번째 매개변수로 강제된다고 한다.


'WebDev' 카테고리의 다른 글

AWS  (0) 2016.03.02
letsencrypt  (0) 2016.02.29
Require.js  (0) 2016.02.20
tosync.js  (0) 2016.02.20
Chrome extension 개발  (0) 2016.02.16