I am building a Django application where there is a Model called Location and another model called Property. Whenever I try to give put request it shows me type error TypeError: Object of type Location is not JSON serializable
My Location Model
class Location(models.Model):
lat = models.DecimalField(max_digits=10,decimal_places=8)
long = models.DecimalField(max_digits=10,decimal_places=8)
address = models.CharField(max_length=256)
class Property(models.Model):
owner = models.OneToOneField(to=User,on_delete=models.CASCADE)
name = models.CharField(max_length=256)
bedrooms = models.SmallPositiveIntigerField()
bathrooms = models.SmallPositiveIntigerField()
living_rooms = models.SmallPositiveIntigerField()
location = models.ForeignKey(to=Location,null=True,on_delete=models.SETNULL)
Serializer
class PropertySerializer(serializers.ModelSerializer):
class Meta:
model = Property
fields = ['id','name','bedrooms','bathrooms','living_rooms','location']
read_only_fields = ['id']
class LocationSerializer(serializers.ModelSerializer):
class Meta:
model = Location
fields = ['id','long','lat','address']
read_only_fields = ['id']
views
class RenterCreate(APIView):
authentication_classes = [TokenAuthentication]
permission_classes = [IsAuthenticated, RenterPermission]
renderer_classes = [JSONRenderer]
def get(self, request):
property = Property.objects.all()
serializer = RenterSerializer(property , many=True)
return Response(serializer.data, status=status.HTTP_200_OK)
def post(self, request):
serializer = PropertySerializer(data=request.data)
if serializer.is_valid():
serializer.save(user=request.user)
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.error_messages, status=status.HTTP_400_BAD_REQUEST)
def put(self, request):
serializer = PropertySerializer(request.user, data=request.data)
if serializer.is_valid():
serializer.save(user=request.user)
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
After saving a Property when I use PUT request to update the information it shows me
TypeError: Object of type Location is not JSON serializable
I have saved a couple of locations in the database.
First I made a post request with it, it gives me STATUS 201 CREATED
{
'name': 'foo',
'bedrooms':4,
'bathrooms':3,
'living_rooms':5,
'location':4,
}
Then I do a put request on it
{
'name': 'foo bar',
'bedrooms':1,
'bathrooms':2,
'living_rooms':2,
'location':1,
}
It gives me TypeError: Object of type Location is not JSON serializable
There are quite a few issues with your code. The GET and POST requests are correctly working on the list endpoint but the PUT request should work on the detail endpoint. This means that the endpoint should enable you to specify the particular Property
object you want to edit, but currently, it is not. Coupled with this, instead of passing the Property
instance you want to edit to the serializer, you're passing the request.user
.
Usually, if you are using the low-level APIView, then you need to make separate views for the list and detail endpoints. If you want to use one view, then you should exploit the higher level viewsets which combine list and detail views. And they are pretty easy to implement as most of the boilerplate code is already implemented for you. For your case, a simple viewset like this can suffice.
from rest_framework import viewsets
class PropertyViewSet(viewsets.ModelViewSet):
authentication_classes = [TokenAuthentication]
permission_classes = [IsAuthenticated, RenterPermission]
renderer_classes = [JSONRenderer]
serilaizer_class = PropertySerializer
queryset = Property.objects.all()
Then register it in the urls.py like this:
from rest_framework.routers import SimpleRouter
router = SimpleRouter()
router.register(r'properties', PropertyViewSet, basename='properties')
urlpatterns = router.get_urls()
It automatically already has the get, post, put and delete implemented and embodies two endpoints: api/properties
called the list endpoint and api/properties/<id>/
- called the detail endpoint.
So to edit the property of say, the property with id 2, you should send the PUT request to api/properties/2/
.
You can also read more about DRF viewsets