如何解决默认情况下,.create方法不支持可写的嵌套字段
DRF不支持create
嵌套序列化器的方法。如果要以扩展布局显示相关字段,而不仅是pks,还可以覆盖该to_representation
方法,而不必重写默认mtm
字段。您还应该重写create
方法,因为mtm
链接中有第三个模型:
class EquipmentSerializer(serializers.ModelSerializer):
class Meta:
model = Equipment
fields = '__all__'
def create(self, validated_data):
order = Order.objects.get(pk=validated_data.pop('event'))
instance = Equipment.objects.create(**validated_data)
Assignment.objects.create(Order=order, Equipment=instance)
return instance
def to_representation(self, instance):
representation = super(EquipmentSerializer, self).to_representation(instance)
representation['assigment'] = AssignmentSerializer(instance.assigment_set.all(), many=True).data
return representation
现在,它将保存正确传递pk列表的mtm字段,例如[1, 2,
3]
和用于表示该mtm相关模型的,EquipmentSerializer
将使用AssignmentSerializer
。
解决方法
关于在DRF中与中间模型进行多对多关系的序列化,我遇到了一个大问题:如果请求方法得到了,那么一切都将正常运行。但是,一旦我尝试将数据发布或放置到API中,就会出现以下错误:
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/core/handlers/base.py",line 149,in get_response
response = self.process_exception_by_middleware(e,request)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/core/handlers/base.py",line 147,in get_response
response = wrapped_callback(request,*callback_args,**callback_kwargs)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/views/decorators/csrf.py",line 58,in wrapped_view
return view_func(*args,**kwargs)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/views/generic/base.py",line 68,in view
return self.dispatch(request,*args,**kwargs)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/djangorestframework-3.5.3-py2.7.egg/rest_framework/views.py",line 477,in dispatch
response = self.handle_exception(exc)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/djangorestframework-3.5.3-py2.7.egg/rest_framework/views.py",line 437,in handle_exception
self.raise_uncaught_exception(exc)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/djangorestframework-3.5.3-py2.7.egg/rest_framework/views.py",line 474,in dispatch
response = handler(request,**kwargs)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/djangorestframework-3.5.3-py2.7.egg/rest_framework/generics.py",line 243,in post
return self.create(request,**kwargs)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/djangorestframework-3.5.3-py2.7.egg/rest_framework/mixins.py",line 21,in create
self.perform_create(serializer)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/djangorestframework-3.5.3-py2.7.egg/rest_framework/mixins.py",line 26,in perform_create
serializer.save()
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/djangorestframework-3.5.3-py2.7.egg/rest_framework/serializers.py",line 214,in save
self.instance = self.create(validated_data)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/djangorestframework-3.5.3-py2.7.egg/rest_framework/serializers.py",line 888,in create
raise_errors_on_nested_writes('create',self,validated_data)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/djangorestframework-3.5.3-py2.7.egg/rest_framework/serializers.py",line 780,in raise_errors_on_nested_writes
class_name=serializer.__class__.__name__
AssertionError: The `.create()` method does not support writable nested fields by default.
Write an explicit `.create()` method for serializer `manager.serializers.EquipmentSerializer`,or set `read_only=True` on nested serializer fields.
我不太确定如何编写适当的创建和更新函数,我也不是很了解它,它在文档中是如何解释的。
码:
views.py:
from django.shortcuts import render
from django.contrib.auth.models import User,Group
from manager.serializers import *
from rest_framework import generics
from rest_framework import viewsets
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework.views import APIView
from django.forms.models import model_to_dict
class OrderSetDetails(generics.RetrieveUpdateDestroyAPIView):
queryset = Order.objects.all()
serializer_class = OrderSerializer
class OrderSetList(generics.ListCreateAPIView):
queryset = Order.objects.all()
serializer_class = OrderSerializer
class EquipmentSetDetails(generics.RetrieveUpdateDestroyAPIView):
queryset = Equipment.objects.all()
serializer_class = EquipmentSerializer
class EquipmentSetList(generics.ListCreateAPIView):
queryset = Equipment.objects.all()
serializer_class = EquipmentSerializer
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all().order_by('-date_joined')
serializer_class = UserSerializer
class GroupViewSet(viewsets.ModelViewSet):
queryset = Group.objects.all()
serializer_class = GroupSerializer
class ClientList(generics.ListCreateAPIView):
queryset = client.objects.all()
serializer_class = ClientSerializer
serializers.py
from rest_framework import serializers
from django.contrib.auth.models import User,Group
from storage.models import *
class AssignmentSerializer(serializers.HyperlinkedModelSerializer):
id = serializers.ReadOnlyField(source = 'Order.id')
name = serializers.ReadOnlyField(source = 'Order.name')
class Meta:
model = Assignment
fields = ('id','name','quantity')
class EquipmentSerializer(serializers.ModelSerializer):
event = AssignmentSerializer(source= 'assignment_set',many = True)
class Meta:
model = Equipment
fields = '__all__'
class ClientSerializer(serializers.ModelSerializer):
class Meta:
model = client
fields = '__all__'
class UserSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = User
fields = ('url','username','email','groups')
class GroupSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Group
fields = ('url','name')
class OrderSerializer(serializers.ModelSerializer):
class Meta:
model = Order
fields = '__all__'
models.py:
from __future__ import unicode_literals
from django.db import models
from storage.choices import *
# Create your models here.
class Equipment(models.Model):
name = models.CharField(max_length=30)
fabricator = models.CharField(max_length=30,default='-')
storeplace = models.IntegerField()
labor = models.CharField(max_length=1,choices=labor_choices)
event = models.ManyToManyField('Order',blank = True,through= 'Assignment',through_fields=('Equipment','Order'))
max_quantity = models.IntegerField(default=1,null = True)
status = models.CharField(max_length=8,choices = STATUS_CHOICES,default = 'im Lager')
def __str__(self):
return self.name
class client(models.Model):
firstname = models.CharField(max_length=30)
secondname = models.CharField(max_length=30)
email = models.EmailField()
post_code = models.IntegerField()
city = models.CharField(max_length=30)
street= models.CharField(max_length=30)
def __str__(self):
return "%s %s" % (self.firstname,self.secondname)
class Order(models.Model):
name = models.CharField(max_length=30)
Type = models.CharField(
max_length=2,choices=TYPE_CHOICES,default='Rental',)
city = models.CharField(max_length=30)
street= models.CharField(max_length=30)
date = models.DateField()
GuestNumber = models.IntegerField()
description = models.TextField()
client = models.ForeignKey("client",on_delete=models.CASCADE,null = True)
status = models.CharField(max_length=30,choices=order_choices,default='glyphicon glyphicon-remove')
def __str__(self):
return self.name
class Assignment(models.Model):
Equipment = models.ForeignKey('Equipment',on_delete=models.CASCADE)
Order = models.ForeignKey('Order',on_delete=models.CASCADE)
quantity = models.PositiveIntegerField(default=1)
提前致谢。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。