【问题标题】:Change Shape of JSON Serialized Object Django REST Framework改变 JSON 序列化对象的形状 Django REST 框架
【发布时间】:2021-02-04 11:48:19
【问题描述】:

我正在尝试在 Django 中更改序列化 JSON 的结构。目前它看起来像这样:

{
    "id": 1,
    "dates": [
        {
            "date": "2021-02-03",
            "entry_id": 1,
            "indicator": "D"
        },
        {
            "date": "2021-02-04",
            "entry_id": 1,
            "indicator": "D"
        },
        {
            "date": "2021-02-05",
            "entry_id": 1,
            "indicator": "2"
        }
    ],
},
{
    "id": 2,
    "dates": [
        {
            "date": "2021-02-09",
            "entry_id": 2,
            "indicator": "K"
        },
        {
            "date": "2021-01-10",
            "entry_id": 2,
            "indicator": "K"
        },
        {
            "date": "2021-01-11",
            "entry_id": 2,
            "indicator": "K"
        },
        {
            "date": "2021-01-18",
            "entry_id": 2,
            "indicator": "K"
        }
    ]
}

但是,我的目标是做出如下结构的响应:

{
    "id": 1,
    "dates": {
        "20210203": "D",
        "20210204": "D",
        "20210205": "2"
    }
},
{
    "id": 2,
    "dates": {
        "20210209": "K",
        "20210110": "K",
        "20210111": "K",
        "20210118": "K"
        }
}

 

目前我的简化模型+序列化器是这样的:

class Dates(models.Model):
    date: date = models.DateField(verbose_name='Datum')
    indicator: str = models.CharField(max_length=1, null=True, default=None, blank=True, verbose_name='Indikator')
    entry: Entry = models.ForeignKey(Entry, on_delete=models.PROTECT, related_name='bookings')

class Entry(models.Model):
    pass


class EntrySerializer(serializers.ModelSerializer):
    dates = DateSerializer(many=True)

    class Meta:
        model = Entry
        fields = ('id', 'dates',)
        read_only_fields = ('id',)

class DatesSerializer(serializers.ModelSerializer):
    entry_id = serializers.PrimaryKeyRelatedField(queryset=Dates.objects.all(), source='entry.id')

    class Meta:
        #depth = 1
        model = Dates
        fields = (
            'date', 'entry_id', 'indicator'
        )
        read_only_fields = ('date', 'entry_id')

    def create(self, validated_data):
        booking = Dates.objects.create(entry=validated_data['entry']['id'],
                                         indicator=validated_data['indicator'],
                                         data=validated_data['date'])

        return booking

我已尝试将 to_representation 函数添加到 Dates 序列化程序,但是我仍然得到 listdicts 而不是“平面”字典。

    def to_representation(self, data):
        return {data.date.strftime('%Y%m%d'): data.indicator}

它可能与many=True 标志有关,但是我不确定如何在不丢失自动将 json 序列化回对象的功能的情况下删除它。为了使 DRF 与 Datatables Editor 一起工作,需要扁平结构,因为每个日期都需要表中的特定列,由唯一名称标识,在我的情况下为 dates.YYYYmmdd

【问题讨论】:

    标签: python django django-rest-framework datatables


    【解决方案1】:

    您可以将日期序列化器设为方法字段并自己实现序列化:

    class EntrySerializer(serializers.ModelSerializer):
        dates = SerializerMethodField()  # implicitly `get_dates`
    
        def get_dates(self, instance):
             return {
                 date.strftime('%Y%m%d'): indicator
                 for (date, indicator)
                 in instance.dates.all().values_list("date", "indicator")
             }
    

    【讨论】:

    • 这非常有效——我印象非常深刻。这是否也可以将 JSON 反序列化回对象,以便为给定条目更新或创建日期模型?
    • SerializerMethodFields 始终是只读的,因此在这种情况下,您需要在序列化程序上自定义 update() 方法(也许这将被重构为 to_representation()dates 将被标记DictField 或类似名称)。
    • 所以,如果我理解是否正确,有两种处理方法——视图上的自定义 update() 方法或另一个 serializer dates 使用?我不能简单地在现有的序列化程序上使用 get_datesupdate_dates
    • 有很多方法可以处理它... :-) 更新(或创建)方法将在条目序列化程序上;由于有一组日期而不是单个日期,因此您不能将该方法放在 DateSerializer 上。 update/create 方法将使用来自输入 data 的字典并创建或更新附加到(可能是新创建的)Entry 对象的 Date 对象。
    • 快速跟进问题 - 是否也可以将原始 Entry queryset 的值传递给 SerializerMethodField?原因是我在特定时间段内查询Entrystart: dateend: date)并且必须添加空的“填充”日期,如果Entry 在该时间段内没有对应的Dates object。编辑:或者有没有更好的方法来完全解决这个问题?
    猜你喜欢
    • 2015-10-29
    • 2015-02-25
    • 1970-01-01
    • 2021-06-18
    • 2016-11-03
    • 2020-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多