django REST 中带有 many2many 的可读嵌套序列化程序
Readable nested serializer with many2many in django REST
我是 运行 一个使用 REST 将数据发送到我的 API 的 django 应用程序。
我有一个包含许多项目的网络,一个项目可以属于多个网络。
我想通过请求发送这个数据集:
payload = {
"name": "my great testnetwork",
"type_network": "xyz",
"projects" : [
{
"project_name": "Brasil",
},
{
"project_name": "Sweden",
},
],
"creation_date": "2020-05-15T15:57:27.399455Z"
}
我不想创建 project_names,它们已经在数据库中了。我只希望它像普通 FK 一样工作,我在其中指定 project_name,它显示在我的 API 中。它应该只涉及它们。
现在的情况是,当我这样发送时,项目列表仍然是空的
这是我得到的:
{
"id": 6,
"name": "my great test",
"type_network": "xyz",
"projects": [],
"creation_date": "2020-05-15T19:00:05.947542Z"
}
但是我需要列表中的项目。
我的序列化程序如下所示:
class NetworkSerializer(serializers.ModelSerializer):
"""Serializer for Network.
Add extra field buildings from NestedProjectSerializer.
"""
projects = NestedProjectSerializer(
many=True,
read_only=True,
help_text="Many to many relation. Project instances expected."
)
class Meta:
model = Network
fields = (
'id',
'name',
'projects',
'creation_date',
)
好的,所以我尝试覆盖可写嵌套序列化器的创建方法,但我想我不需要这个,对吧?因为我不想创建新对象。然后我也尝试使用 PrimaryKeyRelatedField
,但我得到的错误是 pk is not valid
(传递查询集时)或者它不显示项目(使用只读=True 时)。
我有点卡在这里。有人可以帮我吗?非常感谢您的时间和帮助。非常感谢!
如果需要,我很乐意提供更多代码或说明。
我的模特:
class Project(models.Model):
project_name = models.CharField(max_length=120, primary_key=True, unique=True)
location = models.CharField(max_length=120, null=True, blank=True)
class Network(models.Model):
name = models.CharField(
max_length=120,
null=True,
blank=True,
help_text="Name of network. String expected."
)
projects = models.ManyToManyField(
Project,
default=None,
blank=True,
help_text="Many to many relation. Project instances expected."
)
creation_date = models.DateTimeField(
auto_now=True
)
我觉得我必须覆盖创建方法... project_name 是 pk 顺便说一句。
编辑:像这样发送数据:
payload = {
"name": "my great testnetwork",
# "projects" : [
# {
# "project_name": "frankfurt",
# }
# ],
"projects_data" : [
{
"project_name": "Brasil",
}
],
"creation_date": "2020-05-15T15:57:27.399455Z"
}
r = requests.request('post', 'http://localhost:8000/myendpoint', json=payload, headers=headers)
print(r.text)
print(r.status_code)
您需要将代码更新为如下:
from rest_framework import serializers
class NetworkSerializer(serializers.ModelSerializer):
"""Serializer for Network.
Add extra field buildings from NestedProjectSerializer.
"""
projects_data = serializers.SerializerMethodField()
class Meta:
model = Network
fields = (
'id',
'name',
'projects',
'projects_data',
'creation_date',
)
def get_projects_data(self, obj):
projects = obj.projects.all()
return NestedProjectSerializer(projects, many=True).data
希望对您有所帮助..!!
如果你定义一个嵌套的序列化器,你将在创建记录时总是卡住。由于创建方法需要来自项目序列化程序的序列化数据
参考:https://www.django-rest-framework.org/api-guide/fields/#serializermethodfield
编辑:
新序列化器
from rest_framework import serializers
class NetworkSerializer(serializers.ModelSerializer):
"""Serializer for Network.
Add extra field buildings from NestedProjectSerializer.
"""
projects = NestedProjectSerializer(many=True, required=False)
class Meta:
model = Network
fields = (
'id',
'name',
'projects',
'projects_data',
'creation_date',
)
def create(self, validated_data):
projects = validated_data.pop("projects")
network_obj = Network.objects.create(**validated_data)
for project in projects:
network_obj.projects.add(Project.objects.create(**project))
network_obj.save()
return network_obj
我已经根据您的要求重写了创建方法
我是 运行 一个使用 REST 将数据发送到我的 API 的 django 应用程序。
我有一个包含许多项目的网络,一个项目可以属于多个网络。
我想通过请求发送这个数据集:
payload = {
"name": "my great testnetwork",
"type_network": "xyz",
"projects" : [
{
"project_name": "Brasil",
},
{
"project_name": "Sweden",
},
],
"creation_date": "2020-05-15T15:57:27.399455Z"
}
我不想创建 project_names,它们已经在数据库中了。我只希望它像普通 FK 一样工作,我在其中指定 project_name,它显示在我的 API 中。它应该只涉及它们。
现在的情况是,当我这样发送时,项目列表仍然是空的
这是我得到的:
{
"id": 6,
"name": "my great test",
"type_network": "xyz",
"projects": [],
"creation_date": "2020-05-15T19:00:05.947542Z"
}
但是我需要列表中的项目。
我的序列化程序如下所示:
class NetworkSerializer(serializers.ModelSerializer):
"""Serializer for Network.
Add extra field buildings from NestedProjectSerializer.
"""
projects = NestedProjectSerializer(
many=True,
read_only=True,
help_text="Many to many relation. Project instances expected."
)
class Meta:
model = Network
fields = (
'id',
'name',
'projects',
'creation_date',
)
好的,所以我尝试覆盖可写嵌套序列化器的创建方法,但我想我不需要这个,对吧?因为我不想创建新对象。然后我也尝试使用 PrimaryKeyRelatedField
,但我得到的错误是 pk is not valid
(传递查询集时)或者它不显示项目(使用只读=True 时)。
我有点卡在这里。有人可以帮我吗?非常感谢您的时间和帮助。非常感谢!
如果需要,我很乐意提供更多代码或说明。
我的模特:
class Project(models.Model):
project_name = models.CharField(max_length=120, primary_key=True, unique=True)
location = models.CharField(max_length=120, null=True, blank=True)
class Network(models.Model):
name = models.CharField(
max_length=120,
null=True,
blank=True,
help_text="Name of network. String expected."
)
projects = models.ManyToManyField(
Project,
default=None,
blank=True,
help_text="Many to many relation. Project instances expected."
)
creation_date = models.DateTimeField(
auto_now=True
)
我觉得我必须覆盖创建方法... project_name 是 pk 顺便说一句。
编辑:像这样发送数据:
payload = {
"name": "my great testnetwork",
# "projects" : [
# {
# "project_name": "frankfurt",
# }
# ],
"projects_data" : [
{
"project_name": "Brasil",
}
],
"creation_date": "2020-05-15T15:57:27.399455Z"
}
r = requests.request('post', 'http://localhost:8000/myendpoint', json=payload, headers=headers)
print(r.text)
print(r.status_code)
您需要将代码更新为如下:
from rest_framework import serializers
class NetworkSerializer(serializers.ModelSerializer):
"""Serializer for Network.
Add extra field buildings from NestedProjectSerializer.
"""
projects_data = serializers.SerializerMethodField()
class Meta:
model = Network
fields = (
'id',
'name',
'projects',
'projects_data',
'creation_date',
)
def get_projects_data(self, obj):
projects = obj.projects.all()
return NestedProjectSerializer(projects, many=True).data
希望对您有所帮助..!!
如果你定义一个嵌套的序列化器,你将在创建记录时总是卡住。由于创建方法需要来自项目序列化程序的序列化数据
参考:https://www.django-rest-framework.org/api-guide/fields/#serializermethodfield
编辑: 新序列化器
from rest_framework import serializers
class NetworkSerializer(serializers.ModelSerializer):
"""Serializer for Network.
Add extra field buildings from NestedProjectSerializer.
"""
projects = NestedProjectSerializer(many=True, required=False)
class Meta:
model = Network
fields = (
'id',
'name',
'projects',
'projects_data',
'creation_date',
)
def create(self, validated_data):
projects = validated_data.pop("projects")
network_obj = Network.objects.create(**validated_data)
for project in projects:
network_obj.projects.add(Project.objects.create(**project))
network_obj.save()
return network_obj
我已经根据您的要求重写了创建方法