【问题标题】:Can I use ModelSerializer (DRF) to move multiple fields to a JSON field in a CREATE method?我可以使用 ModelSerializer (DRF) 将多个字段移动到 CREATE 方法中的 JSON 字段吗?
【发布时间】:2019-02-13 16:56:44
【问题描述】:

我正在使用 Django Rest 框架构建一个 API。主要要求是它应该允许在调用中灵活地包含额外的字段。基于 POST 调用,我想在 Django 中创建一条新记录,其中一些字段(名称和编号不同)应添加到 JSON 字段(lead_request)。

我怀疑我是否应该使用 ModelSerializer,因为我不知道如何处理应该作为 JSON 合并到一个字段中的各种字段。在 create 方法中,我无法将其他字段合并到 JSON 中,因为它们没有经过验证。

class Leads(models.Model):
    campaign_id = models.ForeignKey(Campaigns, on_delete=models.DO_NOTHING)
    lead_email = models.EmailField(null=True, blank=True)
    lead_request = JSONField(default=dict, null=True, blank=True)

class LeadCreateSerializer(serializers.ModelSerializer):
    def get_lead_request(self):
        return {key: value for key, value in self.request.items() if key.startswith('rq_')}

    class Meta:
        model = Leads
        fields = ['campaign_id',
                  'lead_email',
                  'lead_request']

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

文档主要讨论分配验证数据,但在这里这是不可能的。任何指针都会很有用,因为我不熟悉 DRF。

【问题讨论】:

  • 能否请您在这篇文章中也包含您的模型定义。这样有助于理解模型结构,也有助于人们产生答案。
  • 其余框架已经处理了JSONFields:django-rest-framework.org/api-guide/fields/#jsonfield 的验证/创建,所以如果你的模型上有它并且你正在使用模型序列化器,你应该很高兴 - 通过添加jsonfield_name,然后在您的body 上将 json 传递给它。类似:{ "lead_request": {"key1": "val1", "key2": "val2"} }
  • @Shakil 我已添加模型,感谢您对此进行调查
  • @henriquesalvaro 好点,实际上这在理论上可能是一个解决方案,但不适用于我的用例。该 API 也将被其他程序员使用,这可能是他们在没有大量支持的情况下无法做到的事情。另外,我想允许将链接中的变量作为参数传递,并且很可能不起作用,将 JSON 作为参数传递。感谢您的帮助!
  • 在这种情况下(特别是考虑到您想要接收查询参数),我认为您最好在将数据传递给序列化程序之前对其进行处理。您可以在视图集上操作request.dataquery_params,您甚至可以执行所有这些操作并生成等效的json 形式的lead_request,然后将其传递给您已经存在的序列化程序。

标签: python-3.x django-rest-framework django-views


【解决方案1】:

如果我理解正确并且您也想通过 URL 接收参数,这里有一个示例说明如何实现您想要的:

class LeadViewSet(viewsets.ModelViewSet):

   def create(self, request, *args, **kwargs):
      data = request.data
      lead_request = generate_lead_request(request)
      data['lead_request'] = lead_request
      serializer = self.get_serializer(data=data)
      serializer.is_valid(raise_exception=True)
      ...

generate_lead_request 上,您可以解析可能通过request.data(正文)以及request.query_params 发送的所有附加字段。

【讨论】:

  • 谢谢!看起来这确实是我需要的。仍在测试它,并会尽快回复您。谢谢你帮助我!
  • 设置时效果很好。我也认为在将变量传递给序列化程序之前将它们转换为 json 是很好的。
【解决方案2】:

如果我正确理解问题,这里的主要障碍是我们不知道lead_request 的确切JSON 数据格式。我正在考虑解决这个问题的两种可能的模型。我不确定它们中的任何一个是否合适。只是想分享我的意见。

案例1

假设数据以这种格式传递给LeadCreateSerializer

data = {

    'campaign_id': campaign_id,
    'lead_email': lead_email,
    'lead_request': { 
         # lead_request
     }

}

那么这很容易,普通模型序列化器应该能够做到这一点。如果数据格式不正确,并且可以在传递给序列化程序之前进行组织,那么这些视图或函数应该负责使其格式正确。

案例2

假设在将数据传递到LeadCreateSerializer 之前无法组织数据,那么我们需要在验证或获取lead_request 期间获取我们的相关值。由于这个serializer 的职责是创建新实例并为此验证字段,所以我们假设self.context 中存在整个self.context.request

class LeadCreateSerializer(serializers.ModelSerializer):

    def generate_lead_request(self, data):
         # do your all possible validation and return 
         # in dict format

    def get_lead_request(self):
        request = self.context.request
        lead_request = self.generate_lead_request(request.data)
        return lead_request

    class Meta:
        model = Leads
        fields = ['campaign_id',
                  'lead_email',
                  'lead_request']

【讨论】:

  • 非常感谢,看起来案例 2 确实是我正在寻找的。仍在测试一些东西,看看这是否能解决它,我会在稍后回复你的最终答案!
猜你喜欢
  • 2019-01-01
  • 1970-01-01
  • 2015-04-04
  • 2010-09-21
  • 1970-01-01
  • 2015-08-16
  • 2019-09-09
相关资源
最近更新 更多