我需要序列化一个从多到多相关但每个属性类型分组的项目的属性。
模型
from django.db import models
class AtributoTipo(models.Model):
nombre = models.CharField(max_length=40)
slug = models.SlugField(max_length=40, unique=True)
class Atributo(models.Model):
tipo = models.ForeignKey(AtributoTipo, on_delete=models.CASCADE)
nombre = models.CharField(max_length=40)
slug = models.SlugField(max_length=40)
class Articulo(models.Model):
codigo = models.CharField(max_length=18, unique=True, db_index=True)
nombre = models.CharField(max_length=255)
atributos = models.ManyToManyField(Atributo, related_name="articulos")
普通DRF序列化器:
from rest_framework import serializers
class AtributoTipoSerializer(serializers.ModelSerializer):
class Meta:
model = AtributoTipo
fields = ["__all__"]
class AtributoSerializer(serializers.ModelSerializer):
tipo_slug = serializers.ReadOnlyField(source="tipo.slug")
tipo_nombre = serializers.ReadOnlyField(source="tipo.nombre")
class Meta:
model = Atributo
fields = ["__all__"]
class ArticuloSerializer(serializers.ModelSerializer):
atributos = AtributoSerializer(many=True, read_only=True) # the dude
class Meta:
model = Articulo
fields = ["__all__"]
这是没有任何怪异方法的序列化程序的结果:
{
"id": 44906,
"codigo": "DE0058751",
"atributos": [
{
"id": 15107,
"tipo": 76,
"tipo_slug": "talla",
"tipo_nombre": "Talla",
"nombre": "39",
"slug": "39"
},
{
"id": 43454,
"tipo": 76,
"tipo_slug": "talla",
"tipo_nombre": "Talla",
"nombre": "40",
"slug": "40"
},
{
"id": 23234,
"tipo": 15,
"tipo_slug": "color",
"tipo_nombre": "Color",
"nombre": "Rojo",
"slug": "rojo"
},
{
"id": 12408,
"tipo": 15,
"tipo_slug": "color",
"tipo_nombre": "Color",
"nombre": "Verde",
"slug": "verde"
}
]
}
所需结果:
{
"id": 44906,
"codigo": "DE0058751",
"atributos": [
{
"id": 76,
"slug": "talla",
"nombre": "Talla",
"atributos": [
{
"id": 15107,
"tipo": 76,
"nombre": "39",
"slug": "39"
},
{
"id": 12408,
"tipo": 76,
"nombre": "40",
"slug": "40"
}
]
},
{
"id": 15,
"slug": "color",
"nombre": "Color",
"atributos": [
{
"id": 34234,
"tipo": 15,
"nombre": "Rojo",
"slug": "rojo"
},
{
"id": 2323,
"tipo": 15,
"nombre": "Verde",
"slug": "verde"
}
]
}
]
}
问题是您丢失了文章的上下文。 我尝试了itertools groupby,但我认为DRF必须有另一个逻辑。
答案 0 :(得分:1)
您可以重新定义to_representation
中的ListSerializer
,并将ListSerializer
用作ArticuloSerializer
的字段:
class GroupedAttributosSerializer(serializers.ListSerializer):
def to_representation(self, data):
data = super().to_representation(data)
tipo_slug_to_objects = defaultdict(list)
for d in data:
tipo_slug_to_objects[d["tipo_slug"]].append(d)
result = []
for tipo_slug, objects in tipo_slug_to_objects.items():
result.append(
{
"id": objects[0]["tipo"],
"slug": tipo_slug,
"nombre": objects[0]["tipo_nombre"],
"attributos": [
{"id": attribute["id"],
"tipo": attribute["tipo"],
"nombre": attribute["nombre"],
"slug": attribute["slug"]}
for attribute in objects
]
}
)
return result
class ArticuloSerializer(serializers.ModelSerializer):
atributos = GroupedAttributosSerializer(child=AtributoSerializer(), read_only=True, default=[])
class Meta:
model = Articulo
fields = ["__all__"]