gpt4 book ai didi

django - DRF 使用嵌套序列化程序和外键创建对象

转载 作者:行者123 更新时间:2023-12-04 09:45:14 46 4
gpt4 key购买 nike

我正在使用 DRF 并且我正在尝试创建一个对象,该对象具有多个外键以及需要在此过程中创建的相关对象。

这是我的模型的简化版本:

class Race(models.Model):
name = models.CharField(max_length=200)
owner = models.ForeignKey(User, on_delete=models.CASCADE, related_name='races')
type = models.ForeignKey(Type, on_delete=models.SET_NULL, related_name='races', null=True)
region = models.ForeignKey(Region, on_delete=models.CASCADE, verbose_name=_('region'), related_name='races')
country = models.ForeignKey(Country, on_delete=models.CASCADE, related_name='races')
timezone = models.ForeignKey(Timezone, on_delete=models.SET_NULL, null=True)

class Event(models.Model):
name = models.CharField(max_length=200)
race = models.ForeignKey(Race, on_delete=models.CASCADE, related_name='events')

然后这是我的 Race 序列化程序:
class RaceSerializer(serializers.ModelSerializer):
owner = UserSerializer(read_only=True)
type = TypeSerializer(read_only=True)
events = EventSerializer(many=True)
country = CountrySerializer()
region = RegionSerializer(read_only=True)
timezone = TimezoneSerializer(read_only=True)

def create(self, validated_data):
with transaction.atomic():
events = validated_data.pop('events', None)
race = Race(**validated_data)
race.save()
for event in events:
Event.objects.create(race=race, **event)
return race

而我的观点:
class AddRaceView(CreateAPIView):
serializer_class = RaceSerializer
permission_classes = (IsAuthenticated,)

def perform_create(self, serializer):
serializer.save(owner=self.request.user)

这是我随 POST 请求发送的一些测试数据:
{
"name": "ABC Marathon",
"country": {
"pk": 1,
"name": "United States"
},
"region": {
"pk": 1,
"code": "ME"
},
"timezone": {
"pk": 1,
"code": "EST"
},
"events": [
{
"name": "Marathon"
},
{
"name": "Half Marathon"
}
]
}

所以我遇到的问题是将有效数据传递给外键的序列化程序。我不想为 Type 创建新对象, Region , Country , Timezone ,只传递适当的数据,以便新创建的 Race 对象正确引用现有的外键。

这是我尝试过的:

1) 未设置 read_only=True在外键序列化器上。这会尝试创建我不想要的新对象。

2) 设置 read_only=True在外键序列化程序上(如上面的代码)。这有助于不尝试创建新的 Type , Region etc 对象,但从 validated_data 中删除相应的字段在序列化程序创建方法中。所以我无法在创建时将现有对象添加到 Race 外键。

3) 使用 PrimaryKeyForeignField 代替 TypeSerializer , RegionSerializer等等 但是当我使用 RaceSerializer 时要检索比赛数据,我只有一个 pktype , region等等,我真的很想能够检索外键的所有字段。

你能告诉我正确的设置会寻找这样的东西吗?感觉应该没那么难

谢谢!

最佳答案

所以最后我用 RelatedField 解决了这个问题而不是为每个外键单独的序列化程序,除了嵌套的 EventSerializer真正需要编写嵌套 Event对象。

这是RaceSerializer :

class RaceSerializer(serializers.ModelSerializer):
owner = UserSerializer(read_only=True)
type = TypeField()
country = CountryField()
region = RegionField()
timezone = TimezoneField()
events = EventSerializer(many=True)
race_cal_types = serializers.SerializerMethodField()

def create(self, validated_data):
with transaction.atomic():
events = validated_data.pop('events', None)
race = Race(**validated_data)
race.save()
for event in events:
Event.objects.create(race=race, **event)
return race

这是 RelatedField 的组合和 ModelSerializer我用于 RaceSerializer 中的每个字段,例如为 region外键:
class RegionSerializer(serializers.ModelSerializer):

class Meta:
model = Region
fields = ('pk', 'name', 'code')


class RegionField(RelatedField):

def get_queryset(self):
return Region.objects.all()

def to_internal_value(self, data):
return self.get_queryset().get(**data)

def to_representation(self, value):
return RegionSerializer(value).data

每个字段( typeregioncountrytimezone )都有自己的 to_internal_valueto_representation以我需要的方式序列化/反序列化数据的方法。

关于django - DRF 使用嵌套序列化程序和外键创建对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62156484/

46 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com