leedjango
leedjango

Reputation: 411

I don't understand that keyerror occurs in my code in django

I am using the django rest framework modelviewset to re-turn the entire post when I request get. But after writing the code, I sent the get request and the following error appears.

Traceback (most recent call last):
      File "C:\Users\kurak\AppData\Local\Programs\Python\Python38-32\lib\site-packages\django\core\handlers\exception.py", line 34, in inner
        response = get_response(request)
      File "C:\Users\kurak\AppData\Local\Programs\Python\Python38-32\lib\site-packages\django\core\handlers\base.py", line 115, in _get_response
        response = self.process_exception_by_middleware(e, request)
      File "C:\Users\kurak\AppData\Local\Programs\Python\Python38-32\lib\site-packages\django\core\handlers\base.py", line 113, in _get_response
        response = wrapped_callback(request, *callback_args, **callback_kwargs)
      File "C:\Users\kurak\AppData\Local\Programs\Python\Python38-32\lib\site-packages\django\views\decorators\csrf.py", line 54, in wrapped_view
        return view_func(*args, **kwargs)
      File "C:\Users\kurak\AppData\Local\Programs\Python\Python38-32\lib\site-packages\rest_framework\viewsets.py", line 114, in view
        return self.dispatch(request, *args, **kwargs)
      File "C:\Users\kurak\AppData\Local\Programs\Python\Python38-32\lib\site-packages\rest_framework\views.py", line 505, in dispatch
        response = self.handle_exception(exc)
      File "C:\Users\kurak\AppData\Local\Programs\Python\Python38-32\lib\site-packages\rest_framework\views.py", line 465, in handle_exception
        self.raise_uncaught_exception(exc)
      File "C:\Users\kurak\AppData\Local\Programs\Python\Python38-32\lib\site-packages\rest_framework\views.py", line 476, in raise_uncaught_except

ion
    raise exc
  File "C:\Users\kurak\AppData\Local\Programs\Python\Python38-32\lib\site-packages\rest_framework\views.py", line 502, in dispatch
    response = handler(request, *args, **kwargs)
  File "D:\school\대회 및 프로젝트\CoCo\feed\views.py", line 23, in list
    'email': serializer.data['author_email'],
KeyError: 'author_email'

I have clearly stated this in the serializer, but I don't understand why a keyerror appears. Can you tell me what the problem is in my code? Here's my code. Thank in advance.

views.py

class CreateReadPostView (ModelViewSet) :
    serializer_class = PostSerializer
    permission_classes = [IsAuthenticated]
    queryset = Post.objects.all()

    def perform_create (self, serializer) :
        serializer.save(author=self.request.user)

    def list (self, request) :
        serializer = self.serializer_class(data=request.data)
        serializer.is_valid(raise_exception=True)
        
        data = {
            'author': {
                'email': serializer.data['author_email'],
                'username': serializer.data['author_username'],
                'profile': serializer.data['author_profile']
            },
            'title': serializer.data['title'],
            'text': serializer.data['text'],
            'images': serializer.data['image'],
            'view': serializer.data['view'],
            'tag': serializer.data['tag']
        }

        return Response(data, status=200)

serializers.py

class PostSerializer (serializers.ModelSerializer) :
    author_username = serializers.CharField(source='author.username', read_only=True)
    author_email = serializers.CharField(source='author.email', read_only=True)
    author_profile = serializers.ImageField(source='author.profile', read_only=True, use_url=True)
    title = serializers.CharField(allow_null=True)
    text = serializers.CharField(allow_null=True)
    image = ImageSerializer(many=True, read_only=True)

    class Meta:
        model = Post
        fields = [
            'author_username',
            'author_email',
            'author_profile',
            'title', 
            'text', 
            'image', 
            'view'
        ]

Upvotes: 0

Views: 67

Answers (1)

Ken4scholars
Ken4scholars

Reputation: 6296

The problem is how you defined your list method. Please use the default list method in the viewset as a reference to define yours. Specifically, you are initializing the serializer with request.data, when there is no data in the request because it is a GET request. This is only done in the POST/PUT/PATCH requests when you want to serialize the input and create a new object with the data. Instead, you should pass in the queryset that should be serialized for output.There is KeyError because author_email is readonly and you initialized the serializer in write mode so of course, the author-email is not available.

I would advice that you instead keep the inbuilt list method and use a nested representation in the serializers like this:

class AuthorSerializer(serializers.ModelSerializer):
    class Meta:
        model = Author
        fields = ('username', 'email', 'profile')

class PostSerializer (serializers.ModelSerializer) :
    author = AuthorSerializer(read_only=True)
    title = serializers.CharField(allow_null=True)
    text = serializers.CharField(allow_null=True)
    image = ImageSerializer(many=True, read_only=True)

    class Meta:
        model = Post
        fields = [
            'author',
            'title', 
            'text', 
            'image', 
            'view'
        ]
      

Then you can have a simple viewset:

class CreateReadPostView (ModelViewSet) :
    serializer_class = PostSerializer
    permission_classes = [IsAuthenticated]
    queryset = Post.objects.all()

    def perform_create (self, serializer) :
        serializer.save(author=self.request.user)

To understand more about how the list method is implemented, check the ListMixin. It fetches the queryset, applies filters and then paginates them. These are things you ommitted in your code

Upvotes: 1

Related Questions