查询集返回响应自定义

2024-10-01 04:58:40 发布

您现在位置:Python中文网/ 问答频道 /正文

我对Django restframework很陌生,我现在尝试的是用foreignkey返回object。在

class User(models.Model):
    name = models.CharField(max_length=255,blank=True)
    date_created = models.DateTimeField(auto_now_add=True)
    date_modiefied = models.DateTimeField(auto_now=True)
    area = models.CharField(max_length=255,blank=True)
    uuid = models.CharField(max_length=255)
    home = models.CharField(max_length=255,blank=True)
    work = models.CharField(max_length=255,blank=True)
    mobileNo = models.CharField(max_length=255,blank=True)
    email = models.CharField(max_length=255,blank=True)
    appVersionCode = models.CharField(max_length=255,blank=True)
    photoUrl = models.CharField(max_length=255,blank=True)
    serverTime = models.CharField(max_length=255,blank=True)
    fcmTokenId = models.CharField(max_length=255,blank=True)
   def __str__(self):
    return self.name

class LocationData(models.Model):
   user = models.ForeignKey(
     User, related_name='user', on_delete=models.DO_NOTHING)
    source_id = models.CharField(max_length=255)
    latitude = models.CharField(max_length=255)
    longitude = models.CharField(max_length=255)
    speed = models.CharField(max_length=255)
    kms = models.CharField(max_length=255)
    date_created = models.DateTimeField(auto_now=True)
    date_modiefied = models.DateTimeField(auto



class UserSerializer(serializers.ModelSerializer):
  class Meta:
    model = User
    fields = '__all__'

class LocationDataSerializer(serializers.ModelSerializer): 

class Meta:
    model = LocationData
    fields = '__all__'
    depth = 1

我正在使用def get_queryset(self):

^{pr2}$

现在结果在下面的响应中,它立即抛出这个错误

但我希望queryset返回如下一个,因此我可以在android中读取这些密钥对值

{ "collection": {
  "data": {
    "id": 31,
    "source_id": "55",
    "latitude": "24654",
    "longitude": "454654",     
    "date_created": "2019-02-08T17:10:09.318644Z",
    "date_modiefied": "2019-02-08T17:10:09.318714Z",
    "area": "54546",
    "user": {
        "id": 1,
        "name": "Dormy",
        "date_created": "1992-01-18T03:29:53.388000Z",
        "date_modiefied": "2018-02-19T05:17:00.164000Z",
        "serverTime": "",
        "fcmTokenId": ""
      }
  },
    "statusCode": 200,
    "version": "1.0"
 }

现在错误抛出

AttributeError: Got AttributeError when attempting to get a value for field source_id on serializer LocationDataSerializer. The serializer field might be named incorrectly and not match any attribute or key on the int instance. Original exception text was: 'int' object has no attribute 'source_id'.

谢谢!在


Tags: nameidtruesourceautodatemodelslength
3条回答

在这里实现一个自定义渲染器似乎是一种可行的方法。在

您可以让来自android客户端的请求包含在Accept报头中,以向呈现程序标识客户端。1例如

Accept: application/json; android=true

然后使用JSONRenderer类组成一个呈现器,为您的Android客户端提供格式。在

^{pr2}$

然后,当您需要使用APIView属性的renderer_classes来格式化响应时,就可以使用它。2

这个问题有两种可能的解决办法。NDevox已经提到了如何重写retrive函数并获得预期的响应。但是如果我们希望每个api端点的每个响应都这样做,如果我们这样做,我们需要覆盖每个函数,那么它的负担和DRY我们应该尽量避免这种情况。引入中间件或重写Response的一种可能的方法,这样我们就可以在不显式地覆盖每个功能的情况下获得每个api端点的通用响应。在

可能的解决方案一

当我们在这里使用DRF时,我们可以使用各种媒体类型添加我们自己的返回响应,比如针对application/json。在

首先我们需要添加设置.py在

REST_FRAMEWORK = {
    ...
    'DEFAULT_RENDERER_CLASSES': (
        'app_name.renderers.ApiRenderer',  # our own render middleware
    ),
    ...
}

在我们的定制渲染中间件中

^{pr2}$

参考Link

可能的解决方案二

如果我们使用ModelViewset,那么还有另一种方法可以实现这一点。说我们的视图.py就像下面这些

class A(serializer.ModelSerializer):
    ........

class B(serializer.ModelSerializer):
    ........


class C(serializer.ModelSerializer):
    ........

我们的目标是重写ModelViewset的to\u表示函数并返回我们的自定义结果。这将如下所示

from collections import OrderedDict

class OurParentViewset(serializer.ModelSerializer):

    ......
    def to_representation(self, instance):
        data = super(serializers.ModelSerializer, self).to_representation(instance)
        result = OrderedDict()
        result['data'] = data
        result['version'] = '1.0'
        result['statusCode'] = '2xx' # i am not fully sure how to customize this
        return result

    class A(OurParentViewset):
        ........

    class B(OurParentViewset):
        ........


    class C(OurParentViewset):
        ........

答案取决于您使用的是哪种类型的视图,但底线是您不会在get_queryset中执行此操作,而是在reguest类型的方法中执行的。在

例如,如果您使用的是RetrieveAPIView,您应该从RetrieveModelMixin重写retrieve方法,如下所示:

class MyAPIView(RetrieveAPIView):
    queryset = MyModel.objects.all()
    serializer_class = MySerializer

    def retrieve(self, request, *args, **kwargs):
        instance = self.get_object()
        serializer = self.get_serializer(instance)
        data = {
            "collection": {
                "data": serializer.data
            },
            "statusCode": 200,
            "version": "1.0"
        }
        return Response(data)

如果您使用的是其他类似于ListAPIView的东西,那么您需要查看它在相关方法中使用了什么,并重写它来包装数据。在

这里要认识到的主要问题是它与获取queryset无关,它只是从数据库中获取数据。这是关于在发回响应时将数据转换为正确的格式。因此,这项工作应该在作出回应的时候完成。在

相关问题 更多 >