Open gina0605 opened 4 years ago
참고로 BooleanField
대신 NullBooleanField
를 이용하자 is_valid()
값은 항상 False로, 제가 생각하기에 합당한 결과가 나왔습니다.
혹시 request에 필요한 값을 날리시기 전에 정의한 serializer나 model에서 field가 required=False 또는 blank=True 설정은 없는 상황인가요?
@YeonghyeonKO 네, serializer에서는 required=True
만 설정해두었고(사실 설정하지 않아도 default가 required=True
인 것 같긴 합니다) model에서는 딱히 설정한 것이 없습니다.
자답합니다.
우선, http request를 보낼 때 body에 보내는 내용은 DRF의 Parser에서 처리하게 됩니다. 이를 통해서 request.data
에 QueryDict object가 들어있게 되는 것입니다. 다만, http request의 body가 없을 경우 QueryDict가 아니라 Python dictionary가 되는 것 같습니다.
BooleanField
의 값이 없어도 is_valid
를 통과하는 이유는 DRF BooleanField document를 보면 알 수 있습니다. HTML incode input의 경우 BooleanField의 값이 주어지지 않아도 False
로 처리된다고 적혀있습니다.
When using HTML encoded form input be aware that omitting a value will always be treated as setting a field to False, even if it has a default=True option specified. This is because HTML checkbox inputs represent the unchecked state by omitting the value, so REST framework treats omission as if it is an empty checkbox input.
코드를 살펴보면, serializer의 각 field 값을 주어진 data에서 읽는 메소드인 get_value()가 있습니다.
BooleanField의 경우 default_empty_html
이 False
로 설정되어 있습니다. 그렇기 때문에 값을 입력하지 않아도 저절로 False로 처리되는 것입니다. NullBooleanField의 경우에는 default_empty_html
이 empty
로 설정되어 있습니다. empty는 DRF에서 정의한 class로, 입력된 값이 없는 경우를 의미합니다. (None
자체가 유의미한 값일 수 있기 때문에, 이와 구분하기 위해 존재합니다.) required=True
이고 get_value()
에서 값이 empty
일 경우 is_valid()
값이 False
가 됩니다.
False
로 설정됩니다. False
로 설정되지 않고, is_valid()
값이 False
입니다. request.data
의 Type이 QueryDict와 dictionary 두 가지가 나오는 이유는 DRF Parser와 관련된 내용입니다.도큐멘트에 적혀있는 내용인데 한참 헤맸네요ㅜㅜ 과제는 NullBooleanField
를 이용해 해결했습니다.
아 sql에서 db 보셨으면 모든 accepted가 false로 되는 이유를 설명해주신거 같습니다. 저도 비슷한 상황이 왔었는데 처리만 했었지 이유까지는 알아보지 않았는데 감사합니다!
과제 2 당시 이 부분의 명세가 불명료한 지점이 있었던 것 같은데, 일단 의도는 POST /api/v1/user/
및 POST /api/v1/user/participant/
request의 body에서 accepted
는 optional하고, 없는 경우 True
라는 것이었습니다. accepted는 optional하고 default로 한 쪽의 값을 갖는 것이 일반적인 서비스의 동작을 고려했을 때 좀 더 자연스러운 구현이라고 생각되고, 반대로 accepted
가 없을 때 400
이어야 한다는 명세도 없었긴 했습니다.
어쨌든 과제 2의 이 부분에 대해서는 어느 쪽으로 구현하셨어도 자연스러운 것으로 받아들이도록 하겠습니다. 다만 과제 3을 진행할 때는, #221 과 관련해 optional한 것으로 취급하고, default 값을 True
인 것으로 수정해주세요.
@gina0605 @YeonghyeonKO 관련 내용 과제 2, 과제 3에도 추가했습니다! 감사합니다. https://github.com/wafflestudio/rookies/commit/f2d66399890043cdfbfaedc5a5c2513a958761ae
문제 상황
POST /api/v1/user/participant/
를 구현하는 과정에서 발견한 현상입니다. accepted의 값을 넘겨주지 않았음에도 is_valid() 결과가 True였습니다. 이 현상을 테스트하기 위해 새로운 model과 serializer를 만들어보았습니다.테스트
새로운 app
booleanfield
를 만들어 테스트했습니다.booleanfield/models.py
booleanfield/serializers.py
python manage.py shell
컴퓨터 환경
settings.py는 제공받은 waffle_backend의 settings.py에서
INSTALLED_APPS
와TIME_ZONE
만 수정했습니다. 아래는 제 파이썬 환경입니다.질문
POST /api/v1/user/participant/ request
를 할 때, Body에 데이터를 넘겨주면 ViewSet에서request.data
가 QueryDict였고, 데이터를 아무것도 넘겨주지 않으면request.data
가 빈 dictionary였습니다. 왜request.data
의 type이 달라지나요?