使用 Django 更改 API POST 请求的 JSON 数据结构

Posted

技术标签:

【中文标题】使用 Django 更改 API POST 请求的 JSON 数据结构【英文标题】:Change structure of JSON data for API POST request with Django 【发布时间】:2020-01-31 04:35:21 【问题描述】:

我有一个具有这种结构的 Django REST API 端点,我需要将其发布到外部 API:


    "body": [
        "...",
        "...",
        "...",
    ],
    "title": [
        "...",
        "...",
        "...",
    ],
    "id": [
        "...",
        "...",
        "...",
    ]

“body”下的第一项与“title”和“id”下的第一项一起使用,依此类推。

我遇到的问题是相关 API 需要具有以下结构的 JSON 数据:


  "texts": [
    
      "body": "...",
      "title": "...",
      "id": "..."
    ,
    
      "body": "...",
      "title": "...",
      "id": "..."
    ,
    
      "body": "...",
      "title": "...",
      "id": "..."
    ,
  ],
  "language": "EN",

我不知道我的端点是如何镜像该结构的,bodiestitlesids 分组在一起,这些分组嵌套在 texts 下,以及 language 参数附在最后。

我在views.py 中使用的序列化程序如下所示:

class MyReasonsSerializer(serializers.Serializer):
    body = serializers.SerializerMethodField()
    title = serializers.SerializerMethodField()
    id = serializers.SerializerMethodField()

    def get_body(self, obj):
        return obj.reasons.order_by('transaction_date').values_list('body', flat=True)

    def get_title(self, obj):
        return obj.reasons.order_by('transaction_date').values_list('title', flat=True)

    def get_id(self, obj):
        return obj.reasons.order_by('transaction_date').values_list('transaction_date', flat=True)

class ReasonsData(RetrieveAPIView):
    queryset = Market.objects.all().prefetch_related('reasons')
    authentication_classes = []
    permission_classes = []
    serializer_class = MyReasonsSerializer

提前感谢您的任何建议!

编辑

以下是模型:

class Market(models.Model):
    title = models.CharField(max_length=50, default="")
    current_price = models.DecimalField(max_digits=5, decimal_places=2, default=0.50)
    description = models.TextField(default="")
    ...
    language = models.CharField(max_length=2, default="EN")

    def __str__(self):
        return self.title[:50]

class Reason(models.Model):
    user_id = models.ForeignKey('users.CustomUser',
        on_delete=models.CASCADE,
        related_name='user_reasons',
        default=None)
    market = models.ForeignKey(
        Market,
        on_delete=models.CASCADE,
        related_name='reasons',
        default=None)
    ...
    valence = models.CharField(max_length=11, default="")
    title = models.TextField(default="")
    body = models.TextField(default="")

    def __str__(self):
        return str(self.title)

【问题讨论】:

你确定你的 Json 响应真的是 REST 吗?把自己放在前端开发的地方。如果你需要使用这个 API,你不觉得迭代 3 次(body、title、id)来填充一些“列表页”会非常困难(而且成本很高)吗? 谢谢,@TâmerPinheiro。您对这里的更好方法有什么建议吗? 【参考方案1】:

我会像这样构建它...(如果没有看到模型并尝试一下,很难确切知道)

class ReasonSerializer(serializers.ModelSerializer):
    class Meta:
        model = Reason
        fields = ("id", "body", "title")

class MarketSerializer(serializers.Serializer):
    texts = ReasonSerializer(many=True, source="reasons")
    language = serializers.CharField()

    class Meta:
        model = Market

class ReasonsData(RetrieveAPIView):
    queryset = Market.objects.all()
    authentication_classes = []
    permission_classes = []
    serializer_class = MarketSerializer

    def get_queryset(self):
        qs = super().get_queryset()

        # filter queryset by valence if passed as a query param
        # ?valence=something
        valence = self.request.query_params.get("valence", None)
        if valence is not None:
            qs = qs.filter(reasons__valence=valence)

        return qs

【讨论】:

谢谢!只需将language 属性添加到Market 模型,EN 作为默认值,然后它就像一个魅力。 快速跟进:Reason 模型有一个valence 属性。有没有一种简单的方法来过滤查询集以仅返回具有特定 valence 值的 Reason 实例?我以为我可以通过使用Market.objects.filter(reasons__valence=value) 来做到这一点,但这似乎不起作用。 PS。我已将模型添加到原始帖子中。 你可以使用像 django-filter 这样的包,但有时它可能会过度杀戮,我添加了一个编辑来展示如何通过覆盖 get_queryset 和按查询参数过滤来过滤查询集。跨度>

以上是关于使用 Django 更改 API POST 请求的 JSON 数据结构的主要内容,如果未能解决你的问题,请参考以下文章

尝试向 API 发送 POST 请求时出现属性错误 - Django

如何在django api调用的react js中使用来自post请求的响应部分的数据?

获取 Django POST 请求的 API

使用 Django 访问没有表单(REST api)的 POST 字段数据

django post请求 403错误解决方法

django post请求 403错误解决方法