当前位置: 首页 > 面试题库 >

默认情况下,.create()方法不支持可写的嵌套字段。

武晨
2023-03-14
问题内容

关于在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, *args, **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, *args, **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, blank = True, 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)

提前致谢。


问题答案:

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



 类似资料:
  • 默认情况下,我们的路由器是Yaf_Router, 而默认使用的路由协议是Yaf_Route_Static,是基于HTTP路由的, 它期望一个请求是HTTP请求并且请求对象是使用Yaf_Request_Http

  • 在MySQL Ver 14.14 Distrib 5.7.25上,对于Linux(x86_64),默认设置似乎不起作用,因为我试图一行,其中包含父表键中不存在的值,而成功了。 为什么我必须,即使在默认情况下设置了? ...我将中,得到了这个... 因此,为了弄清楚为什么不应该成功,但却成功了,我阅读了以下网页... null 外键必须为。是。 默认存储引擎必须为。是的。 对每个外键声明使用。是。

  • 问题内容: 众所周知,根据JLS7 p.4.12.5, 每个实例变量均使用默认值初始化。例如(1): 但是我一直认为,这样的类实现(2): 绝对等于示例(1)。我期望,复杂的Java编译器会看到(2)中的所有这些初始化值都是多余的,并忽略了它们。 但是突然对于这两个类,我们有两个不同的字节码。 例如(1): 例如(2): 问题是: 为什么?但这是显而易见的要优化的事情。什么原因? UPD: 我使用

  • 我正在尝试通过PingFederate Idp进行身份验证。我正在使用asp。net mvc4,它通过身份和访问工具提供wsfed。看来我很好地恢复了saml断言。Idp确实要求SP上存在并确认证书。我从Idp获得了证书,并将其安装在受信任的根目录中。我在网上用这句话。将其配置为在受信任的根中查找。 这是我从asp.net得到的确切错误: 在此上下文中不支持加密算法http://www.w3.or

  • 问题内容: 是否可以为类型选择性地启用elasticsearch字段的索引? 通过特定索引的映射设置,可以设置属性 {“ index”:“ not_analyzed”} 对于特定领域。由于我的文档中的字段太多,并且将来可能会更改结构,因此我需要一个映射,除非另行指定,否则默认情况下不会分析字段。 这可能吗? 问题答案: 是的- 看一下动态模板 请尝试以下操作: 动态模板适用于您的映射未涵盖的新字段

  • 所以基本上我有一个学校的项目,它包含一个time循环中的开关语句。 假设我输入“1”,它在大小写“1”中运行代码。然后它应该在之后中断。但默认代码也总是运行。 这是案例“1”代码: 这是默认代码: 以下是输出: 我很有信心我的代码是正确的,但是如果我缺少什么,请告诉我如何修复它,谢谢。