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

Django REST Framework POST嵌套对象

乐城
2023-03-14
问题内容

我现在正面临 Django Rest Framework的 一个小问题。我正在尝试发布一个带有嵌套对象的对象。

这是我的serializers.py

class ClassSerializer(serializers.ModelSerializer):
    class Meta:
        model = Class
        fields = ('number', 'letter')


class SubjectSerializer(serializers.ModelSerializer):
    class Meta:
        model = Subject
        fields = ('title',)


class ExamSerializer(serializers.ModelSerializer):
    subject = SubjectSerializer()
    clazz = ClassSerializer()

    class Meta:
        model = Exam
        fields = ('id', 'subject', 'clazz', 'topic', 'date', 'details')
        depth = 1

    def create(self, validated_data):
        return Exam.objects.create(**validated_data)

    def update(self, instance, validated_data):
        instance.__dict__.update(**validated_data)
        instance.save()

        return instance

create()来自views.py

def create(self, request):
    serializer = self.serializer_class(data=request.data)
    serializer.is_valid(raise_exception=True)
    self.perform_create(serializer)

    return Response(serializer.validated_data, status=status.HTTP_201_CREATED)

这是 邮递员 的回复:
邮递员的回应

我在这里阅读了一些有关此问题的文章,但我仍然坚持下去。我已尝试通过多种方式对其进行修复,但仍在恢复中"This field is required."


问题答案:

您正在处理 嵌套序列化 的问题。在继续之前,请阅读链接的文档。

您的问题涉及DRF中的复杂问题,因此需要进行一些解释和讨论,以了解序列化程序和视图集的工作方式。

我将讨论代表您的问题Subject,并Class通过使用不同的HTTP方法数据的不同表示通过相同的端点数据,因为这通常是当人们希望代表自己的嵌套格式的数据的问题;
他们希望为用户界面提供足够的信息以供清洁使用,例如通过下拉选择器。

