一:表關系如下
from django.db import models
# Create your models here.
__all__=['Book','Publisher','Authon']
class Book(models.Model):
title =models.CharField(max_length=32,verbose_name='圖書名稱')
CHOICES=((1,'python'),(2,'go'),(3,'linux'))
category=models.IntegerField(choices=CHOICES,verbose_name='圖書類別')
pub_time=models.DateTimeField(verbose_name='出版日期')
authon=models.ManyToManyField('Authon')
publisher=models.ForeignKey(to='Publisher',on_delete=None)
def __str__(self):
return self.title
class Authon(models.Model):
name= models.CharField(max_length=32, verbose_name='作者姓名')
def __str__(self):
return self.name
class Publisher(models.Model):
title = models.CharField(max_length=32, verbose_name='出版社名稱')
def __str__(self):
return self.title
二:使用django編寫接口
1:使用jsonResponse模塊進行數據序列化。
from django.http import JsonResponse
class Bookview(View):
#使用jsonResponse 當存在外鍵時,需要自己手動對數據進行處理。
def get(self,request):
book_list=models.Book.objects.values('id','title','pub_time','publisher',"category")
book_list=list(book_list)
for book in book_list:
print(book)
publisher_id = book['publisher']
publisher_obj=models.Publisher.objects.filter(id=publisher_id).first()
book['pulisher']={
'id':publisher_id,
'title':publisher_obj.title
}
return JsonResponse(book_list,safe=False,json_dumps_params={'ensure_ascii':False})
2:使用serialize模塊進行數據序列化。
def get(self,request):
book_list=models.Book.objects.all()
book_list=serializers.serialize('json',book_list,ensure_ascii=False )
return HttpResponse(book_list)
3:使用serialize和JsonResponse不方便處
a:遇到外鍵關系,需要非常繁瑣的處理。
三:使用rest_framework 中 serializers進行序列化和反序列化
1:基本准備
a:下載 rest-framewoke模塊,pip install rest-framework
b:首先要明白后端展示給前端頁面的數據,可能是經過跨表查詢的具體值。而前端傳送給后端,並不需要傳送具體的值,也就是說前端和后端對同一個資源傳遞的數據類型可能不一樣。比如性別,前端展示的是,男,女。但是后端在數據庫存儲的時候,往往是0,1
c:新建文件serializers.py(用於編寫序列化規則)
d:settings中注冊app
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'SerDemo',
'rest_framework' #app注冊
]
2:serializers序列化
a:設定路由
--注意需要調用as_view方法
from django.urls import path,include
from SerDemo import views
urlpatterns = [
path('list/', views.BookApiView.as_view()),
]
b:在serializes.py編寫序列化規則
--注意序列化規則內每一個字段都和models字段相對應。重點,
--外鍵關系一對多和多對多需要注意
--read_only=True(只進行序列化),同理write_only=True(該字段只進行反序列化)
from rest_framework import serializers
from SerDemo.models import Book
#一對多外鍵關系序列化處理
class PublisherSerializers(serializers.Serializer):
id = serializers.IntegerField()
title=serializers.CharField(max_length=32)
#多對多外鍵關系序列化處理
class AuthonSerializers(serializers.Serializer):
id = serializers.IntegerField()
name=serializers.CharField(max_length=32)
class BookSerializers(serializers.Serializer):
#不需要校驗
id = serializers.IntegerField(required=False,)
title = serializers.CharField(max_length=32)
CHOICES = ((1, 'python'), (2, 'go'), (3, 'linux'))
category = serializers.ChoiceField(choices=CHOICES, source="get_category_display",read_only=True)
pub_time = serializers.DateTimeField()
#處理一對多
publisher=PublisherSerializers(read_only=True)
#處理多對多外鍵關系 many=True
authon=AuthonSerializers(many=True,read_only=True)
c:視圖函數的編寫
--導包 (APIView,Response)
--視圖函數繼承APIView
--many默認參數不寫默認序列化一個對象,many=True 表示序列化多個對象
--get請求會對應get方法
from SerDemo import models
from rest_framework.views import APIView #視圖函數繼承APIView 不是View
from rest_framework.response import Response #用於返回值
#BookSerializers 自己定義的序列化規則
from SerDemo.serializers import *
class BookApiView(APIView):
def get(self,request):
book_obj = models.Book.objects.all()
#序列化多組數據 和一個對象,需要many=TRUE 默認一個
ret =BookSerializers(book_obj,many=True)
#序列化的數據在data屬性中
return Response(ret.data)
3:serializers反序列化
a:在serializes.py編寫反序列化規則
--首先序列化,我們常常需要把外鍵對象的值獲取給前端,而反序列化,后端僅僅需要數據庫一個id就能進行數據庫值的插入。
--write_only表示該字段只是反序列化使用,前端發送時key也應該和該值對應
--注意一對多,多對多關系,choices的字段
class BookSerializers(serializers.Serializer):
#不需要校驗
id = serializers.IntegerField(required=False,)
title = serializers.CharField(max_length=32,validators=[my_validata])
CHOICES = ((1, 'python'), (2, 'go'), (3, 'linux'))
category = serializers.ChoiceField(choices=CHOICES, source="get_category_display",read_only=True)
w_category=serializers.ChoiceField(choices=CHOICES,write_only=True)
pub_time = serializers.DateTimeField()
#處理一對多
publisher=PublisherSerializers(read_only=True)
publisher_id=serializers.IntegerField(write_only=True)
#處理多對多外鍵關系 many=True
authon=AuthonSerializers(many=True,read_only=True)
authon_id =serializers.ListField(write_only=True)
b:views文件中編寫post的請求,對數據進行添加。
--添加數據需要在BookSerializers重新編寫create方法
--注意返回值
--所有的數據都在request.data方法中,(與View方法存在request.get,request.post中不同,該方法對這些方法進行封裝)
def post(self,request):
# print(request.data)
data = BookSerializers(data=request.data)
#進行數據驗證,並且在BookSerializers中重寫create方法
if data.is_valid():
data.save()
return Response(data.data)
else:
return Response(data.errors)
c:編寫create方法
class BookSerializers(serializers.Serializer):
#不需要校驗
id = serializers.IntegerField(required=False,)
title = serializers.CharField(max_length=32,validators=[my_validata])
CHOICES = ((1, 'python'), (2, 'go'), (3, 'linux'))
category = serializers.ChoiceField(choices=CHOICES, source="get_category_display",read_only=True)
w_category=serializers.ChoiceField(choices=CHOICES,write_only=True)
pub_time = serializers.DateTimeField()
#處理一對多
publisher=PublisherSerializers(read_only=True)
publisher_id=serializers.IntegerField(write_only=True)
#處理多對多外鍵關系 many=True
authon=AuthonSerializers(many=True,read_only=True)
authon_id =serializers.ListField(write_only=True)
#向服務器添加數據,需要實現該方法
def create(self, validated_data):
book =Book.objects.create(title=validated_data['title'],category=validated_data['w_category'],
pub_time=validated_data['pub_time'],
publisher_id=validated_data['publisher_id']
)
#添加多對多關系
book.authon.add(*validated_data['authon_id'])
return book
d:put實現更新
--路由分發 path('retrieve/<int:id>',views.BookEditView.as_view())
--代碼編寫
--partial參數
def put(self,request,id):
print(request.data)
book_obj = Book.objects.filter(id=id).first()
# partial True 表示可以進行部分字段跟新,Flase 表示全部跟新,默認False
book_serializers = BookSerializers(book_obj,data=request.data,partial=True)
#需要重寫 update
if book_serializers.is_valid():
book_serializers.save()
return Response(book_serializers.validated_data)
else:
return Response(book_serializers.errors)
--重寫update方法
#數據跟新
def update(self, instance, validated_data):
print(validated_data.get('authon'))
instance.title =validated_data.get('title',instance.title)
instance.category=validated_data.get('category',instance.category)
instance.pub_time =validated_data.get('pub_time',instance.pub_time)
instance.publisher_id =validated_data.get('publisher_id',instance.publisher_id)
if validated_data.get('authon_id'):
instance.authon.set(validated_data.get('authon_id'))
instance.save()
return instance
e:實現delete方法
def delete(self,request,id):
book_obj = Book.objects.filter(id=id).first()
book_obj.delete()
return Response("")
4:serializers字段校驗擴展
a:局部鈎子校驗
--校驗字段方法,固定格式validate_字段名
-- 參數value,就是該字段的值
-- 返回值
#單個字段進行校驗
def validate_title(self, value):
if 'python' not in value.lower:
return serializers.ValidationError('標題必須含有python')
return value
b:全局鈎子多個字段聯合校驗
--方法 validate為固定方法
--attrs保存聯合字段的字段值
--注意返回值
#全局鈎子對字段進行聯合校驗
def validate(self, attrs):
if attrs['category'] =='linux' and attrs['publisher_id']==3:
return attrs
else:
return serializers.ValidationError('類型或出版社錯誤')
c:自定義鈎子驗證
#自定義校驗
#在需要進行驗證的字段引用 title = serializers.CharField(max_length=32,validators=[my_validata])
#優先級大於 validata_title 局部鈎子
def my_validata(value):
if value in '敏感信息':
raise serializers.ValidationError('不能含有敏感信息')
return value
