我有一个模型场景:
class Scenario(models.Model):
stakeholder = models.ForeignKey(User, related_name='scenarios', blank=True,)
tasks = models.ManyToManyField(Task, blank=True)
任务对象已经创建,从我的前端我创建了一个场景,只需添加一些现有的任务。
串行:
class ScenarioSerializer(serializers.ModelSerializer):
tasks = TaskSerializer(many=True, required=False)
class Meta:
model = Scenario
fields = '__all__'
def create(self, validated_data):
tasks = validated_data.pop('tasks')
scenario = Scenario.objects.create(**validated_data)
for task in tasks:
Task.objects.update(scenario=scenario, **task)
return scenario
如果没有create()方法,则会抛出错误:
AssertionError: The `.create()` method does not support writable nested fields by default.
Write an explicit `.create()` method for serializer `scenarios.serializers.ScenarioSerializer`, or set `read_only=True` on nested serializer fields.
当我添加此方法时,错误消失了,但它扔了:
FieldError: Cannot update model field <ManyToManyRel: scenarios.scenario> (only non-relations and foreign keys permitted)
我做错了什么?我不想创建新任务,只需创建一个新方案并将现有任务附加到它。
更新:任务模型:
class Task(models.Model):
stakeholder = models.ForeignKey(User, related_name='tasks', blank=True, )
project = models.ForeignKey(Project, related_name='project_tasks' )
title = models.CharField(max_length=50, blank=True, null = True, )
OFTEN_CHOICES = (
('DS', 'Daily several times'),
('DO', 'Daily once'),
('WO', 'Weekly once'),
('MO', 'Monthly once'),
('YO', 'Yearly once'),
)
how_often = models.CharField(blank=True, null = True, choices=OFTEN_CHOICES, max_length=2, )
IMPORTANCE_CHOICES = (
('EI', 'Extremely important'),
('RI', 'Rather important'),
('LI', 'Less important'),
)
how_important_task = models.CharField(blank=True, null = True, choices=IMPORTANCE_CHOICES, max_length=2, )
role = models.CharField(max_length=20, blank=True, null = True, )
why_perform_task = models.CharField(max_length=150, blank=True, null = True, )
why_important_task = models.CharField(max_length=150, blank=True, null = True, )
sequence_of_actions = models.CharField(max_length=500, blank=True, null = True, )
tools_used = models.CharField(max_length=150, blank=True, null = True, )
special_training_required = models.NullBooleanField(blank=True, null = True, default=False, )
what_training_required = models.CharField(max_length=150, blank=True, null = True, )
what_can_go_wrong = models.CharField(max_length=150, blank=True, null = True, )
effects_of_task = models.CharField(max_length=150, blank=True, null = True, )
special_vocabulary_used = models.CharField(max_length=150, blank=True, null = True, )
people_involved = models.CharField(max_length=150, blank=True, null = True, )
any_improvements = models.CharField(max_length=150, blank=True, null = True, )
how_important_improvement = models.CharField(blank=True, null = True, choices=IMPORTANCE_CHOICES, max_length=2, )
benefits_of_improvement = models.CharField(max_length=150, blank=True, null = True, )
样本请求数据:
{"tasks":[{"id":7,"title":"Seven","how_often":"","how_important_task":"","role":"","why_perform_task":"","why_important_task":null,"sequence_of_actions":"","tools_used":"","special_training_required":null,"what_training_required":"","what_can_go_wrong":"","effects_of_task":"","special_vocabulary_used":"","people_involved":"","any_improvements":"","how_important_improvement":"","benefits_of_improvement":"","stakeholder":2,"project":1}]}
答案 0 :(得分:2)
您完成了第一部分,现在需要在docs添加方法update
:
例如
class ScenarioSerializer(serializers.ModelSerializer):
tasks = TaskSerializer(many=True, required=False)
class Meta:
model = Scenario
fields = '__all__'
def create(self, validated_data):
tasks = validated_data.pop('tasks', [])
instance = Scenario.objects.create(**validated_data)
for task_data in tasks:
task = Task.objects.get(pk=task_data.get('id'))
instance.tasks.add(task)
return instance
def update(self, instance, validated_data):
tasks = validated_data.pop('tasks', [])
instance = super().update(instance, alidated_data)
for task_data in tasks:
task = Task.objects.get(pk=task_data.get('id'))
instance.tasks.add(task)
return instance
答案 1 :(得分:0)
按照这篇文章 https://lynxbee.com/solved-the-create-method-does-not-support-writable-nested-fields-by-default/ 中的步骤解决了这个问题。
pip install drf_writable_nested
from drf_writable_nested import WritableNestedModelSerializer
class YourSerializer(WritableNestedModelSerializer, serializers.ModelSerializer):
pass