這兩天一直在學習 Django Rest Framework 這個架構,這是一個非常流行的 REST API 架構,深度整合 Django。但與傳統 MVC 模式的不同, Django REST Framework 在使用過程中,需要了解一些新的東西。結合官方 API 分享一下架構中關于序列化關系模型的了解。
序列化模型與序列化關系模型
序列化模型,顧名思義,即對 models 裡的資料模型作序列化。而序列化關系模型則是對 models 裡資料模型中帶有關系的如
ForeignKey
,
ManyToManyField
和
OneToOneField
字段作序列化。Django Rest Framework 提供了靈活的序列化關系模型,讓開發者可以自由定制序列化資料模型。
序列化關系模型
根據官方的例子來看一下每一個關系模型的介紹。
資料模型如下:
class Album(models.Model):
album_name = models.CharField(max_length=100)
artist = models.CharField(max_length=100)
class Track(models.Model):
album = models.ForeignKey(Album, related_name='tracks', on_delete=models.CASCADE)
order = models.IntegerField()
title = models.CharField(max_length=100)
duration = models.IntegerField()
class Meta:
unique_together = ('album', 'order')
ordering = ['order']
def __unicode__(self):
return '%d: %s' % (self.order, self.title)
StringRelatedField
使用
StringRelatedField
将傳回一個對應關系 model 的
__unicode__()
方法的字元串。
這個字段是隻讀的。
參數:
-
如果應用于多對多關系,則應将此參數設定為many
True
序列化模型如下
class AlbumSerializer(serializers.ModelSerializer):
tracks = serializers.StringRelatedField(many=True)
class Meta:
model = Album
fields = ('album_name', 'artist', 'tracks')
序列化結果如下:
{
'album_name': 'Things We Lost In The Fire',
'artist': 'Low',
'tracks': [
'1: Sunflower',
'2: Whitetail',
'3: Dinosaur Act',
...
]
}
PrimaryKeyRelatedField
PrimaryKeyRelatedField
将傳回一個對應關系 model 的主鍵。
-
用于在驗證字段輸入時模型執行個體查找。 關系必須明确設定queryset
,或設定queryset
read_only = True
-
如果是對應多個的關系,就設定為many
True
-
如果設定為allow_null
,則該字段将接受True
的值或為空的關系的空字元串。預設為None
False
-
設定為一個字段以控制主鍵值的序列化/反序列化。例如,pk_field
将UUID主鍵序列化為緊湊的十六進制表示。pk_field = UUIDField(format ='hex')
class AlbumSerializer(serializers.ModelSerializer):
tracks = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
class Meta:
model = Album
fields = ('album_name', 'artist', 'tracks')
{
'album_name': 'Undun',
'artist': 'The Roots',
'tracks': [
89,
90,
91,
...
]
}
HyperlinkedRelatedField
HyperlinkedRelatedField
将傳回一個超連結,該連結指向對應關系 model 的詳細資料,
view-name
是必選參數,為對應的視圖生成超連結。
-
用作關系目标的視圖名稱。如果使用的是标準路由器類,那麼它的格式為view_name
的字元串<modelname>-detail
-
驗證字段輸入時用于模型執行個體查詢的查詢器。關系必須明确設定queryset
queryset
read_only = True
-
many
True
-
allow_null
True
None
False
-
應該用于查找的目标上的字段。應該對應于引用視圖上的lookup_field
關鍵字參數。預設值為URL
pk
-
與查找字段對應的lookup_url_kwarg
中定義的關鍵字參數的名稱。預設使用與URL conf
相同的值lookup_field
-
如果使用format
字尾,超連結字段将對目标使用相同的format
字尾,除非使用format
參數進行覆寫。format
class AlbumSerializer(serializers.ModelSerializer):
tracks = serializers.HyperlinkedRelatedField(
many=True,
read_only=True,
view_name='track-detail'
)
class Meta:
model = Album
fields = ('album_name', 'artist', 'tracks')
{
'album_name': 'Graceland',
'artist': 'Paul Simon',
'tracks': [
'http://www.example.com/api/tracks/45/',
'http://www.example.com/api/tracks/46/',
'http://www.example.com/api/tracks/47/',
...
]
}
SlugRelatedField
SlugRelatedField
将傳回一個指定對應關系 model 中的字段,需要擦參數
slug_field
中指定字段名稱。
-
應該用于表示目标的字段。這應該是唯一辨別任何給定執行個體的字段。例如slug_field
。這是必選參數username
-
驗證字段輸入時用于模型執行個體查詢的查詢器。 關系必須明确設定queryset
queryset
read_only = True
-
many
True
-
allow_null
True
None
False
class AlbumSerializer(serializers.ModelSerializer):
tracks = serializers.SlugRelatedField(
many=True,
read_only=True,
slug_field='title'
)
class Meta:
model = Album
fields = ('album_name', 'artist', 'tracks')
{
'album_name': 'Dear John',
'artist': 'Loney Dear',
'tracks': [
'Airport Surroundings',
'Everything Turns to You',
'I Was Only Going Out',
...
]
}
HyperlinkedIdentityField
HyperlinkedIdentityField
将傳回指定
view-name
的超連結的字段。
-
應該用作關系目标的視圖名稱。如果您使用的是标準路由器類,則它将是格式為view_name
的字元串。必選參數<model_name>-detail
-
lookup_field
URL
pk
-
lookup_url_kwarg
URL conf
lookup_field
-
format
format
format
參數進行覆寫format
class AlbumSerializer(serializers.HyperlinkedModelSerializer):
track_listing = serializers.HyperlinkedIdentityField(view_name='track-list')
class Meta:
model = Album
fields = ('album_name', 'artist', 'track_listing')
{
'album_name': 'The Eraser',
'artist': 'Thom Yorke',
'track_listing': 'http://www.example.com/api/track_list/12/',
}
嵌套序列化關系模型
在序列化模型中指定嵌套序列化關系模型将傳回一個該嵌套序列化關系模型對應的資料模型中序列化的資料。
讀起來有些拗口,看例子吧。
-
many
True
class TrackSerializer(serializers.ModelSerializer):
class Meta:
model = Track
fields = ('order', 'title', 'duration')
class AlbumSerializer(serializers.ModelSerializer):
tracks = TrackSerializer(many=True, read_only=True)
class Meta:
model = Album
fields = ('album_name', 'artist', 'tracks')
{
'album_name': 'The Grey Album',
'artist': 'Danger Mouse',
'tracks': [
{'order': 1, 'title': 'Public Service Announcement', 'duration': 245},
{'order': 2, 'title': 'What More Can I Say', 'duration': 264},
{'order': 3, 'title': 'Encore', 'duration': 159},
],
}