django에서 auto_now와 auto_now_add 옵션은 어떤 차이가 있을까요? 간단하게 알아보도록 하겠습니다.

 


 먼저 Post는 다음과 같습니다. created는 auto_now_add를 붙였습니다. 그리고 modified는 auto_now를 붙였습니다. 이 둘만 봐도 어디에 어떻게 써야 할 지 눈치챌 수 있습니다. auto_now_add는 추가 될 때 현재 시각으로 들어가고, auto_now는 수정될 때 업데이트 시각을 위한 용도로 쓰겠구나.

 

 여기서 한 단계 더 나아가 봅시다.

 

 

 먼저, 3951번 포스트를 보겠습니다. 저는 / 요청을 날리면, 3951번 포스트를 업데이트 할 거에요.

 

 

 index 함수는 매우 간단합니다. / 요청이 들어왔을 때, 3951번 포스트의 content를 b로 업데이트 해 버립니다.

 

 

 결과는 어떻게 나올까요? auto_now_add는 당연하게도 업데이트가 되지 않았습니다. 그런데, auto_now로 설정된 수정된 날짜 필드인 modified도 업데이트가 되지 않았습니다. 이는 문서를 보면 알 수 있습니다. save 메서드 외에 다른 방법으로 업데이트 할 경우, auto_now가 업데이트 되지 않는다.

 

 저는 save 말고 update를 써서 3951번 포스트를 업데이트 했기에, modified가 변하지 않았습니다.

 

 

 반대로 post를 얻어와서, 적당히 content를 바꾼 후에 save() 메서드를 호출해 보겠습니다.

 

 

 그러면 12월 2일 오후 3:21분에 수정되었다는 정보가 업데이트 됩니다. 결국 save() 메서드가 호출된 경우, auto_now는 업데이트 된다로 정리할 수 있습니다.

 


 이제 post를 추가해 봅시다. 이 경우, 어떻게 동작할까요?

 

 "abcdefg"라는 콘텐츠를 가지고, 작성자가 "chokw"인 포스트를 어드민 페이지에서 하나 추가해 보겠습니다.

 

 

 어? save가 호출되었습니다. 고로, modified도 추가한 날짜로 업데이트가 될 겁니다.

 

 

 정말 그런지 결과를 확인해 보니 그렇습니다.

 

 만약에 Post.objects.create를 부르면 어떻게 될까요?

 

 

 마찬가지로, modified에 추가된 날짜가 적힙니다. 디버그를 타고 들어가 보면 그 이유를 짐작할 수 있습니다.

 

 다른 것은 볼 필요 없고, obj.save가 나옵니다. save() 메서드가 불렸기 때문에, auto_now_add 뿐만 아니라 auto_now 필드도 쿼리가 수행된 시각으로 업데이트 됩니다. 여기까지, save() 메서드가 호출되면 auto_now로 설정된 필드가 업데이트 된다는 현상을 설명드렸습니다.

 


 이 현상이 왜 일어날까요? 저는 venv 환경을 이용해서 django 서버를 돌리고 있어요. 그러니, auto_now_add를 venv 패키지 전체에서 찾아봅시다.

 

 django/db/models/fields/__init__.py가 있습니다. 이 파일 내부로 들어가 봅시다.

 

 

이 파일에서 auto_now_add라는 키워드를 찾아봅시다. 그러면, pre_save라는 함수에 걸린다는 것을 알 수 있습니다. 이 함수를 보면, auto_now 속성을 가지거나, 아니면 auto_now_add 속성을 가지면서 add인 경우에 value를 설정함을 알 수 있어요.

 

 이 때 self는 무엇을 가리킬까요? app.Post.created, app.Post.modified와 같은 필드를 가리킵니다. 그런데, 위에서 save() 메소드가 호출될 때, auto_now는 value를 업데이트 한다고 설명을 했어요. 그런데 pre_save에 self.auto_now인 경우, value를 현재 시각으로 설정했습니다.

 

 그렇다면 save가 호출되기 전이나 후에, 해당 로직이 수행된다는 합리적인 추론이 가능합니다. 실제로, 문서를 보면 save가 시작할 때 signal 처럼 동작한다고 되어 있습니다. 이를 도식화를 시키면 아래와 같습니다.

 

 

 이 과정에서, 필드가 auto_now이거나, 혹은 auto_now_add 이면서 add인 경우를 검사하게 됩니다.

 

 

 검사해서 참이라면, 해당 필드를 어떤 값으로 업데이트 할 지에 대한 정보를 넘깁니다. 그러면 실제로 쿼리는 어떻게 실행될까요?

 

 

 업데이트 쿼리를 silk로 보면, created, modified 등의 필드에 어떤 값을 넣을지 판단한 다음에 query를 만들어서 한꺼번에 실행함을 볼 수 있습니다. 정리하면 auto_now_add는 추가될 때, 추가된 시각으로 업데이트를 합니다. add와 auto_now_add가 같이 붙으면 now로 값을 설정한다는 것을 보면 알 수 있습니다. auto_now는 추가되면 추가된 시각으로, 수정되면 수정된 시각으로 (정확히 말하면, save가 호출된 시각)으로 업데이트 됩니다.