我有任务模型:
class Task(models.Model):
name = models.CharField(max_length=200, blank=True)
description = models.TextField(max_length=1000, blank=True)
completed = models.BooleanField(default=False)
date_created = models.DateField(auto_now_add=True)
due_date = models.DateField(null=True, blank=True)
date_modified = models.DateField(auto_now=True)
tasklist = models.ForeignKey(Tasklist, null=True, related_name='tasks', on_delete=models.CASCADE)
tags = models.ManyToManyField(TaskType, related_name='tasks')
类TaskType(换句话说):
class TaskType(models.Model):
name = models.CharField(max_length=200)
我也有TaskSerializer:
class TaskSerializer(serializers.ModelSerializer):
tags = serializers.SlugRelatedField(many=True, slug_field='name', queryset=TaskType.objects.all())
class Meta:
model = Task
fields = '__all__'
read_only_fields = ('date_created', 'date_modified', 'tasklist')
当我创建一个Task时,为了添加一些标签,我需要先在适当的视图中创建它们,但我希望它们能够即时创建。
因此,在编辑任务的情况下,我添加了update
方法:
def update(self, request, *args, **kwargs):
instance = self.get_object()
tag_names = request.data.get('tags', [])
for tag_name in tag_names:
tag, created = TaskType.objects.get_or_create(name=tag_name)
instance.tags.add(tag)
serializer = self.serializer_class(instance=instance, data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data)
它工作正常,但是当我在创建新任务时添加新标签时失败(400错误请求):
{
"tags": [
"Object with name=%new_tag% does not exist."
]
}
我发现在用它创建Task之前创建合适的标记对象是一个很好的方法,所以我添加了perform_create
方法:
def perform_create(self, serializer):
print('debug')
tag_names = self.request.data.get('tags', [])
for tag_name in tag_names:
tag, created = TaskType.objects.get_or_create(name=tag_name)
list_id = self.kwargs.get('list_id', None)
try:
tasklist = Tasklist.objects.get(pk=list_id)
except Tasklist.DoesNotExist:
raise NotFound()
serializer.save(tasklist=tasklist)
它没有帮助我,实际上我不确定是否至少调用perform_create方法,因为我在控制台中看不到打印(' debug')(当我创建一个任务时我看到的现有标签)。 所以问题是如何更改perform_create方法以便能够创建新的任务而无需首先创建Tag。
答案 0 :(得分:1)
首先,您不需要在视图方法中手动add
个标记。序列化器将为您完成。
其次,当您更新模型时,会使用update
方法。当创建时,您需要覆盖create
方法,perform_create
有效,但发生得太晚了:
def create(self, request, *args, **kwargs):
tag_names = request.data.get('tags', [])
for tag_name in tag_names:
TaskType.objects.get_or_create(name=tag_name)
serializer = self.serializer_class(data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data)
第三,创建新标签后,请致电super().*method*
并让框架为您完成工作:
def update(self, request, *args, **kwargs):
tag_names = request.data.get('tags', [])
for tag_name in tag_names:
TaskType.objects.get_or_create(name=tag_name)
return super().update(request, *args, **kwargs)
def create(self, request, *args, **kwargs):
tag_names = request.data.get('tags', [])
for tag_name in tag_names:
TaskType.objects.get_or_create(name=tag_name)
return super().create(request, *args, **kwargs)
如果您计划使用PATCH方法,还需要添加partial_update
方法,因此最好覆盖序列化程序的to_internal_value
方法而不是每种方法:
class TaskSerializer(serializers.ModelSerializer):
tags = serializers.SlugRelatedField(
many=True, slug_field='name', queryset=TaskType.objects.all())
class Meta:
model = Task
fields = '__all__'
read_only_fields = ('date_created', 'date_modified', 'tasklist')
def to_internal_value(self, data):
for tag_name in data.get('tags', []):
TaskType.objects.get_or_create(name=tag_name)
return super().to_internal_value(data)
答案 1 :(得分:0)
尝试像这样编辑你的视图,
def update(self, request, *args, **kwargs):
instance = self.get_object()
tag_names = request.data.get('tags', [])
serializer = self.serializer_class(instance=instance, data=request.data)
if serializer.is_valid(raise_exception=True)
new_object = serializer.save()
if new_object:
for tag_name in tag_names:
tag, created = TaskType.objects.get_or_create(name=tag_name)
new_object.tags.add(tag)
return Response(serializer.data)