REST 中的多对多字段和嵌套序列化程序:覆盖嵌套序列化程序不会在 Django 中创建嵌套 object
Many to Many field and Nested Serializer in REST: Overwriting Nested serializer doesn't create nested object in Django
我有两个具有多对多关系的模型,并且
我正在尝试将嵌套数据发送到我的 API。不幸的是,它只返回一个空数组。
这就是我正在尝试的:
我的模特:
class Building(models.Model):
name = models.CharField(max_length=120, null=True, blank=True)
net_leased_area = models.FloatField(null=True, blank=True)
class BuildingGroup(models.Model):
description = models.CharField(max_length=500, null=True, blank=True)
buildings = models.ManyToManyField(Building, default=None, blank=True)
我的通用 API 视图:
class BuildingGroupCreateAPIView(CreateAPIView):
queryset = BuildingGroup.objects.all()
serializer_class = BuildingGroupSerializer
我的序列化程序:
class BuildingGroupSerializer(serializers.ModelSerializer):
buildings = BuildingSerializer(many=True)
class Meta:
model = BuildingGroup
fields = (
'description',
'buildings',
)
def create(self, validated_data):
buildings_data = validated_data.pop('buildings')
building_group = BuildingGroup.objects.create(**validated_data)
for building_data in buildings_data:
Building.objects.create(building_group=building_group, **building_data)
return building_group
当我向它发送数据时 returns 这个:
{"description":"Test Description API","buildings":[]}
在数组中我想要我的字典数组。
当我覆盖创建方法以发送嵌套的 object 时,我正在尝试遵循此处的 REST 文档。 (https://www.django-rest-framework.org/api-guide/relations/#writable-nested-serializers) 我认为我这样做是正确的,但史诗失败了。
我使用这样的自定义方法随请求发送数据:
test_api_local(method="post", data={
"description": "Test Description API",
"buildings": [{'name' : 'Testname'}, .... ],
})
非常感谢任何帮助。非常感谢!!
编辑:当我尝试在 REST 视图上测试它时,它告诉我:
TypeError: 'building_group' is an invalid keyword argument for this function
EDIT2:这是我的观点:
class BuildingGroupCreateAPIView(CreateAPIView):
queryset = BuildingGroup.objects.all()
serializer_class = BuildingGroupSerializer
def create(self, request, *args, **kwargs):
serializer = BuildingGroupSerializer(data=self.request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data)
您必须明确获取或创建 Building
个实例,具体取决于有效负载数据中传递的 ID,然后将它们添加到 BuildingGroup
个实例。
class NestedBuildingSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(required=False)
class Meta:
model = Building
fields = '__all__'
class BuildingGroupSerializer(serializers.ModelSerializer):
buildings = NestedBuildingSerializer(many=True)
class Meta:
model = BuildingGroup
fields = (
'description',
'buildings',
)
def create(self, validated_data):
buildings_data = validated_data.pop('buildings')
building_group = BuildingGroup.objects.create(**validated_data)
buildings = [] # it will contains list of Building model instance
for building_data in buildings_data:
building_id = building_data.pop('id', None)
building, _ = Building.objects.get_or_create(id=building_id,
defaults=building_data)
buildings.append(building)
# add all passed instances of Building model to BuildingGroup instance
building_group.buildings.add(*buildings)
return building_group
class BuildingGroupView(ListAPIView, CreateAPIView):
queryset = BuildingGroup.objects.all()
serializer_class = BuildingGroupSerializer
## Assume you add your views like this in urls.py
urlpatterns = [
.....
path('building-groups', views.BuildingGroupView.as_view(),
name='building-group'),
.....
]
在调用端点 /building-groups
作为 POST 方法时,负载如下:
{
"description": "here description",
"buildings": [
{
"id": 1, # existing building of id 1
"name": "name of building 1",
"net_leased_area": 1800
},
{
# a new building will gets create
"name": "name of building 2",
"net_leased_area": 1800
}
]
}
然后,它会return这样的响应:-
{
"description": "here description",
"buildings": [
{
"id": 1,
"name": "name of building 1",
"net_leased_area": 1800
},
{
"id": 2
"name": "name of building 2",
"net_leased_area": 1800
}
]
}
了解 M2M relationship
并且,.get_or_create()
Note: BuildingSerializer
and NestedBuildingSerializer
are both different. Don't mix them up.
我有两个具有多对多关系的模型,并且 我正在尝试将嵌套数据发送到我的 API。不幸的是,它只返回一个空数组。
这就是我正在尝试的:
我的模特:
class Building(models.Model):
name = models.CharField(max_length=120, null=True, blank=True)
net_leased_area = models.FloatField(null=True, blank=True)
class BuildingGroup(models.Model):
description = models.CharField(max_length=500, null=True, blank=True)
buildings = models.ManyToManyField(Building, default=None, blank=True)
我的通用 API 视图:
class BuildingGroupCreateAPIView(CreateAPIView):
queryset = BuildingGroup.objects.all()
serializer_class = BuildingGroupSerializer
我的序列化程序:
class BuildingGroupSerializer(serializers.ModelSerializer):
buildings = BuildingSerializer(many=True)
class Meta:
model = BuildingGroup
fields = (
'description',
'buildings',
)
def create(self, validated_data):
buildings_data = validated_data.pop('buildings')
building_group = BuildingGroup.objects.create(**validated_data)
for building_data in buildings_data:
Building.objects.create(building_group=building_group, **building_data)
return building_group
当我向它发送数据时 returns 这个:
{"description":"Test Description API","buildings":[]}
在数组中我想要我的字典数组。
当我覆盖创建方法以发送嵌套的 object 时,我正在尝试遵循此处的 REST 文档。 (https://www.django-rest-framework.org/api-guide/relations/#writable-nested-serializers) 我认为我这样做是正确的,但史诗失败了。
我使用这样的自定义方法随请求发送数据:
test_api_local(method="post", data={
"description": "Test Description API",
"buildings": [{'name' : 'Testname'}, .... ],
})
非常感谢任何帮助。非常感谢!!
编辑:当我尝试在 REST 视图上测试它时,它告诉我:
TypeError: 'building_group' is an invalid keyword argument for this function
EDIT2:这是我的观点:
class BuildingGroupCreateAPIView(CreateAPIView):
queryset = BuildingGroup.objects.all()
serializer_class = BuildingGroupSerializer
def create(self, request, *args, **kwargs):
serializer = BuildingGroupSerializer(data=self.request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data)
您必须明确获取或创建 Building
个实例,具体取决于有效负载数据中传递的 ID,然后将它们添加到 BuildingGroup
个实例。
class NestedBuildingSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(required=False)
class Meta:
model = Building
fields = '__all__'
class BuildingGroupSerializer(serializers.ModelSerializer):
buildings = NestedBuildingSerializer(many=True)
class Meta:
model = BuildingGroup
fields = (
'description',
'buildings',
)
def create(self, validated_data):
buildings_data = validated_data.pop('buildings')
building_group = BuildingGroup.objects.create(**validated_data)
buildings = [] # it will contains list of Building model instance
for building_data in buildings_data:
building_id = building_data.pop('id', None)
building, _ = Building.objects.get_or_create(id=building_id,
defaults=building_data)
buildings.append(building)
# add all passed instances of Building model to BuildingGroup instance
building_group.buildings.add(*buildings)
return building_group
class BuildingGroupView(ListAPIView, CreateAPIView):
queryset = BuildingGroup.objects.all()
serializer_class = BuildingGroupSerializer
## Assume you add your views like this in urls.py
urlpatterns = [
.....
path('building-groups', views.BuildingGroupView.as_view(),
name='building-group'),
.....
]
在调用端点 /building-groups
作为 POST 方法时,负载如下:
{
"description": "here description",
"buildings": [
{
"id": 1, # existing building of id 1
"name": "name of building 1",
"net_leased_area": 1800
},
{
# a new building will gets create
"name": "name of building 2",
"net_leased_area": 1800
}
]
}
然后,它会return这样的响应:-
{
"description": "here description",
"buildings": [
{
"id": 1,
"name": "name of building 1",
"net_leased_area": 1800
},
{
"id": 2
"name": "name of building 2",
"net_leased_area": 1800
}
]
}
了解 M2M relationship
并且,.get_or_create()
Note:
BuildingSerializer
andNestedBuildingSerializer
are both different. Don't mix them up.