如何在Django rest框架中显示外键数据?

时间:2019-03-02 05:09:02

标签: django api django-models django-rest-framework django-serializer

型号:

class Demo(models.Model):
    name = models.CharField(max_length=255)
    desc = models.TextField()
    user = models.ForeignKey('auth.User', on_delete=models.CASCADE)

序列化器:

class DemoSerializer(serializers.ModelSerializer):
    class Meta:
        model = Demo
        fields = '__all__'

我在前端添加name, desc and assigning to User的表单,所以这里遇到了一个问题。

我正在将数据传递到API {name: "demo", desc: "lorem ipsum", user: 1 } 它正在保存,但是保存后返回相同的响应,但是我希望用户 first_name, last_name, and email 作为返回响应。

因为我有一个显示演示表内容列表的表。但总是只获得User ID而不是用户详细信息。

如果我要增加depth中的Serializer,则会在节省时间方面造成问题,但是在获取记录时间上,我会得到User模型的所有详细信息。像“密码”一样也作为回应,所以这对我来说是一个安全问题。

2 个答案:

答案 0 :(得分:0)

您可以分离创建和检索序列化程序。例如,创建序列化器将是您当前正在使用的序列化器:

class DemoCreateSerializer(serializers.ModelSerializer):
    class Meta:
        model = Demo
        fields = '__all__'

另一方面,检索序列化程序将使用Nested Relationship用其他序列化程序对用户进行序列化。

class DemoRetrieveSerializer(serializers.ModelSerializer):
    user = UserMinimalSerializer # or you could use your UserSerializer, see the last part of the answer
    class Meta:
        model = Demo
        fields = ('id', 'name', 'desc', 'user')
        read_only = ('id', 'name', 'desc', 'user',)

在您看来,您将使用第一个序列化器创建数据,并使用第二个序列化器进行响应。使用APIView的示例:

class DemoView(APIView):
    def post(self, request, format=None):
        create_serializer = DemoCreateSerializer(data=request.data)
        if create_serializer.is_valid():
            instance = create_serializer.save()
            retrive_serializer = DemoRetrieveSerializer(instance)
            return Response(retrive_serializer.data, status=status.HTTP_201_CREATED)
        return Response(create_serializer.errors, status=status.HTTP_400_BAD_REQUEST)

您可能必须自定义DRF提供的视图来实现此目的,即针对Generic views

由于您不想包括用户模型的所有字段,因此您将不得不使用另一个序列化器来编写用户的最小表示形式。

class UserMinimalSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('id', 'first_name', 'last_name', 'email')
        read_only = ('id', 'first_name', 'last_name', 'email',)

希望有帮助。

答案 1 :(得分:0)

您可以使用depth = 1来获取外键对象的所有数据:

class DemoSerializer(serializers.ModelSerializer):
    class Meta:
        model = Demo
        fields = '__all__'
        depth = 1