使用 django rest 框架,如何为现有父对象添加新的嵌套子对象
Posted
技术标签:
【中文标题】使用 django rest 框架,如何为现有父对象添加新的嵌套子对象【英文标题】:Using django rest framework, how to add new nested child object for existing parent object 【发布时间】:2019-06-08 06:10:43 【问题描述】:我正在尝试为时间序列数据构建数据存储,为此我创建了嵌套对象 Coin 和 Data,其中 Coin 是父对象并包含每个数据条目都是单独对象的数据条目。目前,我的代码在 CoinSerializer 中构建创建函数时创建了嵌套对象 Coin[Data],但我无法使用正确的方法在现有 Coin 对象中添加/创建子对象
在我的 python 虚拟环境中,我一直在使用 django 2.1.4 drf 3.9 和 python 3.6.. 也作为我项目的后端数据库引擎,我得到了 mongodb 并使用 djongo 1.2 来维护它
对于我的问题的任何建议的想法或方法将不胜感激,因为这是我的第一篇文章,对任何不恰当的风格表示抱歉..
models.py
class Coin(models.Model):
coin_name = models.CharField(max_length=100,blank=True)
class Data(models.Model):
coin = models.ForeignKey(Coin, related_name='data', on_delete=models.CASCADE,blank=True)
date = models.DateField(("Date"),blank=True)
open = models.FloatField(null=True, blank=True)
high = models.FloatField(null=True, blank=True)
low = models.FloatField(null=True, blank=True)
close = models.FloatField(null=True, blank=True)
class Meta:
unique_together = ('coin', 'date',)
ordering = ['date']
def __unicode__(self):
return '%d: %d %d %d %d' % (self.date, self.open, self.high,
self.low, self.close)
序列化器.py
class DataSerializer(serializers.ModelSerializer):
class Meta():
model = models.Data
fields = ('coin_id','pk','id','date','open','high','low','close')
类 CoinSerializer(serializers.ModelSerializer): data = DataSerializer(many=True)
class Meta:
model = models.Coin
fields = ('pk','id','coin_name', 'data')
def create(self, validated_data):
data = validated_data.pop('data')
coin = models.Coin.objects.create(**validated_data)
models.Data.objects.create(coin=coin, **data[0])
return coin
我的结果是这样的
"pk": 101,
"id": 101,
"coin_name": "ripple",
"data": [
"coin_id": 101,
"pk": 56,
"id": 56,
"date": "2016-12-25",
"open": 4036.0,
"high": 4101.0,
"low": 3983.0,
"close": 4065.0
]
,
and expect to consist lots of data objects which I will add by the time in existing coin object
"pk": 101,
"id": 101,
"coin_name": "ripple",
"data": [
"coin_id": 101,
"pk": 56,
"id": 56,
"date": "2016-12-25",
"open": 4036.0,
"high": 4101.0,
"low": 3983.0,
"close": 4065.0
"coin_id": 102,
"pk": 57,
"id": 57,
"date": "2016-12-26",
"open": 4065.0,
"high": 4189.0,
"low": 3967.0,
"close": 4075.0
...
...
]
,
【问题讨论】:
您要创建的所有Data
都是data = validated_data.pop('data')
?我看到了models.Data.objects.create(coin=coin, **data[0])
。也许问题是你使用data[0]
。在循环中尝试data
并创建
非常感谢您的关注.. 但我认为循环不会起作用,因为 data[0] 与循环的工作相同,因为数据仅包含一项.. 因为我认为问题可能是我不明白 models.Data.objects.create(coin=coin, **data[0]) 语句的明确含义.. 特别是 coin=coin... 如果我分配 coin,现有的 coin 对象,是否正确.. ??提前谢谢..
coin=coin
表示您将创建 models.Data
,它将具有您创建的 coin
是 FK。我看到了预期的结果,你有 2 个不同的 coin_id 是 "coin_id": 101
和 "coin_id": 102
。这意味着这有 2 coin
在数据库中存在不同。你想创建 2 Data
FK 2 Coin
不同吗?你能在data[0]
pls 中显示数据吗?
data = ['date': '2016-12-25', 'high': 4101.0, 'open': 0.0, 'low': 3983.0, 'close': 4065.0] 数据[0] = 'date': '2016-12-25', 'high': 4101.0, 'open': 0.0, 'low': 3983.0, 'close': 4065.0
是的,你没看错...... coin_id = 102 不正确,它必须是 101.. 抱歉,谢谢..
【参考方案1】:
我就是这样做的。在我的 viewset.ModelViewSet 实现中。在我的例子中。父类包含一个 manyToMany 对象的列表。我在 manyToMany 中发布新对象..> 创建它们.. 然后将 ID 重新插入到发布数据中并调用基类。工作起来很简单..我喜欢它包含在视图中。然而,我对 Django 较新。但这对我有用。
class CaseDeepViewSet(viewsets.ModelViewSet):
permission_classes = (IsAuthenticated,)
queryset = Case.objects.all().order_by('-id')
def get_serializer_class(self):
if self.request.method in ['GET']:
return CaseDeepSerializer
return CaseSerializer
def create(self, request):
print('IM here: ')
print(request.data)
case_interactions = request.data.pop('new_case_interactions')
listCreatedInteractions = []
for interaction in case_interactions:
print("interaction", interaction)
interaction['issara_staff'] = obj = IssaraUser.objects.get(pk=interaction.get('issara_staff'))
listCreatedInteractions.append(CaseInteraction.objects.create(**interaction).id)
request.data['case_interactions'] = listCreatedInteractions
return super().create(request)
【讨论】:
【参考方案2】:你走错路了。相反,您也应该为 Data 创建另一个端点。在那里你可以创建数据并传递父代币的 id。仅当您同时创建硬币和数据时,使用嵌套架构才有意义。在这种情况下,只需使用数据端点在传递硬币的 id 的同时创建数据
编辑:批量创建
只是为了说明如何为多个 Data 对象实现批量创建 - 您需要使用循环来实现它,因为 model.objects.create()
排除单个对象的数据。你可以使用bulk_create,但它有很多注意事项,所以我会使用循环
【讨论】:
@Giosanikidze 检查更新,如果有帮助别忘了点赞 上帝 .. 太容易了.. 谢谢谢谢谢谢.. 我花了一个多星期的时间在盒子里寻找方法.. 所以我使用数据端点做到了.. 问题解决了。 . @GioSanikidze 不客气。再一次,不要忘记投票:) 您确认了我怀疑的正确方法。谢谢。【参考方案3】:尝试使用数组中的多个项目更改您的输入数据,例如:
data = ['date': '2016-12-25', 'high': 4101.0, 'open': 0.0, 'low': 3983.0, 'close': 4065.0, 'date': '2016-12-26', 'high': 4101.0, 'open': 0.0, 'low': 3983.0, 'close': 4065.0]
这个例子在数组data
中多了一项。
并更改此行:
coin = models.Coin.objects.create(**validated_data)
models.Data.objects.create(coin=coin, **data[0])
到
coin = models.Coin.objects.create(**validated_data)
for item_data in data:
models.Data.objects.create(coin=coin, **item_data)
这将创建一些Data
,FK 是Coin
。
【讨论】:
以上是关于使用 django rest 框架,如何为现有父对象添加新的嵌套子对象的主要内容,如果未能解决你的问题,请参考以下文章
Django Rest Framework api如何为所有人添加身份验证权限
Django Rest Framework - 如何为所有 ModelSerializer 字段创建自定义错误消息?
使用 django rest 框架和 django oauth 工具包在单元测试中进行 oAuth 身份验证
Django Rest API,如何为 2 个模型条目创建 post api,并具有与模型关联的外键