默认情况下,Django和Django REST Framework(DRF )通过其 主键
引用相关对象(您SubjectClass)。默认情况下,这些是使用Django自动递增的整数键。如果要通过其他方式引用它们,则必须为此编写重写。有几种不同的选择。
__

  1. 第一种选择是 专门化您的创建和更新逻辑: 通过其他一些属性来引用您的类,并手动编写用于自己创建的查找,或者将要引用的键设置为类的 主键 。您可以将您的类的名称,UUID或任何其他属性设置为主数据库键,只要它是唯一的 单个字段即可 (我之所以这样说是因为您目前正在Class用由复合(数字,字母)搜索词组成的复合搜索。例如,您可以在create视图方法中覆盖相关的对象查找(对于POST),但随后,您也必须在update视图方法中处理类似的查找(对于PUT和PATCH)。
  2. 其次,在我看来,更可取的选择是 专门化对象的表示形式: 通常通过主键引用类,并 创建一个用于读取 对象的 序列化程序 以及 用于创建和更新 对象的 序列化 程序。这可以通过序列化器类的继承和覆盖您的表示来轻松实现。在POST,PUT,PATCH等请求中使用主键来更新您的类引用和外键。

选项1:在创建和更新中使用任意属性查找类和主题:

将嵌套的类序列化器设置为只读:

class ExamSerializer(serializers.ModelSerializer):
    subject = SubjectSerializer(read_only=True)
    clazz = ClassSerializer(read_only=True)

覆盖视图的创建,以在自由格式属性上查找相关类。此外,请检查
DRF如何通过mixins实现此功能
。您还必须重写update方法以正确处理这些问题,并且如果采取以下方法PATCH,除了PUT(更新)之外,还应考虑(部分更新)支持:

def create(self, request):
    # Look up objects by arbitrary attributes.
    # You can check here if your students are participating
    # the classes and have taken the subjects they sign up for.
    subject = get_object_or_404(Subject, title=request.data.get('subject'))
    clazz = get_object_or_404(
        Class, 
        number=request.data.get('clazz_number')
        letter=request.data.get('clazz_letter')
    )

    serializer = self.get_serializer(data=request.data)
    serializer.is_valid(raise_exception=True)
    serializer.save(clazz=clazz, subject=subject)
    headers = self.get_success_headers(serializer.data)

    return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

选项2:专用于序列化器进行读写和使用主键; 这是惯用的方法:

首先定义一个您希望用于常规操作(POST,PUT,PATCH)的默认ModelSerializer:

class ExamSerializer(serializers.ModelSerializer)
    class Meta:
        model = Exam
        fields = ('id', 'subject', 'clazz', 'topic', 'date', 'details')

然后,使用您要提供给它们的表示形式来覆盖必填字段,以读取数据(GET):

class ExamReadSerializer(ExamSerializer):
     subject = SubjectSerializer(read_only=True)
     clazz = ClassSerializer(read_only=True)

然后为ViewSet 指定要用于不同操作的序列化
器。在这里,我们返回嵌套的Subject和Class数据以进行读取操作,但仅将其主键用于更新操作(更简单):

class ExamViewSet(viewsets.ModelViewSet):
     queryset = Exam.objects.all()

     def get_serializer_class(self):
         # Define your HTTP method-to-serializer mapping freely.
         # This also works with CoreAPI and Swagger documentation,
         # which produces clean and readable API documentation,
         # so I have chosen to believe this is the way the
         # Django REST Framework author intended things to work:
         if self.request.method in ['GET']:
             # Since the ReadSerializer does nested lookups
             # in multiple tables, only use it when necessary
             return ExamReadSerializer
         return ExamSerializer

如您所见,选项2似乎不太复杂且不易出错,在DRF(get_serializer_class实现)上仅包含3行手写代码。只需让框架的逻辑为您弄清楚对象的表示形式以及对象的创建和更新。

我看到了许多其他方法,但是到目前为止,这些方法为我生成的代码最少,并且可以以干净的方式利用DRF的设计。



 类似资料:
  • 问题内容: 这是我在elasticsearch中存储在索引上的数据类型。我必须找到包含主要成分牛肉(且重量小于1000)和成分-(辣椒粉且重量小于250),(橄榄油和重量小于300)以及所有其他成分类似的食谱。 索引的映射是 我的查询是 但这给了Null。有人可以帮我吗?我认为我没有正确使用嵌套查询 问题答案: 试试这个:

  • 我将spring boot与thymeleaf结合使用,在页面中尝试显示表单及其嵌套对象。 我的对象工厂有 id 当我显示时 我的工厂有很多机器,但没有一台展出 任何想法?

  • 我有一门java课 在上面的场景中,示例具有子示例,这又是示例列表。此嵌套可以是 n 级。我想实现的是有一个示例列表,即扁平化上面的对象并将所有示例收集到最终列表中(收集所有n级示例)。一个明显的方法是递归。在Java中有什么方法可以更有效地实现它。我尝试了一些java 8概念,但它们不符合要求。

  • 让我们考虑一下这些帖子的集合。每个帖子都有一个评论数组,每个评论都有一个字符串数组,带有键“likes”,表示喜欢该评论的用户。 如何使用mongoose检查用户是否喜欢具有给定ID的评论?

  • 问题内容: 我有这样的角度嵌套对象。有没有办法为嵌套属性过滤它 我只显示父元素,但想按两个元素进行过滤,例如: 问题答案: 是的,如果我正确理解您的示例,则可以。 根据集合的大小,计算迭代所用的集合可能会更好,这样过滤器就不会随着模型的更改而不断地进行操作。 http://jsfiddle.net/suCWn/ 基本上,如果我理解正确,您会执行以下操作:

  • 我有一个带有嵌套字段的JSON: 我正在使用JSONPATH从嵌套中获取。 我已经将我的JSON文本粘贴到了http://jsonpath.com/这个网站上;并且在使用了这一行之后: 我得到了这个: 使用此行后: 我得到了这个: 我尝试返回(输出)的内容如下: 但是我找不到合适的语法来将这两个组合在一行中,并用一个JSONPATH查询返回它们。

  • 有了jOOQ惊人的多集算子,我们能够查询嵌套列表并将其映射到pojo对象。现在,我试图找到一种方法来同时映射单个嵌套对象。例如,我有一个组合的自定义pojo类,如: 我想在一个步骤中查询并获取它。因此,我目前的工作解决方案是: 这包括一个预初始化的字段列表,其目的是以某种方式告诉JOOQ从“教师”映射教师对象。*”列。 我现在想知道在这方面是否有更直观的解决方案。我曾尝试使用row运算符,但到目前