DRF普通序列化(瞭解一下就行)
重新創建一個新的應用
python manage.py startapp app02
創建完應用之後,要記得註冊應用
先創建模型類
from django.db import models
# Create your models here.
class Article(models.Model):
title = models.CharField(verbose_name='標題', max_length=100)
vum = models.IntegerField(verbose_name='瀏覽量')
content = models.TextField(verbose_name='內容')
然後再序列化
先在app02下創建一個序列化文件serializers.py
在drf中,每一個模型都可以序列化
from rest_framework import serializers
#導入最開始的序列化
from .models import Article
#導入模型類
class ArticleSerializer(serializers.Serializer):
#在最普通的序列化裏面,要序列化的字段、還有下面的兩個方法都需要手打出來,得自己寫
id = serializers.IntegerField(read_only=True)
vum = serializers.IntegerField()
content = serializers.CharField(max_length=1000)
title = serializers.CharField(required=True, max_length=100)
def create(self, validated_data):
return Article.objects.create(**validated_data)
def update(self, instance, validated_data):
instance.title = validated_data.get('title', instance.title)
#instance.title就是說,沒有取到的話,就用原來的數據
instance.vum = validated_data.get('vum', instance.vum)
instance.content = validated_data.get('content', instance.content)
instance.save()
#創建序列化器對象的時候,如果沒有傳遞instance實例,則調用save()方法的時候,create()被調用,
# 相反,如果傳遞了instance實例,則調用save()方法的時候,update()被調用。
return instance
之後就開始遷移文件,生成表
python manage.py makemigrations
python manage.py migrate
普通序列化裏面的參數約束
read_only:True表示不允許用戶自己上傳,只能用於api的輸出。
write_only: 與read_only對應
required: 顧名思義,就是這個字段是否必填。
allow_null/allow_blank:是否允許爲NULL/空 。
error_messages:出錯時,前端的信息提示。
name = serializers.CharField(required=True, min_length=6,
error_messages={
‘min_length’: ‘名字不能小於6個字符’,
‘required’: ‘請填寫名字’})
label: 字段顯示設置,如 label=’驗證碼’
help_text: 在指定字段增加一些提示文字,這兩個字段作用於api頁面比較有用
style: 說明字段的類型,這樣看可能比較抽象,看下面例子:
#在api頁面,輸入密碼就會以*顯示
password = serializers.CharField(
style={‘input_type’: ‘password’})
#會顯示選項框
color_channel = serializers.ChoiceField(
choices=[‘red’, ‘green’, ‘blue’],
style={‘base_template’: ‘radio.html’})
validators:自定義驗證邏輯
用終端傳數據
可以在pycharm自帶的數據庫裏面傳數據,也可以在終端傳入數據
這裏採用終端傳入數據
python manage.py shell 打開終端
from app02.serializers import ArticleSerializer 導入模型類
from rest_framework.renderers import JSONRenderer 可以生成json數據的包
然後開始創建數據(也就是反序列化)
反序列化的關鍵字是data
d = {"title":"這是一個測試標籤","vum":11,"content":"哈哈哈哈"}
ser = ArticleSerializer(data=d)
ser.is_valid()# 驗證數據是否正確,傳的時候如果少一個字段,會返回false
ser.save()# 保存數據
然後這個時候去看數據庫的時候(pycharm自帶的),會發現有數據
查數據
有了數據之後,就在終端接着查數據
from app02.models import *
# 查多個數據(多個對象序列化)
arts = Article.objects.all()
ser = ArticleSerializer(instace=arts,many=True) # 如果多個對象序列化 需要加many
ser.data
這就是查到的數據,如何返回json數據呢
from rest_framework.renderers import JSONRenderer
json_data = JSONRenderer().render(ser.data)
json_data
這個json_data就是序列化好的json數據
查詢所有的數據返回的是一個列表,然後通過https response 返回就可以了
這個就是把模型轉化成json數據
這個查多個數據,也就是序列化多個數據,那單個數據可以查到嗎?
單個對象的序列化
art = Article.objects.get(id=1)
ser = ArticleSerializer(art)
json_data = JSONRenderer().render(ser.data)
json_data
查詢當個數據返回的是字典
當我們序列化的時候,也就是查數據的時候,要用instance傳參
當我們反序列化,也就是傳入數據的時候,要用data傳參
DRF模型序列化(繼承ModelSerializer)
ModelSerializers默認幫我們實現了創建和更新方法,簡化了我們的操作,當然如果你想自己寫,可以重寫它。其餘使用方法跟普通的序列化一樣。
class ArticleSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = ('id', 'title', 'vnum', 'content') #三者取一
#exclude = () 表示不返回字段 三者取一
#fields = '__all__': 表示所有字段 三者取一
#read_only_fields = () #設置只讀字段 不接受用戶修改
模型類
模型類還是和普通序列化一樣,我們用同一個例子來對比一下,普通序列化和模型序列化的區別
from django.db import models
# Create your models here.
class Article(models.Model):
title = models.CharField(verbose_name='標題', max_length=100)
vum = models.IntegerField(verbose_name='瀏覽量')
content = models.TextField(verbose_name='內容')
序列化
接着在已經創建好的serializers.py上寫
from rest_framework import serializers
#導入最開始的序列化
from .models import Article
#導入模型類
#模型序列化
class ArticleSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = '__all__'
#序列化這個模型類裏面的而全部字段
視圖(增加數據的視圖)
from django.shortcuts import render
from .models import *
#導入模型
from .serializers import *
#導入序列化類
from rest_framework.renderers import JSONRenderer
#轉json數據
from django.http import HttpResponse
from rest_framework.parsers import JSONParser
#把json數據轉成python裏的數據
from django.views.decorators.csrf import csrf_exempt
#解決403錯誤,使用這個封裝函數,把django裏面的驗證先去掉
# Create your views here.
@csrf_exempt
def article_list(request):
if request.method == 'GET':
#獲取數據 #查詢所有的數據
arts = Article.objects.all()
ser = ArticleSerializer(instance=arts,many=True)
#序列化
json_data = JSONRenderer().render(ser.data)
#反序列化,轉json數據
return HttpResponse(json_data,content_type='application/json',status=200)
elif request.method == 'POST':
#接收數據,把用戶輸入的json數據轉成python數據
data = JSONParser().parse(request)#把前端傳過來的json數據轉化成python裏面的數據
ser = ArticleSerializer(data=data)
if ser.is_valid():
ser.save()
json_data = JSONRenderer().render(ser.data)
return HttpResponse(json_data, content_type='application/json', status=201)
#201表示創建成功數據
json_data = JSONRenderer().render(ser.errors)
return HttpResponse(json_data, content_type='application/json', status=400)
#400表示get request
路由
from django.contrib import admin
from django.urls import path
from app02 import views
#導入試圖
urlpatterns = [
path('articles/', views.article_list,name='article_list'),
]
根及路由
from django.contrib import admin
from django.urls import path,include
from app01 import views
from rest_framework.routers import DefaultRouter
#使用提供的路由
route = DefaultRouter()
#把視圖生成的路由註冊到這個裏
route.register(r'students',views.StudentViewSet)
route.register(r'groups',views.GroupViewSet)
#這樣的話,他會幫我們生成對應的路由
'''
http://127.0.0.1:8000/students就會生成這樣的路由
如果是獲取當個學生的話,路由就是
http://127.0.0.1:8000/students/1/
'''
urlpatterns = [
path('admin/', admin.site.urls),
# path('api/',include(route.urls)),
# #這個加上api之後的路由就是http://127.0.0.1:8000/api/students
path('api/',include('app02.urls'))
]
可以通過postman看一下
這是獲取數據和添加數據,還有刪除和更新
更新刪除視圖
class JSONResponse(HttpResponse):
def __init__(self, data, **kwargs):
content = JSONRenderer().render(data)
kwargs['content_type'] = 'application/json'
super(JSONResponse, self).__init__(content, **kwargs)
#封裝一個函數
@csrf_exempt
def article_detail(request,pk):
#要獲取單個數據,一定要傳進來一個關於這個數據的唯一標識
try:
art = Article.objects.get(pk=pk)
#查詢像刪除的數據,獲取id
except Article.DoesNotExist:
#捕獲異常,如果這個數據不存在
return HttpResponse(status=404)
if request.method == 'GET':
serializer = ArticleSerializer(instance=art)
#把查到數據序列化
return JSONResponse(serializer.data,status=200)
elif request.method == 'PUT':
data = JSONParser().parse(request)
#解析前端的數據
serializer = ArticleSerializer(instance=art,data=data)
#序列化單個數據
if serializer.is_valid():
#如果序列化好的數據存在的話
serializer.save()
#就保存起來
return JSONResponse(serializer.data,status=201)
#返回json數據
return JSONResponse(serializer.errors, status=400)
#不存在的話,就返回一個error錯誤
elif request.method == 'PATCH':
#表示局部更新
data = JSONParser().parse(request)
#解析前端的數據
serializer = ArticleSerializer(instance=art,data=data,partial=True)
#序列化單個數據,局部更新一定要加上partial=True,默認是false
if serializer.is_valid():
#如果序列化好的數據存在的話
serializer.save()
#就保存起來
return JSONResponse(serializer.data,status=201)
#返回json數據
return JSONResponse(serializer.errors, status=400)
#不存在的話,就返回一個error錯誤
elif request.method == 'DELETE':
art.delete()
#表示把查到的數據刪除
return HttpResponse(status=204)
#204表示刪除成功
drf模型序列化高級一
模型類
from django.db import models
# Create your models here.
class Category(models.Model):
name = models.CharField(verbose_name='分類名字',max_length=10)
class Article(models.Model):
title = models.CharField(verbose_name='標題', max_length=100)
vum = models.IntegerField(verbose_name='瀏覽量')
content = models.TextField(verbose_name='內容')
category = models.ForeignKey(to=Category,on_delete=models.CASCADE,related_name='articles')
之後,開始遷移
python manage.py makemigrations
python manage.py migrate
序列化
from rest_framework import serializers
#導入最開始的序列化
from .models import Article,Category
#導入模型類
#模型序列化
class ArticleSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = '__all__'
#序列化這個模型類裏面的而全部字段
class CatrgorySerializer(serializers.ModelSerializer):
class Meta:
model = Category
fields = ('id','name','articles')
#因爲模型中有反向查找
視圖
from django.shortcuts import render
from .models import *
from .serializers import ArticleSerializer,CatrgorySerializer
from rest_framework.renderers import JSONRenderer
from django.http import JsonResponse,HttpResponse
from rest_framework.parsers import JSONParser
from django.http import Http404
from django.views.decorators.csrf import csrf_exempt
# Create your views here.
class JSONResponse(HttpResponse):
def __init__(self, data, **kwargs):
content = JSONRenderer().render(data)
kwargs['content_type'] = 'application/json'
super(JSONResponse, self).__init__(content, **kwargs)
#封裝一個函數
@csrf_exempt
def article_list(request):
if request.method == 'GET':
#請求數據,這個過程就是要把數據序列化
arts = Article.objects.all()
#查詢數據
ser = ArticleSerializer(instance=arts,many=True)
#序列化查詢出來的數據,instance表示你要序列化的數據,
# data表示你要反序列化的數據
#many=True 如果你序列化的字段很多,一定要加上這個
json_data = JSONRenderer().render(ser.data)
#調用data方法,把序列化好的數據取出來,
return HttpResponse(json_data,content_type='applications/json',status=200)
#注意不要忘記,告訴瀏覽器,返回的數據類型,
#content_type='applications/json'表示,網頁上用json形式把josn_data數據展示出來
#狀態碼200200是響應正常的意思
elif request.method == 'POST':
#新增,也就是json數據轉化爲可傳輸數據
data = JSONParser().parse(request)
#把前端json的數據解析出來,解析成python裏面的數據類型
serialize = ArticleSerializer(data=data)
#反序列化數據,注意,有顏色的這個data是關鍵字
if serialize.is_valid():
#校驗數據,假如存在
serialize.save()
#就保存數據
json_data = JSONRenderer().render(serialize.data)
#然後再取出來數據,用json數據返回去
return HttpResponse(json_data, content_type='applications/json', status=200)
#201表示創建成功
json_data = JSONRenderer().render(serialize.errors)
#表示序列化沒有成功
return HttpResponse(json_data, content_type='applications/json', status=400)
#校驗不成功,就返回401未經授權
@csrf_exempt
def article_detail(request,pk):
#要獲取單個數據,一定要傳進來一個關於這個數據的唯一標識
try:
art = Article.objects.get(pk=pk)
#查詢像刪除的數據,獲取id
except Article.DoesNotExist:
#捕獲異常,如果這個數據不存在
return HttpResponse(status=404)
if request.method == 'GET':
serializer = ArticleSerializer(instance=art)
#把查到數據序列化
return JSONResponse(serializer.data,status=200)
elif request.method == 'PUT':
data = JSONParser().parse(request)
#解析前端的數據
serializer = ArticleSerializer(instance=art,data=data)
#序列化單個數據
if serializer.is_valid():
#如果序列化好的數據存在的話
serializer.save()
#就保存起來
return JSONResponse(serializer.data,status=201)
#返回json數據
return JSONResponse(serializer.errors, status=400)
#不存在的話,就返回一個error錯誤
elif request.method == 'PATCH':
#表示局部更新
data = JSONParser().parse(request)
#解析前端的數據
serializer = ArticleSerializer(instance=art,data=data,partial=True)
#序列化單個數據,局部更新一定要加上partial=True,默認是false
if serializer.is_valid():
#如果序列化好的數據存在的話
serializer.save()
#就保存起來
return JSONResponse(serializer.data,status=201)
#返回json數據
return JSONResponse(serializer.errors, status=400)
#不存在的話,就返回一個error錯誤
elif request.method == 'DELETE':
art.delete()
#表示把查到的數據刪除
return HttpResponse(status=204)
#204表示刪除成功
@csrf_exempt
def category_list(request):
if request.method == 'GET':
#請求數據,這個過程就是要把數據序列化
cat = Category.objects.all()
#查詢數據
ser = CatrgorySerializer(instance=cat,many=True)
#序列化查詢出來的數據,instance表示你要序列化的數據,
# data表示你要反序列化的數據
#many=True 如果你序列化的字段很多,一定要加上這個
json_data = JSONRenderer().render(ser.data)
#調用data方法,把序列化好的數據取出來,
return HttpResponse(json_data,content_type='applications/json',status=200)
#注意不要忘記,告訴瀏覽器,返回的數據類型,
#content_type='applications/json'表示,網頁上用json形式把josn_data數據展示出來
#狀態碼200200是響應正常的意思
elif request.method == 'POST':
#新增,也就是json數據轉化爲可傳輸數據
data = JSONParser().parse(request)
#把前端json的數據解析出來,解析成python裏面的數據類型
serialize = CatrgorySerializer(data=data)
#反序列化數據,注意,有顏色的這個data是關鍵字
if serialize.is_valid():
#校驗數據,假如存在
serialize.save()
#就保存數據
json_data = JSONRenderer().render(serialize.data)
#然後再取出來數據,用json數據返回去
return HttpResponse(json_data, content_type='applications/json', status=200)
#201表示創建成功
json_data = JSONRenderer().render(serialize.errors)
#表示序列化沒有成功
return HttpResponse(json_data, content_type='applications/json', status=400)
#校驗不成功,就返回401未經授權
@csrf_exempt
def category_detail(request,pk):
#要獲取單個數據,一定要傳進來一個關於這個數據的唯一標識
try:
art = Category.objects.get(pk=pk)
#查詢像刪除的數據,獲取id
except Category.DoesNotExist:
#捕獲異常,如果這個數據不存在
return HttpResponse(status=404)
if request.method == 'GET':
serializer = CatrgorySerializer(instance=art)
#把查到數據序列化
return JSONResponse(serializer.data,status=200)
elif request.method == 'PUT':
data = JSONParser().parse(request)
#解析前端的數據
serializer = CatrgorySerializer(instance=art,data=data)
#序列化單個數據
if serializer.is_valid():
#如果序列化好的數據存在的話
serializer.save()
#就保存起來
return JSONResponse(serializer.data)
#返回json數據
return JSONResponse(serializer.errors, status=400)
#不存在的話,就返回一個error錯誤
elif request.method == 'PATCH':
#表示局部更新
data = JSONParser().parse(request)
#解析前端的數據
serializer = CatrgorySerializer(instance=art,data=data,partial=True)
#序列化單個數據,局部更新一定要加上partial=True,默認是false
if serializer.is_valid():
#如果序列化好的數據存在的話
serializer.save()
#就保存起來
return JSONResponse(serializer.data)
#返回json數據
return JSONResponse(serializer.errors, status=400)
#不存在的話,就返回一個error錯誤
elif request.method == 'DELETE':
art.delete()
#表示把查到的數據刪除
return HttpResponse(status=204)
#204表示刪除成功
路由
from django.contrib import admin
from django.urls import path,include
from app02 import views
urlpatterns = [
path('article',views.article_list,name='article-list'),
path('articles/<int:pk>',views.article_detail,name='article-detail'),
#這個表示獲取單個數據,一定要注意和視圖裏面的參數保持一致,主鍵要一致
#name表示重命名
path('category', views.category_list, name='category_list'),
path('category/<int:pk>', views.category_detail, name='category_detail'),
]
然後就可以去訪問一下
DRF高級序列二(基於序列化)
StringRelatedField(和模型類的str配合使用,返回名字)
StringRelatedField 將返回一個對應關係 model 的 unicode() 方法的字符串。
#模型序列化
class ArticleSerializer(serializers.ModelSerializer):
class Meta:
category = serializers.StringRelatedField()
model = Article
fields = '__all__'
#序列化這個模型類裏面的而全部字段
class Category(models.Model):
name = models.CharField(verbose_name='分類名字',max_length=10)
def __str__(self):
return self.name
#這塊寫什麼返回什麼,寫self.name返回的是輸入的名字
#比如寫哈哈,那麼返回的就是哈哈
category = serializers.StringRelatedField(many=True)
#如果是一查多的話,要寫上many=True
在Article的模型下面加上srt方法
然後去訪問標籤頁
顯示的就是對應的文章標題,而不是id
PrimaryKeyRelatedField(顯示對應模型的id)
使用 PrimaryKeyRelatedField 將返回一個對應關係 model 的主鍵。
參數:
- queryset 用於在驗證字段輸入時模型實例查找。 關係必須明確設置 queryset,或設置 read_only = True
many 如果是對應多個的關係,就設置爲 True- allow_null 如果設置爲 True,則該字段將接受 None 的值或爲空的關係的空字符串。默認爲 False
pk_field 設置爲一個字段以控制主鍵值的序列化/反序列化。例如,pk_field = UUIDField(format =‘hex’) 將UUID主鍵序列化爲緊湊的十六進制表示。
class CategorySerializer(serializers.ModelSerializer):
articles = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
class Meta:
model = Category
fields = '__all__'
PrimaryKeyRelatedField,如果是單個不需要加,many=True
標籤所對應的文章的id就會被返回,但是,其實它默認的就是返回的id
HyperlinkedRelatedField(在關聯的模型中返回超鏈接)
使用 HyperlinkedRelatedField 將返回一個超鏈接(點擊跳轉對應頁面),該鏈接指向對應關係 model 的詳細數據,view-name 是必選參數,爲對應的視圖生成超鏈接。
參數:
- view_name 用作關係目標的視圖名稱。如果使用的是標準路由器類,那麼它的格式爲 -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 CategorySerializer(serializers.ModelSerializer):
articles = serializers.HyperlinkedRelatedField(
many=True,#標籤查文章有很多,所以要加上這個參數,一對一的話,不用加
read_only=True,
view_name='article_detail', #如果根及路由有別名的話,這個地方應該寫成 根及路由的別名:應用及路由的別名
lookup_field='id', # 數據庫字段的名字
lookup_url_kwarg="id" # 路由中參數的名字,必須和路由參數保持一致
)
class Meta:
model = Category
fields = '__all_
要想使用這個連接,必須在視圖裏面增加上下文,否則報錯。
在視圖裏面加上上下文
content={‘request’:request}
添加位置在每一個序列化的地方
就在這些地方添加
這個時候在去訪問
SlugRelatedField(可以返回對應模型的任何一個字段)
使用 SlugRelatedField 將返回一個指定對應關係 model 中的字段,需要參數 slug_field 中指定字段名稱。可以返回模型類中的任何字段
參數:
- slug_field 應該用於表示目標的字段。這應該是唯一標識任何給定實例的字段。例如 username 。這是必選參數
- queryset 驗證字段輸入時用於模型實例查詢的查詢器。 關係必須明確設置 queryset,或設置 read_only = True
- many 如果應用於多對多關係,則應將此參數設置爲 True
- allow_null 如果設置爲 True,則該字段將接受 None 的值或爲空的關係的空字符串。默認爲 False
class CategorySerializer(serializers.ModelSerializer):
articles = serializers.SlugRelatedField(
many=True,
read_only=True,
slug_field='vum'
#這個寫什麼,就返回對應模型的值
)
class Meta:
model = Category
fields = '__all__'
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 ArticleSerializer(serializers.ModelSerializer):
category = serializers.HyperlinkedIdentityField(view_name="app03:category-detail", lookup_field='id')
#view_name的格式 根及路由的別名:應用及的路由別名
#lookup_field應用及的路由參數,保持一致
class Meta:
model = Article
fields = '__all__'
-------------------------------------------------
class CategorySerializer(serializers.ModelSerializer):
articles = serializers.HyperlinkedIdentityField(view_name="app03:article-detail", lookup_field='id', many=True)
class Meta:
model = Category
fields = '__all__'
HyperlinkedModelSerializer(返回超鏈接)
HyperlinkedModelSerializer
類與 ModelSerializer
類相似,只不過它使用超鏈接來表示關係而不是主鍵。
view_name的參數使用方法和上面一樣
class ArticleSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Article
fields = '__all__'
extra_kwargs = {
'url': {'view_name': 'app04:article-detail', 'lookup_field': 'id'},
'category': {'view_name': 'app04:category-detail', 'lookup_field': 'pk','lookup_url_kwarg':'id'},
}
class CategorySerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Category
fields = ('id', 'name', 'articles','url')
#不寫all的原因,Category裏面沒有article字段,但是在文章的模型中用到了反向查找,就可以這麼用
extra_kwargs = {
'url': {'view_name': 'app04:category-detail', 'lookup_field': 'id'},
'articles': {'view_name': 'app04:article-detail', 'lookup_field': 'id'},
}
'''
使用extra_kwargs額外參數爲ModelSerializer添加或修改原有的選項參數---字典格式
extra_kwargs = {
'vnum': {'min_value': 0, 'required': True},
}
'''
extra_kwargs 裏面的寫什麼,什麼就會返回超鏈接
嵌套序列化關係模型(常用)
class ArticleSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = '__all__'
class CategorySerializer(serializers.ModelSerializer):
articles = ArticleSerializer(many=True)
#如果返回的單個的話,不需要加many = true
class Meta:
model = Category
fields = '__all__'
depth
這個字段可以用來深度遍歷
#注意是ModelSerializer
class CategorySerializer(serializers.ModelSerializer):
articles = ArticleSerializer(many=True)
class Meta:
model = Category
fields = '__all__'
depth = 2
把相關的數據找出來,depth爲幾就找幾層,一般建議2-3即可。
SerializerMethodField(自定義對應模型的屬性)
我們可以自定義一些屬性。
比如我們想看每個分類下有多少篇文章
class CategorySerializer(serializers.ModelSerializer):
articles = ArticleSerializer(many=True)
count = serializers.SerializerMethodField()
#這個是自定義屬性,有了SerializerMethodField,必須實現下方的函數,那個函數也有規律
class Meta:
model = Category
fields = ('id','name','articles','count')
def get_count(self, obj):
#函數的名字是 get_加上上面自定義的屬性名字
#obj表示當前分類的對象
return obj.articles.count()
source
class ArticleSerializer(serializers.ModelSerializer):
category = serializers.CharField(source='category.id')
class Meta:
model = Article
fields = '__all__'
source=‘category.id’,上面這個指定的返回id,他返回的就是id
#這個類可以定義屬性,以及想返回的值
class MyCharField(serializers.CharField):
#下面使用了這個類之後,所查到的數據都會給value,因爲查找的是所有的值,所以返回的是一個列表
#所以可以定義一個空列表,進行遍歷
def to_representation(self, value):
data_list = []
for row in value:
data_list.append({'title': row.title, 'content': row.content})
return data_list
class CategorySerializer(serializers.ModelSerializer):
#arts = MyCharField(source='articles.all')
#arts = serializers.CharField(source='articles_set.all')
#如果在模型中沒有反向查找的話,也就可以這麼寫
arts = MyCharField(source='articles_set.all')
#使用上面定義的類,然後會把查到的所有文章,都給上面的參數value,因爲是所有的文章,所以返回的是一個列表
class Meta:
model = Category
fields = ('id', 'name', 'arts')
利用source實現可讀可寫
from collections import OrderedDict
class ChoiceDisplayField(serializers.Field):
"""Custom ChoiceField serializer field."""
def __init__(self, choices, **kwargs):
"""init."""
self._choices = OrderedDict(choices)
super(ChoiceDisplayField, self).__init__(**kwargs)
# 返回可讀性良好的字符串而不是 1,-1 這樣的數字
def to_representation(self, obj):
"""Used while retrieving value for the field."""
return self._choices[obj]
def to_internal_value(self, data):
"""Used while storing value for the field."""
for i in self._choices:
# 這樣無論用戶POST上來但是CHOICES的 Key 還是Value 都能被接受
if i == data or self._choices[i] == data:
return i
raise serializers.ValidationError("Acceptable values are {0}.".format(list(self._choices.values())))
to_representation
序列化器的每個字段實際都是由該字段類型的to_representation方法決定格式的,可以通過重寫該方法來決定格式。
class ArticleSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = '__all__'
def to_representation(self, instance):
representation = super(ArticleSerializer, self).to_representation(instance)
representation['category'] = CategorySerializer(instance.category).data
representation['tags'] = TagSerializer(instance.tags, many=True).data
return representation