Djando REST Framework 序列化返回關聯物件除id之外的欄位
阿新 • • 發佈:2021-01-06
技術標籤:Django rest frameworkserializerrelationsdjangopython
Djando REST Framework 序列化返回關聯物件除id之外的欄位
參考來源(rest framework 官網):api_guide-relations
前言:已經好久沒有用Django了,很多東西已經忘了,所以文章中有存在不足的地方,歡迎指正。
之前用Django做了一個web專案,也不知道是公司伺服器的問題,還是什麼,前端拿資料的速度很慢。600多條資料,竟然最快也需要5秒,我能做的就只有優化程式碼了。。。
看了一下之前寫的code,確實有優化的空間,現在回去看之前寫的程式碼,感覺太low…
之前的做法很low,是拿到owner_id或者owner_id_list 再根據id去查詢owner_name, owner_id_list 還得迴圈, 這樣肯定很影響速度。所以必須改。
model:
class Owner(models. Model):
name = models.CharField(max_length=20, unique=True)
objects = moldes.Manager()
class A(models.Model):
owner = models.ForeignKey('Owner', on_delete=models.CASCADE)
name = models.CharField(max_length=20)
objects = moldes.Manager()
class B(models.Model):
owner = models.MnayToManyField(Owner)
name = models.CharField(max_length=20)
objects = moldes.Manager()
預設的serializer很簡單:
class OwnerSerializer(serialziers.ModelSerializer):
class Mate:
model = Owner
fields = ['id', 'name']
class ASerializer(serialziers.ModelSerializer):
class Mate:
model = A
fields = ['id', 'name', 'owner']
class BSerializer(serialziers.ModelSerializer):
class Mate:
model = B
fields = ['id', 'name', 'owner']
但是這樣返回的資料中owner是以id的形式存在的,我需要返回的資料中有owner_name。
所以我需要改寫serializer。(這裡我既想保留owner_id,又想返回owner_name, 如ASerializer fields中,owner欄位為owner_id,a_owner 為owner_name)
多對多的情況會稍微複雜一點。
重寫serializer:
class OwnerSerializer(serialziers.ModelSerializer):
class Mate:
model = Owner
fields = ['id', 'name']
#一對一的情況
class ASerializer(serialziers.ModelSerializer):
a_owner = serializers.CharField(source='owner.name', read_only=True)
class Mate:
model = A
fields = ['id', 'name', 'owner', 'a_owner']
# 這裡我既保留了owner(返回值為owner_id),又新增了a_owner(返回值為owner_name)
# 如果不想保留owner_id, 直接把owner的返回值由owner_id變成owner_name,可以這樣:
# class ASerializer(serialziers.ModelSerializer):
# owner = serializers.CharField(read_only=True)
# 這裡的owner變數必須要和A model 的owner欄位名一樣,否則會報錯,
#因為rest_framework就是根據這個變數去找對應的欄位。
#如果你的owner名字和A model中的owner欄位名不一樣,就必須在後面加source='owner.name',
#就像上面未註釋的class ASerializer那樣。
# class Mate:
# model = A
# fields = ['id', 'name', 'owner']
#多對多的情況
class BOwnerField(serializer.RelatedField):
def to_representation(self, value):
return value.name
# 按官網說的,這裡可以自定義返回的格式,例如:return f'{value.id}: {value.name}',這將使得b_owner = ['1: wang', '2:zhang']。
class BSerializer(serialziers.ModelSerializer):
b_owner = BOwnerField(many=True, read_only=True, source='owner')
class Mate:
model = Owner
fields = ['id', 'name', 'owner', 'b_owner']