'Django KeyError and MultiValueDictKeyError when trying to POST

I am trying to do a POST request to Django through Vue JS, this POST request is a review to a city, When I try to POST through Vue JS I get no response so I tried using the Django API directly and each time I get the same error MultiValueDictKeyError The way I'm trying to POST this request is that each Review is connected to a specific City so I have to attach the city ID to it so I can pass to that City through the API. This is my views.py file:

from django.shortcuts import render

from rest_framework.views import APIView
from rest_framework.response import Response

from .models import City, Review
from .serializers import CitySerializer, ReviewSerializer
from rest_framework.parsers import FormParser, MultiPartParser, JSONParser
from django.http import HttpResponse


class LatestCityList(APIView):
    parser_classes = (FormParser, MultiPartParser)
    def get(self, request, format=None):
        cities = City.objects.all()
        serializer = CitySerializer(cities, many=True)
        return Response(serializer.data)

    def post(self, request, format=None):
        Name = request.data['Name']
        Picture = request.data['Picture']
        Description = request.data['Description']
        slug = Name.lower().replace(' ', '_')
        City.objects.create(Name=Name, Picture=Picture, Description=Description, slug=slug)
        return HttpResponse({'message': 'City created successfully'}, status=201)


class CityDetail(APIView):
    parser_classes = (FormParser, MultiPartParser)
    def get(self, request, slug, format=None):
        city = City.objects.get(slug=slug)
        serializer = CitySerializer(city)
        return Response(serializer.data)


class CityReviewList(APIView):
    parser_classes = (FormParser, MultiPartParser)
    def get(self, request, slug, format=None):
        city = City.objects.get(slug=slug)
        reviews = Review.objects.filter(City=city)
        serializer = ReviewSerializer(reviews, many=True)
        return Response(serializer.data)

    def post(self, request, slug, format=None):
        city = City.objects.get(slug=slug)
        id = City.objects.get(slug=slug).id
        Review = request.data['Review']
        TravelerName = request.data['TravelerName']
        Picture = request.data['Picture']
        slug = TravelerName.lower().replace(' ', '_')
        Review.objects.create(City=city, Review=Review, TravelerName=TravelerName, Picture=Picture, slug=slug)
        return HttpResponse({'message': 'Review created successfully'}, status=201)

You can see that I have POST for LastestCityList and that works perfectly both from the API and from Vue JS I tried applying the same concept for the Review and I couldn't figure it out, I know that the problem is related to City but I tried everything to debug it but still getting an error each time.

This is my serializers.py file:

from rest_framework import serializers

from .models import City, Review

class CitySerializer(serializers.ModelSerializer):
    class Meta:
        model = City
        fields = ('id', 'Name', 'Picture', 'Description',
        'get_absolute_url', 'get_image', 'slug')

class ReviewSerializer(serializers.ModelSerializer):
    class Meta:
        model = Review
        fields = ('id', 'City', 'Review', 'TravelerName', 'slug',
        'Picture', 'get_absolute_url', 'get_image')

Models.py:

from PIL import Image
from django.core.files.uploadedfile import InMemoryUploadedFile
import sys
from django.core.files import File
from django.db import models



class City(models.Model):
    Name = models.CharField(max_length=50, blank=False, null=False)
    Picture = models.ImageField(upload_to='uploads/', blank=False, null=False)
    Description = models.TextField(blank=False, null=False)
    slug = models.SlugField(max_length=50, blank=True, null=True, unique=True)

    class Meta:
        """Meta definition for City."""
        ordering = (['Name'])

    def __str__(self):
        return self.Name

    def get_absolute_url(self):
        """ Returns the url to access a particular instance of the model. """
        return f'/{self.slug}/'

    def get_image(self):
        if self.Picture:
            return 'http://127.0.0.1:12222' + self.Picture.url
        return ''


class Review(models.Model):
    City = models.ForeignKey(City, on_delete=models.CASCADE, related_name='reviews')
    Review = models.TextField(blank=False, null=True)
    TravelerName = models.CharField(max_length=50, blank=True, null=True)
    Picture = models.ImageField(upload_to='uploads/', blank=True, null=True)
    slug = models.SlugField(max_length=50, blank=True, null=True, unique=True)

    class Meta:
        ordering = (['TravelerName'])

    def __str__(self):
        return self.TravelerName

    def get_absolute_url(self):
        return f'/{self.City.slug}{self.slug}/'

    def get_image(self):
        if self.Picture:
            return 'http://127.0.0.1:12222' + self.Picture.url
        return ''

Vue JS Component for the POST data:

<script>
import axios from 'axios';

export default {
    name: 'ReviewPost',
    data() {
        return {
            review: {
              id: null,
              city: '',
              Review: '',
              TravelerName: '',
              Picture: null,
              slug: ''
        },
            myimg: null,
    };
  },
    methods: {
        onFileChange(e) {
            this.myimg = e.target.files[0];
            console.log(this.myimg)},
        uploadImageToServer() {
            let formData = new FormData();
            formData.append('id', null)
            formData.append('Picture', this.myimg, this.myimg.name);
            formData.append('City', this.review.city);
            formData.append('Review', this.review.Review);
            formData.append('TravelerName', this.review.TravelerName);
            formData.append('slug', this.review.slug);
            axios.post('http://127.0.0.1:12222/api/v1/cities/' + this.review.city + '/reviews/', formData)
                .then(res => {
                    console.log(res)
                })
                .catch(err => {
                    console.log(err)
                })
            }
    },
    components: {
    Headers
  },
}
</script>


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source