如何使用django-rest-framework保存外键

时间:2018-12-26 17:27:00

标签: django python-3.x django-rest-framework django-2.1

我是Django的新手,我试图将Unit和current_user外键保存在基于数据库的pk中,但每次尝试这样做时,都会遇到两种错误类型serializers.is_valid()引发异常错误或序列化程序返回"Invalid data. Expected a dictionary, but got Unit."

我尝试通过摆脱绕过序列化程序的方式非常丑陋,但我得到ee8452a4-2a82-4804-a010-cf2f5a41e006必须是SavedUnit.unit的实例。我还尝试过直接使用{{ 1}}没有运气

model.py

SavedUnit.objects.create()

serializers.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)

views.py

class SavedSerializer(serializers.ModelSerializer):
    unit = UnitSerializer()
    class Meta:
        model = SavedUnit
        fields = [
            'id',
            'unit'
        ]

2 个答案:

答案 0 :(得分:0)

实际上问题出在这里:

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,那为什么还要使用序列化器呢?因为您已经拥有单元,所以不需要它,并且您可以从{{ 1}},您已经在这样做了。我认为您不应该使用request.user,可以这样声明post方法:@staticmethod并删除静态方法装饰器)

答案 1 :(得分:0)

您的代码仅将序列化程序用于验证,但是可以使用它在调用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
}