【问题标题】:how to save foreign keys using django-rest-framework如何使用 django-rest-framework 保存外键
【发布时间】:2018-12-26 17:27:00
【问题描述】:

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

我尝试了一种非常丑陋的方式来绕过序列化程序,但我得到 ee8452a4-2a82-4804-a010-cf2f5a41e006 必须是 SavedUnit.unit 的一个实例。我还尝试使用 @987654323 直接保存外键@没有运气

模型.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)

序列化器.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)

【问题讨论】:

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


    【解决方案1】:

    您的代码仅使用序列化程序进行验证,但可以使用它在调用serializer.save() 的数据库中插入或更新新对象。

    要使用 django-rest-framework 保存外键,您必须在序列化程序上放置一个相关字段来处理它。使用PrimaryKeyRelatedField

    序列化器.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
    }
    

    【讨论】:

      【解决方案2】:

      其实问题出在这里:

      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,那你为什么还要使用序列化程序?因为你不需要它,因为你已经有了这个单元,你可以从 @987654324 访问当前用户@,你已经在做。而且我认为你不应该使用@staticmethod,你可以像这样声明post方法:def post(self, request, pk)并删除静态方法装饰器)

      【讨论】:

      • request.data 返回一个空对象,因为我认为这是因为我没有发送数据
      • 根据documentationrequest.data包含请求体的解析数据。所以你必须向端点发送数据
      猜你喜欢
      • 2019-07-02
      • 1970-01-01
      • 1970-01-01
      • 2019-02-12
      • 2017-08-15
      • 2016-01-09
      • 2017-06-23
      • 2017-12-05
      • 1970-01-01
      相关资源
      最近更新 更多