如何使用 django-rest-framework 保存外键
how to save foreign keys using django-rest-framework
我是 Django 的新手,我正在尝试将 Unit 和 current_user 外键保存在数据库中基于获得的 pk 但是每次我尝试这样做但是 运行 分为两种类型错误 serializers.is_valid()
引发异常错误或序列化程序 returns "Invalid data. Expected a dictionary, but got Unit."
我尝试了一种非常非常丑陋的方法来绕过序列化程序,但我得到了 ee8452a4-2a82-4804-a010-cf2f5a41e006 must be an instance of SavedUnit.unit.I 我也尝试过直接使用保存外键SavedUnit.objects.create()
运气不好
model.py
class SavedUnit(models.Model):
"""
Saving units for later models
relationship with units and users
"""
id = models.UUIDField(primary_key=True, default=hex_uuid, editable=False)
unit = models.ForeignKey(Unit, on_delete=models.CASCADE)
user = models.ForeignKey('accounts.User', on_delete=models.CASCADE, related_name='user')
published_at = models.DateTimeField(auto_now_add=True)
serializers.py
class SavedSerializer(serializers.ModelSerializer):
unit = UnitSerializer()
class Meta:
model = SavedUnit
fields = [
'id',
'unit'
]
views.py
class SavedUnitView(APIView):
"""
Query all the unites saved
"""
@staticmethod
def get_unit(request, pk):
try:
return Unit.objects.get(pk=pk)
except Unit.DoesNotExist:
return Response(status=status.HTTP_400_BAD_REQUEST)
@staticmethod
def post(request, pk):
if request.user.is_authenticated:
unit = get_object_or_404(Unit, id=pk)
serializers = SavedSerializer(data=unit)
if serializers.is_valid(raise_exception=True):
created = SavedUnit.objects.get_or_create(
user=request.user,
unit=unit)
return Response(status=status.HTTP_201_CREATED)
return Response(status=status.HTTP_401_UNAUTHORIZED)
def get(self, request):
units = SavedUnit.objects.filter(user=self.request.user.id)
try:
serializers = SavedSerializer(units, many=True)
return Response(serializers.data, status=status.HTTP_200_OK)
except Unit.DoesNotExist:
return Response(status=status.HTTP_500_INTERNAL_SERVER_ERROR)
其实问题出在这里:
def post(request, pk):
if request.user.is_authenticated:
unit = get_object_or_404(Unit, id=pk)
serializers = SavedSerializer(data=unit) <-- Here
您正在传递一个单元实例,但它应该是 request.data,如下所示:
serializers = SavedSerializer(data=request.data)
( 我不确定你在做什么,如果你已经有了 PK,那你为什么还要使用序列化器?因为你不需要它,因为你已经有了这个单元,你可以从访问当前用户request.user
,你已经在做了。而且我认为你不应该使用 @staticmethod
,你可以这样声明 post 方法:def post(self, request, pk)
并删除静态方法装饰器)
您的代码仅使用序列化程序进行验证,但可以使用它在数据库调用时插入或更新新对象 serializer.save()
。
要使用django-rest-framework 保存外键,您必须在序列化器上放置一个相关字段来处理它。使用 PrimaryKeyRelatedField
。
serializers.py
class SavedSerializer(serializers.ModelSerializer):
unit_id = serializers.PrimaryKeyRelatedField(
source='unit',
queryset=Unit.objects.all()
)
unit = UnitSerializer(read_only=True)
class Meta:
model = SavedUnit
fields = [
'id',
'unit_id',
'unit'
]
views.py
class SavedUnitView(APIView):
permission_classes = (permissions.IsAuthenticated,) # For not handling authorization mannually
def post(request):
serializer = SavedSerializer(data=request.data)
serializer.is_valid(raise_exception=True) # Trigger Bad Request if errors exist
serializer.save(user=request.user) # Passing the current user
return Response(serializer.data, status=status.HTTP_201_CREATED)
现在,单元的id将像这样在请求体中传递
POST /saved-units/
Accept: application/json
Content-Type: application/json
Authorization: Token your-api-token
{
"unit_id": 5 # Id of an existing Unit
}
我是 Django 的新手,我正在尝试将 Unit 和 current_user 外键保存在数据库中基于获得的 pk 但是每次我尝试这样做但是 运行 分为两种类型错误 serializers.is_valid()
引发异常错误或序列化程序 returns "Invalid data. Expected a dictionary, but got Unit."
我尝试了一种非常非常丑陋的方法来绕过序列化程序,但我得到了 ee8452a4-2a82-4804-a010-cf2f5a41e006 must be an instance of SavedUnit.unit.I 我也尝试过直接使用保存外键SavedUnit.objects.create()
运气不好
model.py
class SavedUnit(models.Model):
"""
Saving units for later models
relationship with units and users
"""
id = models.UUIDField(primary_key=True, default=hex_uuid, editable=False)
unit = models.ForeignKey(Unit, on_delete=models.CASCADE)
user = models.ForeignKey('accounts.User', on_delete=models.CASCADE, related_name='user')
published_at = models.DateTimeField(auto_now_add=True)
serializers.py
class SavedSerializer(serializers.ModelSerializer):
unit = UnitSerializer()
class Meta:
model = SavedUnit
fields = [
'id',
'unit'
]
views.py
class SavedUnitView(APIView):
"""
Query all the unites saved
"""
@staticmethod
def get_unit(request, pk):
try:
return Unit.objects.get(pk=pk)
except Unit.DoesNotExist:
return Response(status=status.HTTP_400_BAD_REQUEST)
@staticmethod
def post(request, pk):
if request.user.is_authenticated:
unit = get_object_or_404(Unit, id=pk)
serializers = SavedSerializer(data=unit)
if serializers.is_valid(raise_exception=True):
created = SavedUnit.objects.get_or_create(
user=request.user,
unit=unit)
return Response(status=status.HTTP_201_CREATED)
return Response(status=status.HTTP_401_UNAUTHORIZED)
def get(self, request):
units = SavedUnit.objects.filter(user=self.request.user.id)
try:
serializers = SavedSerializer(units, many=True)
return Response(serializers.data, status=status.HTTP_200_OK)
except Unit.DoesNotExist:
return Response(status=status.HTTP_500_INTERNAL_SERVER_ERROR)
其实问题出在这里:
def post(request, pk):
if request.user.is_authenticated:
unit = get_object_or_404(Unit, id=pk)
serializers = SavedSerializer(data=unit) <-- Here
您正在传递一个单元实例,但它应该是 request.data,如下所示:
serializers = SavedSerializer(data=request.data)
( 我不确定你在做什么,如果你已经有了 PK,那你为什么还要使用序列化器?因为你不需要它,因为你已经有了这个单元,你可以从访问当前用户request.user
,你已经在做了。而且我认为你不应该使用 @staticmethod
,你可以这样声明 post 方法:def post(self, request, pk)
并删除静态方法装饰器)
您的代码仅使用序列化程序进行验证,但可以使用它在数据库调用时插入或更新新对象 serializer.save()
。
要使用django-rest-framework 保存外键,您必须在序列化器上放置一个相关字段来处理它。使用 PrimaryKeyRelatedField
。
serializers.py
class SavedSerializer(serializers.ModelSerializer):
unit_id = serializers.PrimaryKeyRelatedField(
source='unit',
queryset=Unit.objects.all()
)
unit = UnitSerializer(read_only=True)
class Meta:
model = SavedUnit
fields = [
'id',
'unit_id',
'unit'
]
views.py
class SavedUnitView(APIView):
permission_classes = (permissions.IsAuthenticated,) # For not handling authorization mannually
def post(request):
serializer = SavedSerializer(data=request.data)
serializer.is_valid(raise_exception=True) # Trigger Bad Request if errors exist
serializer.save(user=request.user) # Passing the current user
return Response(serializer.data, status=status.HTTP_201_CREATED)
现在,单元的id将像这样在请求体中传递
POST /saved-units/
Accept: application/json
Content-Type: application/json
Authorization: Token your-api-token
{
"unit_id": 5 # Id of an existing Unit
}