我有3个模型:Workflow,WorkflowLevels,WorkflowLevelPermissions:
models.py:
class Workflow(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4,
editable=False)
name = models.CharField(max_length=32, default=None, null=True)
description = models.CharField(max_length=100, default=None,
null=True)
tenant = models.ForeignKey(Tenant, on_delete=models.CASCADE,
default=None, null=False)
class Meta:
unique_together = ('name', 'tenant')
class WorkflowLevel(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4,
editable=False)
workflow = models.ForeignKey(Workflow, on_delete=models.CASCADE,
related_name='levels', default=None,
null=False)
level = models.IntegerField(default=None, null=False)
operation = models.CharField(max_length=32, default=None,
null=False)
class Meta:
unique_together = ('workflow', 'level')
class WorkflowPermission(models.Model):
short_name = models.CharField(max_length=32, primary_key=True,
default=None, null=False)
class WorkflowLevelPermission(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4,
editable=False)
level = models.ForeignKey(WorkflowLevel, on_delete=models.CASCADE,
default=None, null=False,
related_name='workflow_permissions')
permission = models.ForeignKey(WorkflowPermission,
on_delete=models.CASCADE,
default=None, null=False)
class Meta:
unique_together = ('level', 'permission')
def short_name(self):
return self.permission.short_name
我使用嵌套的序列化器以这种格式显示工作流数据
.json:
[
{
"name": "test",
"description": "Easy",
"levels": [
{
"level": 1,
"operation": "AND",
"workflow_permissions": [
{
"short_name": "admin_approval"
},
{
"short_name": "coordinator_approval"
}
]
},
{
"level": 2,
"operation": "AND",
"workflow_permissions": []
}
]
}
]
序列化器:
class WorkflowPermissionSerializer(serializers.ModelSerializer):
class Meta:
model = WorkflowPermission
fields = '__all__'
class WorkflowLevelPermissionSerializer(serializers.ModelSerializer):
short_name = serializers.SerializerMethodField('short_name')
class Meta:
model = WorkflowLevelPermission
fields = ['short_name']
def short_name(self):
return self.permission.short_name
class WorkflowLevelSerializer(serializers.ModelSerializer):
workflow_permissions = WorkflowLevelPermissionSerializer(many=True)
class Meta:
model = WorkflowLevel
fields = ['level', 'operation', 'workflow_permissions']
class WorkflowSerializer(serializers.ModelSerializer):
levels = WorkflowLevelSerializer(many=True)
class Meta:
model = Workflow
fields = ('name', 'description', 'levels')
我希望能够在Workflow API视图中以相同格式发布数据。现在它显示错误:
.create()
方法默认情况下不支持可写的嵌套字段。
为串行器.create()
编写一个显式的exzaacademy.els.tenantmgmt.serializers.WorkflowSerializer
方法,或在嵌套的串行器字段上设置read_only=True
。
如何编写正确的create()方法?
我将create方法覆盖为:
class WorkflowSerializer(serializers.ModelSerializer):
levels = WorkflowLevelSerializer(many=True)
class Meta:
model = Workflow
fields = ('name', 'description', 'levels', 'tenant')
def create(self, validated_data):
levels = validated_data.pop('levels')
workflow = Workflow.objects.create(**validated_data)
for level in levels:
permissions = level.pop('workflow_permissions')
level=WorkflowLevel.objects.create(
workflow=workflow,
level=level['level'],
operation=level['operation']
)
for permission in permissions:
WorkflowLevelPermission.objects.create(
level=level,
permission=permission
)
return workflow
出现错误:WorkFLowLevelPermission.level必须是一个关卡实例
答案 0 :(得分:2)
您需要做的是在串行器create
中覆盖WorkflowSerializer
函数,如此处所述:https://www.django-rest-framework.org/api-guide/relations/#writable-nested-serializers。请记住,对于POST
create
以及PUT
或PATCH
覆盖update
。在这里,您必须执行手动创建/更新模型的逻辑。您始终可以访问来自validated_data
的接收数据和来自self.initial_data
的原始数据。请按照上述可写嵌套序列化程序指南进行操作。
在这里,我看到您在嵌套序列化程序中还有另一个嵌套序列化程序。因此,实现起来可能会很复杂。
在这种情况下,以下指南可能会非常有用:https://medium.com/profil-software-blog/10-things-you-need-to-know-to-effectively-use-django-rest-framework-7db7728910e0
请参见部分9。在嵌套的序列化程序中处理多个创建/更新/删除
答案 1 :(得分:1)
class WorkflowSerializer(serializers.ModelSerializer):
levels = WorkflowLevelSerializer(many=True)
class Meta:
model = Workflow
fields = ('name', 'description', 'levels', 'tenant')
def create(self, validated_data):
levels = validated_data.pop('levels')
workflow = Workflow.objects.create(**validated_data)
for level in levels:
permissions = level.pop('workflow_permissions')
level_var = WorkflowLevel.objects.create( # Change Here
workflow=workflow,
level=level['level'],
operation=level['operation']
)
for permission in permissions:
WorkflowLevelPermission.objects.create(
level=level_var, # Change Here
permission=permission
)
return workflow
答案 2 :(得分:0)
这对我有用:
class WorkflowSerializer(serializers.ModelSerializer):
levels = WorkflowLevelSerializer(many=True)
class Meta:
model = Workflow
fields = ('name', 'description', 'levels')
def create(self, validated_data):
levels = validated_data.pop('levels')
workflow=Workflow.objects
.create(**validated_data,tenant=self.context['request'].user.tenant)
for index,level in enumerate(levels):
permissions = level.pop('workflow_permissions')
level_var = WorkflowLevel.objects.create(
workflow=workflow,
level=level['level'],
operation=level['operation']
)
print("Initial data",self.initial_data)
for permission in self.initial_data['levels'][index]['workflow_permissions']:
permission_obj = WorkflowPermission.objects
.filter(short_name=permission['short_name']).first()
WorkflowLevelPermission.objects.create(
id=uuid.uuid4().hex,
level=level_var,
permission=permission_obj
)
return workflow