使用 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",
我不知道我的端点是如何镜像该结构的,bodies
、titles
和 ids
分组在一起,这些分组嵌套在 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请求的响应部分的数据?