亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

DRF 使用嵌套序列化程序和外鍵創建對象

DRF 使用嵌套序列化程序和外鍵創建對象

慕田峪7331174 2022-12-20 09:49:47
我正在使用 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)所以我遇到的問題是將有效數據傳遞給外鍵的序列化程序。我不想為Type、Region、Country、創建新對象Timezone,只傳遞適當的數據,以便新創建的 Race 對象正確引用現有的外鍵。這是我嘗試過的:1) 沒有read_only=True在外鍵序列化器上設置。這會嘗試創建我不想要的新對象。2)設置read_only=True外鍵序列化器(如上面的代碼)。這有助于不嘗試創建新Type的等對象,而是從序列化程序創建方法中Region刪除相應的字段。validated_data所以我無法在創建時將現有對象添加到 Race 外鍵。3) 使用 PrimaryKeyForeignField 而不是TypeSerializer等RegionSerializer。但是當我RaceSerializer用來檢索比賽數據時,我只有一個pkundertype等region,我真的很想能夠檢索外鍵的所有字段。您能否建議正確的設置會尋找這樣的東西?我覺得它不應該這么難。
查看完整描述

1 回答

?
MMMHUHU

TA貢獻1834條經驗 獲得超8個贊

所以最后我通過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,例如外鍵:ModelSerializerRaceSerializerregion


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

每個字段 ( type, region, country, timezone) 都有自己的to_internal_value方法to_representation,可以按照我需要的方式序列化/反序列化數據。


查看完整回答
反對 回復 2022-12-20
  • 1 回答
  • 0 關注
  • 162 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號