【问题标题】:how to override returned serializer object that is returned with the response django rest framework serializer如何覆盖与响应 django rest framework 序列化程序一起返回的返回序列化程序对象
【发布时间】:2019-11-20 13:33:28
【问题描述】:

我有一个 django rest 框架项目。我想在发出 get 请求以显示与数据库结构不相似的特定方式时覆盖返回的 json 对象结构。

我当前的返回对象是这样显示的:

    {
        "id": 9,
        "namespace": "steve",
        "path": "something/another",
        "value": "this is a value",
        "person": 1
    },
    {
        "id": 11,
        "namespace": "namespace1",
        "path": "path2",
        "value": "anyoher value",
        "person": 2
    },
    {
        "id": 12,
        "namespace": "namespace1",
        "path": "path3",
        "value": "this dsiaalks",
        "person": 2
    },
    {
        "id": 13,
        "namespace": "namespace2",
        "path": "path4",
        "value": "asdfasdfasdf",
        "person": 2
    },

我想换个

"person":2 

显示

"user":{
    "userId":testUser
}
  • testUser 是 id 为 2 的用户的用户名 *

这是我目前的 serailzer:

from rest_framework import serializers
from .models import Preference
from django.contrib.auth.models import User


class PreferenceSerializer(serializers.ModelSerializer):
    person = serializers.PrimaryKeyRelatedField(queryset=User.objects.all(),)

    class Meta:
        model = Preference
        fields = ('id', 'namespace', 'path', 'value', 'person')

这是当前的模型:

from django.db import models
from django.contrib.auth.models import User
from owf_framework.people.models import Person

class Preference(models.Model):
    id = models.BigAutoField(primary_key=True, null=False)
    version = models.BigIntegerField(default=1, null=False)
    path = models.CharField(max_length=200, null=False)
    namespace = models.CharField(max_length=200, null=False)
    value = models.TextField(null=False)
    user_id = models.BigIntegerField(null=False, default=1)
    person = models.ForeignKey(User, on_delete=models.CASCADE)

    def __str__(self):
        return self.namespace

    class Meta:
        db_table = 'preference'

字段 person 是用户的外键。

【问题讨论】:

    标签: django django-rest-framework django-views django-serializer


    【解决方案1】:

    希望这会有所帮助:

    serializers.py

    from rest_framework import serializers
    from .models import Preference
    from django.contrib.auth.models import User
    
    
    class PreferenceSerializer(serializers.ModelSerializer):
        person = serializers.PrimaryKeyRelatedField(queryset=User.objects.all(),)
    
        class Meta:
            model = Preference
            fields = ('id', 'namespace', 'path', 'value', 'person')
    
        def to_representation(self, instance):
            ret = super(PreferenceSerializer, self).to_representation(instance)
            # check the request is list view or detail view
            is_list_view = isinstance(self.instance, list)
            if is_list_view:
                person_id = ret.pop('person', None)
                user_obj = User.objects.filter(id=person_id).first()
                user_name = user_obj.username if user_obj else ""
                extra_ret = {
                    "user": {
                        "userId": user_name
                    }
                }
                ret.update(extra_ret)
            return ret
    

    【讨论】:

      【解决方案2】:

      我认为您可以使用模型方法。示例:

      models.py

      from django.db import models
      from django.contrib.auth.models import User
      from owf_framework.people.models import Person
      
      class Preference(models.Model):
          id = models.BigAutoField(primary_key=True, null=False)
          version = models.BigIntegerField(default=1, null=False)
          path = models.CharField(max_length=200, null=False)
          namespace = models.CharField(max_length=200, null=False)
          value = models.TextField(null=False)
          user_id = models.BigIntegerField(null=False, default=1)
          person = models.ForeignKey(User, on_delete=models.CASCADE)
      
          def __str__(self):
              return self.namespace
      
          def get_person(self):
              return self.person.username
      
          class Meta:
              db_table = 'preference'
      

      那么你就是序列化器:

      from rest_framework import serializers
      from .models import Preference
      from django.contrib.auth.models import User
      
      
      class PreferenceSerializer(serializers.ModelSerializer):
          person = serializers.PrimaryKeyRelatedField(queryset=User.objects.all(),)
      
          class Meta:
              model = Preference
              fields = ('id', 'namespace', 'path', 'value', 'person', 'get_person')
      

      【讨论】:

        【解决方案3】:

        我的建议是不要覆盖序列化程序。序列化程序应该只按原样序列化您拥有的数据。在您的情况下,您可以创建一个 ViewSet(不是 ModelViewSet),在 retrieve() 方法中使用过滤器定义您的查询,然后轻松配置您需要的响应。

        【讨论】:

          【解决方案4】:

          我认为这对你有帮助:

          from rest_framework.serializers import ModelSerializer, SerializerMethodField
          
          class PrefrenceSerializer(ModelSerializer):
              user = SerializerMethodField()
          
              class Meta:
                  model = Prefrence
                  exclude = ['person']
          
              def get_user(self, obj):
          
                  return {
                      "userId": obj.person.userId
                  }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-09-27
            • 2014-08-17
            • 2019-05-23
            • 2016-10-22
            • 2019-05-13
            • 2022-12-19
            相关资源
            最近更新 更多