DRF之序列化
阿新 • • 發佈:2018-09-08
獲取 values pat 沒有 date fir 2-0 choices ron
目錄
- 準備事項
- 序列化組件初見
- 序列化字段
- ModelSerializer
- 重載create方法
- 單條數據處理
- 現階段代碼
準備事項
# models.py from django.db import models class Publisher(models.Model): title = models.CharField(max_length=32) address = models.CharField(max_length=128) def __str__(self): return self.title class Author(models.Model): name = models.CharField(max_length=32) birth_date = models.DateField() gender = models.IntegerField(choices=((0,'male'),(1,'female')),default=0) email = models.EmailField(max_length=64) def __str__(self): return self.name class Book(models.Model): title = models.CharField(max_length=32) authors = models.ManyToManyField(Author) publisher = models.ForeignKey(Publisher) pub_date = models.DateField() word_count = models.IntegerField() price = models.IntegerField(null=True,blank=True) def __str__(self): return self.title
# settings.py
INSTALLED_APPS = [
'app01',
'rest_framework',
]
序列化組件初見
利用HttpResponse返回json或者文本數據。
from rest_framework.views import APIView from django.shortcuts import HttpResponse from .models import Publisher import json from .models import Publisher from rest_framework import serializers class PublisherSerializer(serializers.Serializer): title = serializers.CharField() address = serializers.CharField() class PubliserView(APIView): """獲取所有出版社""" def get(self,request,*args,**kwargs): # 方式1: # publishers = Publisher.objects.all().values() # query set對象不能直接被序列化 # publishers = list(publishers) # return HttpResponse(json.dumps(publishers), content_type='application/json') # 方式2: from django.forms.models import model_to_dict # publishers = Publisher.objects.all() # temp = [] # for obj in publishers: # temp.append(model_to_dict(obj)) # return HttpResponse(json.dumps(temp), content_type='application/json') # 方式3 # from django.core import serializers # django的方法,與rest無關 # publishers = Publisher.objects.all() # ret = serializers.serialize('json',publishers) # return HttpResponse(ret) # 內容更多 # 方式4: publishers = Publisher.objects.all() ser = PublisherSerializer(instance=publishers,many=True) # 若實例是對象集合,則必須增加many=True print(ser.data) # [OrderedDict([('title', '長江出版社'), ('address', '武漢市武昌區')]), OrderedDict([('title', '人民出版社')] return HttpResponse(ser.data)
序列化字段
類似django form。
# urls.py from app01.views import PubliserView, BookView url(r'^books/',BookView.as_view()), # views.py class BookView(APIView): def get(self, request, *args, **kwargs): book_list = Book.objects.all() from .my_serializer import BookSerializer ser = BookSerializer(instance=book_list, many=True) # 1、返回json格式的字符串,對於瀏覽器相應內容會渲染到drf模板中,若是postman發的請求直接返回原始的數據 from rest_framework.response import Response return Response(ser.data) # 2、直接返回字符串 # return HttpResponse(ser.data) # my_serializer.py from rest_framework import serializers class BookSerializer(serializers.Serializer): title = serializers.CharField(max_length=32) pub_date = serializers.DateField() word_count = serializers.IntegerField() # 一對多使:用source屬性 publisher = serializers.CharField(source='publisher.address') # 可以指定關聯表的字段 price = serializers.IntegerField() # 針對多對多字段 # authors = serializers.CharField(source="authors.all") authors = serializers.SerializerMethodField() def get_authors(self,obj): # print(obj) authors = list(obj.authors.all().values_list('name')) # [('蔣勛',), ('易中天',)] # authors = list(obj.authors.all().values('name')) # [{'name': '蔣勛'}, {'name': '易中天'}] authors = [item[0] for item in authors if item] return authors # 本質 ''' book_list = BookSerializer(book_list,many=True) temp = [] for obj in book_list: temp.append({ "title":str(obj.title), "price":obj.price, "pub_date":str(obj.pub_date), "word_count":obj.word_count, "publisher":str(obj.publisher), "authors":str(get_authors(obj)), # 多對多字段 }) '''
ModelSerializer
類似與django的model-form。
作用:
將query_set轉換成json數據
def get(self,request): publishers = Publisher.objects.all() ser = PublisherSerializer(instance=publishers,many=True) # 若實例是對象集合,則必須增加many=True return Response(ser.data)
將 model對象 轉換成json數據
def get(self, request, pid): p_obj = Publisher.objects.filter(pk=int(pid)).first() ps = PublisherSerializer(instance=p_obj) return Response(ps.data)
3、做數據校驗,將json數據>>>成queryset或者model對象>>>記錄:
```
def post(self, request):
bs = BookSerializers(data=request.data)
# 做校驗
if bs.is_valid():
# 轉換成model對象
bs.save() # 把數據保存到數據庫中(會有反序列化操作),.save()中有 create()方法
return Response(bs.data)
else:
return HttpResponse(bs.errors) # bs.errors 表示 錯誤信息
```
語法實例:
from .models import *
class BookSerializer(serializers.ModelSerializer):
"""
僅適用於展示字段
"""
# 重載默認的字段
publisher = serializers.CharField(source='publisher.address') # 可以指定關聯表的字段
price = serializers.IntegerField()
# 針對多對多字段
authors = serializers.SerializerMethodField()
def get_authors(self,obj):
# print(obj)
authors = list(obj.authors.all().values_list('name')) # [('蔣勛',), ('易中天',)]
# authors = list(obj.authors.all().values('name')) # [{'name': '蔣勛'}, {'name': '易中天'}]
authors = [item[0] for item in authors if item]
return authors
class Meta:
model = Book
fields = '__all__'
# 對於多余多對多和一對多默認使用pk,一般為id
depth = 1
'''
# 增加前
[{
"id": 2,
"title": "蔣勛說唐詩",
"pub_date": "2012-02-07",
"word_count": 12,
"price": 34,
"publisher": 1,
"authors": [
1
]
},
# 增加後
[
{
"id": 2,
"title": "蔣勛說唐詩",
"pub_date": "2012-02-07",
"word_count": 12,
"price": 34,
"publisher": {
"id": 1,
"title": "長江出版社",
"address": "武漢市武昌區"
},
"authors": [
{
"id": 1,
"name": "蔣勛",
"birth_date": "1956-10-12",
"gender": 0,
"email": "[email protected]"
}
]
'''
重載create方法
增加對象記錄。
from .my_serializer import BookSerializers
class BookView(APIView):
def post(self, request, *args, **kwargs):
"""保存提交的數據"""
bs = BookSerializers(data=request.data)
if bs.is_valid(): # 做校驗
print('validated_data>>>>>>',bs.validated_data) # 結果為OrderedDict對象
'''
OrderedDict([
('title', 'who am i'), ('pub_date', datetime.date(2012, 12, 12)), ('word_count', 12), ('price', 29),
('publisher', <Publisher: 長江出版社>), ('authors', [<Author: 蔣勛>, <Author: 易中天>])
])
'''
bs.save() # 把數據保存到數據庫中(會有反序列化操作) # .save()中有 create()方法
print('data>>>>>>', bs.data) # 結果為字典
'''
{'id': 21, 'title': 'who am i', 'pub_date': '2012-12-12', 'word_count': 12, 'price': 29, 'publisher': 1, 'authors': [1, 2]}
'''
return Response(bs.data)
else:
return HttpResponse(bs.errors) # bs.errors 表示 錯誤信息
# 1、使用默認的字段,則無需定制
# 在postman中提交json格式的數據:{"title":"1212312!","pub_date":"2012-12-12","word_count":12,"price":29,"publisher":1,"authors":[1,2]}
class BookSerializers(serializers.ModelSerializer):
class Meta:
model = Book
fields = "__all__"
# 2、定制字段後
class BookSerializers(serializers.ModelSerializer):
publisher = serializers.CharField(source='publisher.pk')
class Meta:
model = Book
fields = "__all__"
# exclude = ['authors',]
# depth=1
# 處理多對多字段時需要重寫 save()中的 create()方法
def create(self, validated_data):
print('validated_data>>>>>>>',validated_data)
'''
{
'title': '鋼鐵是怎樣煉成的',
'pub_date': datetime.date(2012, 12, 12),
'word_count': 12, 'price': 29,
'publisher': <Publisher: 長江出版社>,
'authors': [<Author: 蔣勛>, <Author: 易中天>]
}
'''
book_obj = Book.objects.create(
title=validated_data['title'],
pub_date=validated_data['pub_date'],
word_count=validated_data['word_count'],
publisher_id=validated_data['publisher']['pk'], # 註意此處字段名稱為publisher_id!!!
price=validated_data['price'],
)
print('book_obj',book_obj)
# authors = validated_data.pop('authors')
# obj = Book.objects.create(**validated_data)
book_obj.authors.add(*validated_data['authors'])
return book_obj
單條數據處理
對特定對象的刪、改、查操作。
# urls
url(r'^books/(?P<id>\d+)/$',BookDetailView.as_view()),
# views.py
class BookDetailView(APIView):
"""對特定書籍的查看、修改和刪除操作"""
def get(self, request, id):
b_obj = Book.objects.filter(pk=int(id)).first()
bs = BookSerializers(instance=b_obj)
return Response(bs.data)
def put(self, request, id):
"""沒有對應的對象則更新,有則修改"""
b_obj = Book.objects.filter(pk=int(id)).first()
bs = BookSerializers(instance=b_obj,data=request.data)
if bs.is_valid(): # 數據需要填寫完整
bs.save()
return Response(bs.data)
else:
return HttpResponse(bs.errors)
def delete(self, request,id):
"""刪除指定的對象"""
b_obj = Book.objects.filter(pk=int(id)).first()
b_obj.delete()
return Response() # 返回空
例:postman進行put操作
現階段代碼
urls
from django.conf.urls import url
from django.contrib import admin
from app01.views import PubliserView, BookView, BookDetailView,PubliserDetailView
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^publishers/$',PubliserView.as_view()), # 新增/查詢所有
url(r'^publishers/(?P<pid>\d+)/$',PubliserDetailView.as_view()), # 編輯/新增/刪除
url(r'^books/$',BookView.as_view()), # 新增/查詢所有
url(r'^books/(?P<id>\d+)/$',BookDetailView.as_view()), # 編輯/新增/刪除
]
serializer
from rest_framework import serializers
from .models import *
class PublisherSerializer(serializers.ModelSerializer):
class Meta:
model = Publisher
fields = '__all__'
# depth = 1
class BookSerializers(serializers.ModelSerializer):
class Meta:
model = Book
fields = "__all__"
# exclude = ['authors',]
# depth=1
views
有部分重復代碼,有待優化!
from rest_framework.views import APIView
from django.shortcuts import HttpResponse
from .models import Publisher,Book
from rest_framework.response import Response
from .my_serializer import PublisherSerializer
from .my_serializer import BookSerializers
class PubliserView(APIView):
def get(self,request):
"""查詢並返回所有出版社"""
publishers = Publisher.objects.all()
ser = PublisherSerializer(instance=publishers,many=True) # 若實例是對象集合,則必須增加many=True
return Response(ser.data)
def post(self,request):
"""新增出版社"""
bs = PublisherSerializer(data=request.data)
if bs.is_valid():
bs.save()
return Response(bs.data)
else:
return Response(bs.errors)
class BookView(APIView):
def get(self, request):
"""查詢所有書籍"""
book_list = Book.objects.all()
ser = BookSerializers(instance=book_list, many=True)
from rest_framework.response import Response
return Response(ser.data)
def post(self, request):
"""新增書籍記錄"""
bs = BookSerializers(data=request.data)
if bs.is_valid(): # 做校驗
bs.save() # 把數據保存到數據庫中(會有反序列化操作) # .save()中有 create()方法
return Response(bs.data)
else:
return HttpResponse(bs.errors) # bs.errors 表示 錯誤信息
class PubliserDetailView(APIView):
"""獲取所有出版社"""
def get(self, request, pid):
"""查詢並返回某一個的出版社信息"""
p_obj = Publisher.objects.filter(pk=int(pid)).first()
ps = PublisherSerializer(instance=p_obj)
print(ps)
return Response(ps.data)
def put(self, request, pid):
"""修改或新增一條出版社信息"""
p_obj = Publisher.objects.filter(pk=int(pid)).first()
ps = PublisherSerializer(instance=p_obj, data=request.data)
print('ps>>>>',ps)
if ps.is_valid(): # 數據需要填寫完整
ps.save()
return Response(ps.data)
else:
return HttpResponse(ps.errors)
def delete(self, request,pid):
"""刪除某一條出版社記錄"""
Publisher.objects.filter(pk=int(pid)).delete()
return Response() # 返回空
class BookDetailView(APIView):
def get(self, request, id):
"""查詢並返回某一本書籍信息"""
b_obj = Book.objects.filter(pk=int(id)).first()
bs = BookSerializers(instance=b_obj)
return Response(bs.data)
def put(self, request, id):
"""修改或新增一條書籍信息"""
b_obj = Book.objects.filter(pk=int(id)).first()
bs = BookSerializers(instance=b_obj,data=request.data)
if bs.is_valid(): # 數據需要填寫完整
bs.save()
return Response(bs.data)
else:
return HttpResponse(bs.errors)
def delete(self, request,id):
"""刪除某一條書籍記錄"""
b_obj = Book.objects.filter(pk=int(id)).first()
b_obj.delete()
return Response() # 返回空
DRF之序列化