TypeError: Comment() got unexpected keyword arguments
Serializers.py
class CommentSerializer(serializers.ModelSerializer):
class Meta:
model = Comment
fields = '__all__'
read_only_fields = ['post']
Views.py
def post(self, request, post_id):
post = self.get_object(post_id)
serializer = CommentSerializer(data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save(post=post)
return Response(serializer.data, status=200)
위의 코드로 postman을 돌리면 아래의 이미지와 같이 user nickname,
user id, post id와 같이 자동으로 입력되어야 하는 값들도 작성하게 되어있다.
serializers.py를 보면 읽기전용 필드가 read_only_fields = ['post']
만 되어있어
['post_id', 'user_id', 'user_nickname']
로 변경해준다.
read_only_fields = ['post_id', 'user_id', 'user_nickname']
로 해두면
클라이언트들이 수정이 불가능하며, 해당 필드들은 서버에서 자동으로 설정된다.
다시 postman을 돌려보면 content 필드만 필수라고 나온다.
content 필드를 넣어서 구동을 시키면 아래의 오류가 나온다.
CommentSerializer에서 Comment.objects.create() 메서드 호출 시 잘못된
키워드 post가 전달되어 발생했다.
필드를 읽기전용으로 설정하거나 create() 메서드를 사용하여 해결할 수 있다.
해당 오류는 CommentSerializer
를 통해 save()
메서드를 호출할 때 발생하는 오류로 save()
메서드는 내부적으로 Comment.objects.create()
를 호출하여 새로운 인스턴스를 생성한다. 이과정에서 validated_data
에 포함된 post
키워드가 잘못된 인수로 전달되어 오류가 발생한 것이다.
create 메서드를 사용하여 post, user, user_nickname 필드를 직접 설정하여 준다.
Serializers.py
class CommentSerializer(serializers.ModelSerializer):
class Meta:
model = Comment
fields = '__all__'
read_only_fields = ['post_id', 'user_id', 'user_nickname']
def create(self, validated_data):
request = self.context.get('request')
post = validated_data.pop('post')
user = request.user
comment = Comment.objects.create(
post_id=post,
user_id=user,
user_nickname=user.nickname
)
return comment
Views.py
def post(self, request, post_id):
post = self.get_object(post_id)
serializer = CommentSerializer(data=request.data, context={'request': request})
if serializer.is_valid(raise_exception=True):
serializer.save(post=post_id)
return Response(serializer.data, status=200)
위의 방법으로 로직을 수정하면
Cannot assign "6": "Comment.post_id" must be a "Post" instance.
오류가 나온다.
이는 Comment 모델의 post_id 필드에 Post 인스턴스가 아닌 post_id값을 전달하려고 해서 발생한 오류이다.
post_id 대신 post를 전달해줘야 한다.
Serializers.py
class CommentSerializer(serializers.ModelSerializer):
class Meta:
model = Comment
fields = '__all__'
read_only_fields = ['post_id', 'user_id', 'user_nickname']
def create(self, validated_data):
request = self.context.get('request')
post = self.context.get('post')
user = request.user
comment = Comment(
post_id=post,
user_id=user,
user_nickname=user.nickname,
**validated_data
)
comment.save()
return comment
post_id대신 post인스턴스를 직접 할당하도록 수정한다.
이는 Comment 모델의 post_id 필드에 Post 인스턴스가 아닌 post_id값을 전달하려고 해서 발생한 오류로
post_id 대신 post를 전달해야 한다.
create 메서드에서 post를 직접 할당하여 Comment 객체를 생성한다.
post 인스턴스를 사용하여 올바른 외래키 관계를 설정한다.
Views.py
def post(self, request, post_id):
post = self.get_object(post_id)
serializer = CommentSerializer(data=request.data, context={'request': request, 'post': post})
if serializer.is_valid(raise_exception=True):
serializer.save()
return Response(serializer.data, status=200)
context로 post 인스턴스를 CommentSerializer에 전달하여 create 메서드에 접근할 수 있게 한다.
CommentSerializer에서 create() 메서드를 정의하여 post와 관련된 데이터는 Post 모델의 인스턴스를 직접 할당하도록 수정
view에서 post 인스턴스를 serializer에 context로 전달해 create() 메서드가 올바른 값으로 댓글을 생성할 수 있게 함