Put Request Django Rest Framework 时出现类型错误
Type error while Put Request Django Rest Framework
我正在构建一个 Django 应用程序,其中有一个名为 Location 的模型和另一个名为 属性 的模型。每当我尝试发出放置请求时,它都会显示类型错误 TypeError: Object of type Location is not JSON serializable
我的位置模型
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)
序列化器
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']
观看次数
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)
保存 属性 后,当我使用 PUT 请求更新它显示的信息时
TypeError: Object of type Location is not JSON serializable
我在数据库中保存了几个位置。
首先我用它发出了一个 post 请求,它给了我 STATUS 201 CREATED
{
'name': 'foo',
'bedrooms':4,
'bathrooms':3,
'living_rooms':5,
'location':4,
}
然后我在上面做一个放置请求
{
'name': 'foo bar',
'bedrooms':1,
'bathrooms':2,
'living_rooms':2,
'location':1,
}
它给了我 TypeError: Object of type Location is not JSON serializable
在您的 PropertySerializer
中,您需要向“位置”属性添加 PrimaryKeyRelatedField
或 LocationSerializer
:
class PropertySerializer(serializers.ModelSerializer):
location = PrimaryKeyRelatedField()
class Meta:
model = Property
fields = ['id','name','bedrooms','bathrooms','living_rooms','location']
read_only_fields = ['id']
或:
class PropertySerializer(serializers.ModelSerializer):
location = LocationSerializer()
class Meta:
model = Property
fields = ['id','name','bedrooms','bathrooms','living_rooms','location']
read_only_fields = ['id']
我相信在 RenterCreate 视图中也有一种方法可以做到这一点,但如果其中任何一个首先起作用,请告诉我。
在您的 PUT 方法 (put(self, request)
) 中,您使用 request.user 作为 PropertySerializer 的对象而不是 属性 对象。您可以查看 the serializer documentation for saving an object.
您可以按照 this wonderful DRF tutorial 设置您的 APIView 并 urls.py 设置 get/put/post 方法。
然后您可以毫无问题地创建、更新和获取对象。
您的代码存在不少问题。 GET 和 POST 请求在列表端点上正常工作,但 PUT 请求应该在详细信息端点上工作。这意味着端点应使您能够指定要编辑的特定 Property
对象,但目前还不能。与此相结合,您没有将要编辑的 Property
实例传递给序列化程序,而是传递了 request.user
.
通常,如果您使用的是低级 APIView,则需要为列表端点和详细端点创建单独的视图。如果你想使用一个视图,那么你应该利用结合了列表和详细视图的更高级别的视图集。而且它们非常容易实现,因为大部分样板代码已经为您实现了。对于您的情况,像这样的简单视图集就足够了。
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()
然后像这样在 urls.py 中注册它:
from rest_framework.routers import SimpleRouter
router = SimpleRouter()
router.register(r'properties', PropertyViewSet, basename='properties')
urlpatterns = router.get_urls()
它已经自动实现了 get、post、put 和 delete,并包含两个端点:api/properties
称为列表端点和 api/properties/<id>/
- 称为详细信息端点。
因此,要编辑 属性,即 ID 为 2 的 属性,您应该将 PUT 请求发送到 api/properties/2/
。
您还可以阅读更多关于 DRF viewsets
我在这件事上找到了问题并解决了
Serializer 和 Models 相同,但我更改了视图。
class PropertyView(viewsets.ModelViewSet):
# Adding Authentication classes Token Authentication
# Permission class > Will allow only post request if user is not authenticated
authentication_classes = [TokenAuthentication]
# Permissions only allow renters and authenticated users
permission_classes = [IsAuthenticated, RenterPermission]
# Gives JSON Rendered Class
renderer_classes = [JSONRenderer]
# Serializer Class for this Class View
serializer_class = PropertySerializer
# Query set of all renter objects
queryset = Renter_Property_Pref.objects.all()
@action(methods=['get'], detail=True)
def retrieve(self, request, pk=None):
renter = get_object_or_404(self.queryset, user=request.user)
serializer = self.get_serializer(renter, many=False)
return Response(serializer.data, status=status.HTTP_200_OK)
@action(methods=['post'], detail=True)
def create(self, request):
# giving serializer the data from request data
serializer = self.get_serializer(data=request.data)
# checks if serializer is valid
if serializer.is_valid():
# saves user information and saves it
serializer.save(user=self.request.user)
return Response(serializer.data, status=status.HTTP_201_CREATED)
# Otherwise it will return errors and a bad request
return Response(serializer.error_messages, status=status.HTTP_400_BAD_REQUEST)
@action(methods=['put'], detail=True)
def update(self, request):
# Propery Serializer and instance object
instance = Property.objects.get(owner=request.user)
serializer = self.get_serializer(instance=instance, data=request.data)
# If serializer is valid it will save
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
# Otherwise it will show error
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)**
我正在构建一个 Django 应用程序,其中有一个名为 Location 的模型和另一个名为 属性 的模型。每当我尝试发出放置请求时,它都会显示类型错误 TypeError: Object of type Location is not JSON serializable
我的位置模型
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)
序列化器
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']
观看次数
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)
保存 属性 后,当我使用 PUT 请求更新它显示的信息时
TypeError: Object of type Location is not JSON serializable
我在数据库中保存了几个位置。
首先我用它发出了一个 post 请求,它给了我 STATUS 201 CREATED
{
'name': 'foo',
'bedrooms':4,
'bathrooms':3,
'living_rooms':5,
'location':4,
}
然后我在上面做一个放置请求
{
'name': 'foo bar',
'bedrooms':1,
'bathrooms':2,
'living_rooms':2,
'location':1,
}
它给了我 TypeError: Object of type Location is not JSON serializable
在您的 PropertySerializer
中,您需要向“位置”属性添加 PrimaryKeyRelatedField
或 LocationSerializer
:
class PropertySerializer(serializers.ModelSerializer):
location = PrimaryKeyRelatedField()
class Meta:
model = Property
fields = ['id','name','bedrooms','bathrooms','living_rooms','location']
read_only_fields = ['id']
或:
class PropertySerializer(serializers.ModelSerializer):
location = LocationSerializer()
class Meta:
model = Property
fields = ['id','name','bedrooms','bathrooms','living_rooms','location']
read_only_fields = ['id']
我相信在 RenterCreate 视图中也有一种方法可以做到这一点,但如果其中任何一个首先起作用,请告诉我。
在您的 PUT 方法 (put(self, request)
) 中,您使用 request.user 作为 PropertySerializer 的对象而不是 属性 对象。您可以查看 the serializer documentation for saving an object.
您可以按照 this wonderful DRF tutorial 设置您的 APIView 并 urls.py 设置 get/put/post 方法。
然后您可以毫无问题地创建、更新和获取对象。
您的代码存在不少问题。 GET 和 POST 请求在列表端点上正常工作,但 PUT 请求应该在详细信息端点上工作。这意味着端点应使您能够指定要编辑的特定 Property
对象,但目前还不能。与此相结合,您没有将要编辑的 Property
实例传递给序列化程序,而是传递了 request.user
.
通常,如果您使用的是低级 APIView,则需要为列表端点和详细端点创建单独的视图。如果你想使用一个视图,那么你应该利用结合了列表和详细视图的更高级别的视图集。而且它们非常容易实现,因为大部分样板代码已经为您实现了。对于您的情况,像这样的简单视图集就足够了。
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()
然后像这样在 urls.py 中注册它:
from rest_framework.routers import SimpleRouter
router = SimpleRouter()
router.register(r'properties', PropertyViewSet, basename='properties')
urlpatterns = router.get_urls()
它已经自动实现了 get、post、put 和 delete,并包含两个端点:api/properties
称为列表端点和 api/properties/<id>/
- 称为详细信息端点。
因此,要编辑 属性,即 ID 为 2 的 属性,您应该将 PUT 请求发送到 api/properties/2/
。
您还可以阅读更多关于 DRF viewsets
我在这件事上找到了问题并解决了 Serializer 和 Models 相同,但我更改了视图。
class PropertyView(viewsets.ModelViewSet):
# Adding Authentication classes Token Authentication
# Permission class > Will allow only post request if user is not authenticated
authentication_classes = [TokenAuthentication]
# Permissions only allow renters and authenticated users
permission_classes = [IsAuthenticated, RenterPermission]
# Gives JSON Rendered Class
renderer_classes = [JSONRenderer]
# Serializer Class for this Class View
serializer_class = PropertySerializer
# Query set of all renter objects
queryset = Renter_Property_Pref.objects.all()
@action(methods=['get'], detail=True)
def retrieve(self, request, pk=None):
renter = get_object_or_404(self.queryset, user=request.user)
serializer = self.get_serializer(renter, many=False)
return Response(serializer.data, status=status.HTTP_200_OK)
@action(methods=['post'], detail=True)
def create(self, request):
# giving serializer the data from request data
serializer = self.get_serializer(data=request.data)
# checks if serializer is valid
if serializer.is_valid():
# saves user information and saves it
serializer.save(user=self.request.user)
return Response(serializer.data, status=status.HTTP_201_CREATED)
# Otherwise it will return errors and a bad request
return Response(serializer.error_messages, status=status.HTTP_400_BAD_REQUEST)
@action(methods=['put'], detail=True)
def update(self, request):
# Propery Serializer and instance object
instance = Property.objects.get(owner=request.user)
serializer = self.get_serializer(instance=instance, data=request.data)
# If serializer is valid it will save
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
# Otherwise it will show error
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)**