覆盖Django(DRF)序列化程序对象GET [英] Override Django (DRF) Serializer object GET

查看:70
本文介绍了覆盖Django(DRF)序列化程序对象GET的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试注入"一些 raw sql 到我的DRF嵌套序列化程序中:

 <代码>#SERIALIZERSCarSerializer类(serializers.ModelSerializer):类Meta:型号=汽车字段='__all__'类DriverSerializer(serializers.ModelSerializer):car = CarSerializer()#< ---在这里,我不想获取Car对象,而是注入一个原始sql.类Meta:型号=驱动程序字段='__all__' 

由于我使用的是MariaDB版本表,因此需要SQL注入来请求数据的特定版本,但这无关紧要.如何覆盖从 CarSerializer 获取对象的方法?谢谢.

解决方案

感谢大家的回答,尽管我的解决方案不像@yvesonline和@iklinak所建议的那样干净,但我设法使它起作用:

我首先查看了有关覆盖序列化程序的官方DRF文档: https://www.django-rest-framework.org/api-guide/serializers/#overriding-serialization-and-deserialization-behavior

我特别对方法的重写感兴趣: .to_representation(self,instance),该方法控制从数据库中获取对象:

从datetime

 导入日期时间为dt从集合中导入OrderedDict从rest_framework.relations导入PKOnlyObject从rest_framework.fields导入SkipField,为空def __init __(self,instance = None,data = empty,asTime = str(dt.now()),** kwargs):self.asTime = asTimeself.instance =实例如果数据不为空:self.initial_data =数据self.partial = kwargs.pop('partial',False)self._context = kwargs.pop('context',{})kwargs.pop('很多',无)super().__ init __(** kwargs)def to_representation(自己,实例):#用我的原始查询替换实例#警告:self.asTime是自定义变量,请检查#上面的__init__方法!实例= Car.objects.raw('''从db_car选择*截至时间戳记%s的system_time其中id =%s;''',[self.asTime,instance.id])[0]ret = OrderedDict()字段= self._read_fields对于字段中的字段:尝试:属性= field.get_attribute(实例)除了SkipField:继续check_for_none = attribute.pk,如果isinstance(属性,PKOnlyObject)else属性如果check_for_none为None:ret [field.field_name] =无别的:ret [field.field_name] = field.to_representation(属性)返回ret 

您可以在此处找到原始代码: class DriverSerializer(serializers.ModelSerializer):汽车= CarSerializer(asTime ='2021-02-05 14:34:00')类Meta:型号=驱动程序字段='__all__'

I'm trying to "inject" some raw sql into my DRF nested Serializer:

# SERIALIZERS

class CarSerializer(serializers.ModelSerializer):

    class Meta:
        model = Car
        fields = '__all__'

class DriverSerializer(serializers.ModelSerializer):
    car = CarSerializer()   # <--- here I don't want to get the Car object but rather inject a raw sql.

    class Meta:
        model = Driver
        fields = '__all__'

The SQL injection is needed to request for a specific version of the data since I'm using MariaDB versioning tables but this is not relevant. How do I override the method that gets the object from CarSerializer? Thank you.

Thank you everyone for your answers, I managed to make it work although my solution is not as clean as the one suggested from @yvesonline and @iklinak:

I first checked the official DRF documentation on overriding serializers: https://www.django-rest-framework.org/api-guide/serializers/#overriding-serialization-and-deserialization-behavior

In particular I was interested in the overriding of the method: .to_representation(self, instance) that controls the fetching of the object from the database:

from datetime import datetime as dt
from collections import OrderedDict
from rest_framework.relations import PKOnlyObject
from rest_framework.fields import SkipField, empty

    def __init__(
            self, instance=None, data=empty, asTime=str(dt.now()), **kwargs):
        self.asTime = asTime
        self.instance = instance
        if data is not empty:
            self.initial_data = data
        self.partial = kwargs.pop('partial', False)
        self._context = kwargs.pop('context', {})
        kwargs.pop('many', None)
        super().__init__(**kwargs)

    def to_representation(self, instance):
        # substitute instance with my raw query
        # WARNING: self.asTime is a custom variable, check the
        # __init__ method above!

        instance = Car.objects.raw(
            '''
                    select * from db_car
                    for system_time as of timestamp %s
                    where id=%s;
                ''', [self.asTime, instance.id])[0]

        ret = OrderedDict()
        fields = self._readable_fields

        for field in fields:
            try:
                attribute = field.get_attribute(instance)
            except SkipField:
                continue

            check_for_none = attribute.pk if isinstance(
                attribute, PKOnlyObject) else attribute
            if check_for_none is None:
                ret[field.field_name] = None
            else:
                ret[field.field_name] = field.to_representation(attribute)

        return ret

You can find the original code here: https://github.com/encode/django-rest-framework/blob/19655edbf782aa1fbdd7f8cd56ff9e0b7786ad3c/rest_framework/serializers.py#L335

Then finally in the DriverSerializer class:

class DriverSerializer(serializers.ModelSerializer):
    car = CarSerializer(asTime='2021-02-05 14:34:00')

    class Meta:
        model = Driver
        fields = '__all__'

这篇关于覆盖Django(DRF)序列化程序对象GET的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