Django 如何正确地将子对象添加到父对象';使用rest框架的s集合
我有以下两个模型:蓝图和工作负载。 Blueprint模型实例应具有与其关联的工作负载集合。 最初,应该允许单独创建蓝图和工作负载实例。 一个完整的典型场景如下: 1) 将创建一个新的Blueprint实例 2) 将创建一个新的工作负载实例 3) 创建的工作负载实例将添加到蓝图的“工作负载”集合中 python REPL版本如下所示:Django 如何正确地将子对象添加到父对象';使用rest框架的s集合,django,django-rest-framework,Django,Django Rest Framework,我有以下两个模型:蓝图和工作负载。 Blueprint模型实例应具有与其关联的工作负载集合。 最初,应该允许单独创建蓝图和工作负载实例。 一个完整的典型场景如下: 1) 将创建一个新的Blueprint实例 2) 将创建一个新的工作负载实例 3) 创建的工作负载实例将添加到蓝图的“工作负载”集合中 python REPL版本如下所示: blueprint = Blueprint(name="bluepint 1") blueprint.save() workload = Workload)nam
blueprint = Blueprint(name="bluepint 1")
blueprint.save()
workload = Workload)name="workload 1")
workload.save()
blueprint.workloads.add(blueprint)
blueprint.save()
在我的python客户机中,我能够独立地创建蓝图和工作负载的实例,并且没有问题
我的问题是:向Blueprint的“workloads”集合添加工作负载的正确HTTP方法和相应的URL语法是什么
以下是models.py:
class Workload(models.Model):
name = models.CharField(max_length=120, blank=True, default='')
description = models.TextField()
image = models.CharField(max_length=120, blank=True, default='')
flavor = models.CharField(max_length=120, blank=True, default='')
blueprint = models.ForeignKey('Blueprint', related_name='workloads', null=True)
class Meta:
ordering = ('name',)
unique_together = ('blueprint', 'name')
def __unicode__(self):
return '%d: %s' % (self.name, self.description)
class Blueprint(models.Model):
name = models.CharField(max_length=120, blank=True, default='')
description = models.TextField()
class Meta:
ordering = ('name',)
下面是serializers.py:
# region Workload Serializer
class WorkloadSerializer(serializers.Serializer):
pk = serializers.IntegerField(read_only=True)
name = serializers.CharField(required=False, allow_blank=True, max_length=120)
description = serializers.CharField(style={'type': 'textarea'})
image = serializers.CharField(required=False, allow_blank=True, max_length=120)
flavor = serializers.CharField(required=False, allow_blank=True, max_length=120)
def create(self, validated_data):
"""
Create and return a new `Snippet` instance, given the validated data.
"""
return Workload.objects.create(**validated_data)
def update(self, instance, validated_data):
"""
Update and return an existing `Snippet` instance, given the validated data.
"""
instance.name = validated_data.get('name', instance.name)
instance.description = validated_data.get('description', instance.description)
instance.image = validated_data.get('image', instance.image)
instance.flavor = validated_data.get('flavor', instance.flavor)
instance.save()
return instance
# endregion
# region Blueprint Serializer
class BlueprintSerializer(serializers.ModelSerializer):
workloads = serializers.StringRelatedField(many=True, required=False)
pk = serializers.IntegerField(read_only=True)
name = serializers.CharField(required=False, allow_blank=True, max_length=120)
description = serializers.CharField(style={'type': 'textarea'})
def create(self, validated_data):
"""
Create and return a new `Snippet` instance, given the validated data.
"""
return Blueprint.objects.create(**validated_data)
def update(self, instance, validated_data):
"""
Update and return an existing `Snippet` instance, given the validated data.
"""
instance.name = validated_data.get('name', instance.name)
instance.description = validated_data.get('description', instance.description)
instance.save()
return instance
class Meta:
model = Blueprint
fields = ('name', 'description', 'workloads')
# endregion
-Eugene我不是REST专家,但就REST而言,我相信您的URL应该是这样的:
GET /api/blueprint/ #list the blueprints
POST /api/blueprint/ #add new blueprint
GET /api/blueprint/1/ #detail information about blueprint with id=1
PUT /api/blueprint/1/ #update blueprint with id=1
GET /api/blueprint/1/workloads/ #list all workloads of blueprint with id 1
POST /api/blueprint/1/workloads/ #add new workload to blueprint with id 1 workloads
GET /api/blueprint/1/workloads/1 #detail information about workload with id=1 and blueprint id = 1
PUT /api/blueprint/1/workloads/1 #update information about workload with id=1 and blueprint id = 1
因此,您在REST
contex中的repl-exmaple将如下所示:
#request
http POST /api/blueprint/ name="bluepint 1"
#response
{
"id": 1,
"name": "bluepint 1",
"description": ""
}
#request
http POST /api/blueprint/1/workloads/ name="workload 1"
#response
{
"id": 1,
"name": "workload 1",
"description": "",
"image": "",
"flavor": "",
"blueprint": 1
}
为了创建这样的url结构,您应该签出或
另一种方法是向/api/blueprint/
添加自定义细节端点,类似于:
http POST /api/blueprint/1/add_workload/ name="workload 2"
如果使用视图集,这将如下所示:
#inside BlueprintViewset
@detail_route(methods=['post'])
def add_workload(self, request, pk):
serializer = WorkloadSerializer(data=request.data)
if serializer.is_valid():
serializer.save(blueprint=pk)
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
谢谢!今晚我要试试这个