目前,我的 Django 服务器可以返回以下 JSON:
[
{
"id": 1,
"customer": {
"id": 1,
"name": "John Doe"
},
"description1": "...",
"description2": "...",
"description3": "...",
"description4": "..."
},
{
"id": 2,
"customer": {
"id": 1,
"name": "John Doe"
},
"description1": "...",
"description2": "...",
"description3": "...",
"description4": "..."
},
{
"id": 3,
"customer": {
"id": 1,
"name": "John Doe"
},
"description1": "...",
"description2": "...",
"description3": "...",
"description4": "..."
},
{
"id": 4,
"customer": {
"id": 2,
"name": "Jane Doe"
},
"description1": "...",
"description2": "...",
"description3": "...",
"description4": "..."
},
{
"id": 5,
"customer": {
"id": 2,
"name": "Jane Doe"
},
"description1": "...",
"description2": "...",
"description3": "...",
"description4": "..."
}
]
我的模特是:
from django.db import models
class Customer(models.Model):
name = models.CharField(verbose_name="Customer name")
from django.db import models
class PurchaseDescriptions(models.Model):
customer = models.ManyToManyField("customer.Customer", related_name="customer", verbose_name="Customer")
description1 = models.CharField(verbose_name="Description 1")
description2 = models.CharField(verbose_name="Description 2")
description3 = models.CharField(verbose_name="Description 3")
description4 = models.CharField(verbose_name="Description 4")
我的序列化程序是:
from rest_framework import serializers
class CustomerSerializer(serializers.ModelSerializer):
class Meta:
model = Customer
fields = [
"id",
"name",
]
class PurchaseDescriptionsSerializer(serializers.ModelSerializer):
customer = CustomerSerializer()
class Meta:
model = PurchaseDescriptions
fields = [
"id",
"customer",
"description1",
"description2",
"description3",
"description4",
]
我的观点是:
from rest_framework.viewsets import GenericViewSet
from rest_framework import mixins
class ScheduleViewSet(
mixins.ListModelMixin,
GenericViewSet,
):
queryset = PurchaseDescriptions.objects.all()
serializer_class = PurchaseDescriptionsSerializer
我想重写它并根据
customer
做一些组,例如
[
{
"customer": {
"id": 1,
"name": "John Doe"
},
"data": [
{
"id": 1,
"description1": "...",
"description2": "...",
"description3": "...",
"description4": "..."
},
{
"id": 2,
"description1": "...",
"description2": "...",
"description3": "...",
"description4": "..."
},
{
"id": 3,
"description1": "...",
"description2": "...",
"description3": "...",
"description4": "..."
}
]
},
{
"customer": {
"id": 2,
"name": "Jane Doe"
},
"data": [
{
"id": 4,
"description1": "...",
"description2": "...",
"description3": "...",
"description4": "..."
},
{
"id": 5,
"description1": "...",
"description2": "...",
"description3": "...",
"description4": "..."
}
]
}
]
但我不知道如何使用 Django 的视图和序列化程序来实现。我怎样才能得到这样的JSON?请注意,如果可能的话,我想避免在数据库中创建额外的表。
您可以覆盖序列化器to_representation() 以获得自定义 JSON 响应。
试试这个:
class PurchaseDescriptionsSerializer(serializers.ModelSerializer):
customer = CustomerSerializer()
class Meta:
model = PurchaseDescriptions
fields = [
"id",
"customer",
"description1",
"description2",
"description3",
"description4",
]
def to_representation(self, instance):
data = super().to_representation(instance)
customer_id = data["customer"]["id"]
customer_name = data["customer"]["name"]
del data["customer"]
return {
"customer": {
"id": customer_id,
"name": customer_name,
},
"data": [data],
}
# defined model
class Customer(models.Model):
name = models.CharField(verbose_name="Customer name")
class PurchaseDescriptions(models.Model):
customer = models.ManyToManyField("Customer", related_name="customer", verbose_name="Customer")
description1 = models.CharField(verbose_name="Description 1")
description2 = models.CharField(verbose_name="Description 2")
description3 = models.CharField(verbose_name="Description 3")
description4 = models.CharField(verbose_name="Description 4")
# serializers.py
from rest_framework.serializers import ModelSerializer, Serializer
from rest_framework.fields import CharField, SerializerMethodField
from drf_spectacular.utils import extend_schema_field
class PurchaseDescriptionSchema(ModelSerializer):
class Meta:
model = PurchaseDescriptions
exclude = ("customer",)
class PurchaseDescriptionsSchema(Serializer):
customer = SerializerMethodField(method_name="nested_customer")
data = PurchaseDescriptionSchema(many=True)
# i don't like MethodField
# but there is no other way because it's too wierd schema structure
@extend_schema_field(OpenApiTypes.OBJECT)
def nested_customer(self, obj: Customer2) -> Dict[str,Any]:
return {
"id": obj.id,
"name": obj.name
}
# viewSets.py
class ScheduleViewSet(
mixins.ListModelMixin,
GenericViewSet,
):
queryset = Customer.objects.prefetch_related(
Prefetch(lookup="purchasedescriptions_set", to_attr="data", queryset=PurchaseDescriptions.objects.all())
).all()
serializer_class = PurchaseDescriptionsSchema
ViewSetList 的响应
"즐코하세요
\n"++++
如果您想以不使用 MethodField 的方式实现它,您可以在 QuerySet 中使用 Concat 来获取 JSON 格式的客户数据。
Customer.objects.annotate(customer=Concat(Value("{ \"id\": "), id, Value(",\"name\" "), name, Value("}") )).prefetch_related(~~~)
您可以通过这种方式配置查询集并使用
class PurchaseDescriptionsSchema(Serializer):
# set customer = SerializerMethodField(method_name="nested_customer")
customer = JsonField() # DRF SerializerField
data = PurchaseDescriptionSchema(many=True)
如上所示实现序列化程序。
但是,上述案例的查询集太乱了,所以我使用SerializerMethodField。