在Django Rest Framework

时间:2017-11-19 23:01:33

标签: django django-rest-framework

我正在使用Django Rest Framework来创建REST Api。我的序列化器:

class ItemSerializer(serializers.ModelSerializer): #inherit from this class
    owner = serializers.ReadOnlyField(source='user.id')

    class Meta:
        model = Item
        fields = ('id','name', 'owner')


class UserSerializer(serializers.ModelSerializer):
    items = serializers.PrimaryKeyRelatedField(many=True, queryset=Item.objects.all())

    class Meta:
        model = User
        fields = ('id', 'username', 'items')

唯一的型号:

class Item(models.Model):
    name = models.CharField(max_length=10)
    id = models.AutoField(primary_key=True)
    owner = models.ForeignKey('auth.User', related_name='items', on_delete=models.CASCADE)

    def __str__(self):
        return self.name

现在,如果我GET用户:

  

HTTP 200 OK   允许:GET,HEAD,OPTIONS   Content-Type:application / json   变化:接受   [       {           “id”:1,           “用户名”:“查克”,           “项目”:[               1,               2           ]       }   ]

我收到了这个用户拥有的所有项目(顺便说一下,我可以获取名称而不是项目的主键吗?)。

如果我想扭转这个过程并获得对象的所有所有者,我该怎么办?以下是我到目前为止的回复(业主不见了):

  

HTTP 200 OK   允许:GET,POST,HEAD,OPTIONS   Content-Type:application / json   变化:接受   [       {           “id”:1,           “名字”:“背心”       },       {           “id”:2,           “名字”:“裤子”       }   ]`

我已尝试添加owners = serializers.ReadOnlyField(source='owner'),因为您可以在代码(注释部分)中看到,但我有以下错误:

Object of type 'User' is not JSON serializable

感谢您的帮助。

2 个答案:

答案 0 :(得分:2)

如果您希望接收该项目的名称而不是主键,则可以将items更改为StringRelatedField,然后使用__str__中的Item

items = serializers.StringRelatedField(many=True)

但更好的解决方案是Nested relationship。您只需将items更改为序列化程序定义项,例如:

items = ItemSerializer(many=True, read_only=True)

另一种解决方案是删除owner并定义深度。这样,所有关于所有者(用户)的信息都将被序列化:

class ItemSerializer(serializers.ModelSerializer):

    class Meta:
        model = Item
        depth = 1
        fields = ('id', 'name', 'owner')

items

class UserSerializer(serializers.ModelSerializer):

    class Meta:
        model = User
        depth = 1
        fields = ('id', 'username', 'items')

现在反过来说,拥有所有者的项目列表,ModelSerializer无法实现。您可能必须手动执行此操作。这是一个示例,您不需要序列化程序。

class ItemOwnerViewSet(viewsets.ViewSet):

    def list(self, request):
        data = []
        queryset = Item.objects.values('name', 'owner__username')
        for item in queryset:
            temp = dict()
            t = next((i for i in data if i['name'] == item['name']), None)
            if t:
                t['owners'].append(item['owner__username'])
            else:
                temp['name'] = item['name']
                temp['owners'] = [item['owner__username']]
                data.append(temp)

        return Response(data)

这个viewset的序列化器可能就是这样的:

class ItemOwnerSerializer(serializers.Serializer):

    name = serializers.CharField()
    owners = serializers.ListField(child=serializers.CharField())

我还没有测试过这一切,但我想它应该可行。我希望它有所帮助。

答案 1 :(得分:1)

你快到了。 在ItemSerializer中,尝试

serializers.ReadOnlyField(source='owner.id')

owner = UserSerializer()

如果您想查看所有用户信息