我正在使用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
感谢您的帮助。
答案 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()
如果您想查看所有用户信息