咱們在views.py中不論是增刪改查操做後都要經過Response返回status,msg或者網絡狀態碼與狀態信息和外界傳來的數據,所以咱們能夠將這些所有封裝到一個類中數據庫
django
from rest_framework.response import Response # 自定義response類 class APIResponse(Response): def __int__(self, status=0, msg='ok', http_status=None, headers=None, exception=False, **kwargs): # 將外界傳來的數據存儲在kwargs中,外界傳來的數據狀態碼,狀態信息及其餘額外字段都格式化成data數據 data= { 'status': status, 'msg': msg } if kwargs: data.update(kwargs) # 繼承原有的網絡狀態碼及狀態信息 super().__init__(data=data, status=http_status, headers=headers, exception=exception)
使用:在views中直接使用默認就是{"status": 0, "msg": "ok"}api
# APIResponse() 表明就返回 {"status": 0, "msg": "ok"} # APIResponse(result="結果") 表明返回 {"status": 0, "msg": "ok", "result": "結果"} # APIResponse(status=1, msg='error', http_status=400, exception=True) 異常返回 {"status": 1, "msg": "error"}
一、兩張表之間有關係的,進行增刪改的操做的時候都會相互影響(效率低),查詢操做正常網絡
二、有關係的兩張表,斷開關聯,但原來的數據保持與原來一致,每張表均可以單獨操做,增刪改操做效率極高,可是容易出現髒數據(開發中能夠避免),因爲數據沒有任何變化,查詢操做不會受影響app
三、Django的ORM支持斷關聯操做關係表,且全部的操做方式與沒有斷開關聯操做一致post
一、一對多:外鍵字段ForeignKey必須在多的一方,書與出版社,外鍵在書表中測試
二、多對多:ManyToManyField放在任何一方均可以,由於會建立第三張關係表,用兩個外鍵分別關聯兩個表spa
三、一對一:OneToOneField放在依賴的表,做者與做者詳情,放在詳情表中,OneToOneField也能夠轉換成 外鍵 + 惟一約束rest
一、ForeignKey能夠設置related_name,db_constraint,on_deletecode
二、OneToOneField能夠設置related_name,db_constraint,on_delete
三、ManyToManyField能夠設置related_name,db_constraint
不能設置on_delete,緣由:不論是關聯在哪張表上,數據修改,都會影響到關係表(默認級聯),若是想控制,只能自定義關係表,在關係表的兩個外鍵分別設置on_delete
一、related_name:表之間反向訪問的名字,默認是表名小寫 | 表名小寫_set,正向外鍵字段就是屬性名,反向外鍵字段就是設置的related_name
二、db_constraint:表之間的關聯關係,默認是True,表明關聯,手動設置爲False斷關聯,提升增刪改操做,且其餘操做不會受影響
三、on_delete:在Django 1.x默認就是CASCADE級聯刪除,在Django2.x下必須手動明確
一、做者沒,做者詳情必定沒用:CASCADE
二、做者沒,書還在:DO_NOTHING
三、部門沒,員工進入未分組部門:SET_DEFAULT (須要配合default屬性使用)
四、部門沒,員工部門的外鍵字段設爲空,SET_NULL (須要配合null=True屬性使用)
class Author(models.Model): name = models.CharField(max_length=64) class AuthorDetail(models.Model): phone = models.CharField(max_length=11) # 外鍵字段設置依賴的一方 author = models.OneToOneField( to=Author, related_name='detail', # 反向訪問的名字 db_constraint=False, # 表之間的關聯,斷關聯 on_delete=models.SET_NULL, # 關聯的外鍵沒,設爲空 null=True )
測試:
import os, django os.environ.setdefault("DJANGO_SETTINGS_MODULE", "d_proj.settings") django.setup() from api.models import Author, AuthorDetail # 測試正向反向查詢 # a1 = Author.objects.first() # print(a1.name) # print(a1.detail.phone) # ad2 = AuthorDetail.objects.last() # print(ad2.phone) # print(ad2.author.name) # 級聯關係測試 # ad2 = AuthorDetail.objects.last() # type: AuthorDetail # ad2.delete() # Author.objects.first().delete()
抽象出各表中共有的字段,而且不會完成數據庫遷移,必須配置abstract=True,其餘表繼承該表便可
# 基類:是抽象的(不會完成數據庫遷移),目的是提供共有字段的 class BaseModel(models.Model): is_delete = models.BooleanField(default=False) updated_time = models.DateTimeField(auto_now_add=True) class Meta: abstract = True # 必須完成該配置
一、fields='__ all__' 將所有字段提供給外界(不經常使用)
class AuthorModelSerializer(serializers.ModelSerializer): class Meta: model = models.Author # 不經常使用,將所有字段提供給外界 fields = '__all__'
二、exclude=['is_delete', 'updated_time'] 排除指定字段,返回其餘字段,可是不能包含外鍵的反向字段(不經常使用)
class AuthorModelSerializer(serializers.ModelSerializer): class Meta: model = models.Author # 不經常使用,排除指定字段的其餘全部字段,不能自動包含 外鍵反向 字段 exclude = ['is_delete', 'updated_time']
三、depth自動深度,自動深度會顯示外鍵關聯的全部字段(不經常使用)
class AuthorModelSerializer(serializers.ModelSerializer): class Meta: model = models.Author # 'detail', 'books' 是 外鍵(正向|反向) 字段 fields = ['name', 'detail', 'books'] # 不經常使用,自動深度,自動深度會顯示外鍵關聯表的全部字段 depth = 2
四、子序列化:對於只有查操做的時候咱們能夠採用子序列化
子序列化的字段,必須是外鍵字段,不論是正向反向,而且多表纔有子序列化
子序列化的類必須寫在上面,而且序列化的數據是單個默認是many=False,多個數據對應時many=True
子序列化其實就是自定義序列化字段,覆蓋了原有的外鍵字段的規則,全部不能進行反序列化,只能讀不能寫入,因此只能針對只有查操做的時候採用
class AuthorDetailSerializer(serializers.ModelSerializer): class Meta: model = models.AuthorDetail fields = ['phone'] class BookModelSerializer(serializers.ModelSerializer): class Meta: model = models.Book fields = ['name', 'price'] class AuthorModelSerializer(serializers.ModelSerializer): # 子序列化類必須寫在上方,而且只能對外鍵字段覆蓋,不能進行寫操做反序列化,因此只能對於只查的操做 # 不設置read_only,至關於容許反序列化,而自己就不能反序列化,反序列化會報錯 # 設置了read_only,反序列化不會報錯,可是新增的數據沒有外鍵字段的數據 # books = BookModelSerializer(many=True) books = BookModelSerializer(many=True, read_only=True) # detail = AuthorDetailSerializer() detail = AuthorDetailSerializer(read_only=True) class Meta: model = models.Author fields = ['name', 'books', 'detail']
一、外鍵字段要參與反序列化,,因此外鍵字段要設置爲write_only
二、外鍵關係須要連表序列化結果給前臺,能夠用@property來自定義連表序列化
三、字段少時能夠自定義序列化邏輯,字段多時能夠藉助序列化類子序列化來完成序列化過程
models.py
class Book(BaseModel): # ... @property # @property字段默認就是read_only,且不容許修改 def publish_name(self): return self.publish.name @property # 1字段少能夠用自定義序列化過程 def author_list(self): temp_author_list = [] for author in self.authors.all(): author_dic = { "name": author.name } try: author_dic['phone'] = author.detail.phone except: author_dic['phone'] = '' temp_author_list.append(author_dic) return temp_author_list @property # 2字段多能夠用藉助序列化類完成序列化過程 def read_author_list(self): from .serializers import AuthorModelSerializer return AuthorModelSerializer(self.authors.all(), many=True).data
serializers.py
# 輔助序列化類子序列化 class AuthorDetailModelSerializer(serializers.ModelSerializer): class Meta: model = models.AuthorDetail fields = ['phone'] # 輔助序列化類 class AuthorModelSerializer(serializers.ModelSerializer): detail = AuthorDetailModelSerializer(many=False, read_only=True) class Meta: model = models.Author fields = ['name', 'detail'] # 主序列化類 class BookModelSerializer(serializers.ModelSerializer): class Meta: model = models.Book fields = ('name', 'price', 'image', 'publish', 'authors', 'publish_name', 'author_list', 'read_author_list') extra_kwargs = { 'image': { 'read_only': True, }, 'publish': { # 系統原有的外鍵字段,要留給反序列化過程使用,序列化外鍵內容,用@property自定義 'write_only': True, }, 'authors': { 'write_only': True, } }
一、如何區別是單增仍是羣增:判斷request.data是{ }單增仍是[ ]羣增
二、羣增若是有一個失敗會直接拋出異常給前臺,其餘數據也不會存入數據庫中
# 單增羣增 def post(self, request, *args, **kwargs): # 如何區別單增羣增:request.data是{}仍是[] if not isinstance(request.data, list): # 單增 serializer = serializers.BookModelSerializer(data=request.data) serializer.is_valid(raise_exception=True) # 若是校驗失敗,會直接拋異常,返回給前臺 obj = serializer.save() # 爲何要將新增的對象從新序列化給前臺:序列化與反序列化數據不對等 return APIResponse(result=serializers.BookModelSerializer(obj).data, http_status=201) else: # 羣增 serializer = serializers.BookModelSerializer(data=request.data, many=True) serializer.is_valid(raise_exception=True) # 若是校驗失敗,會直接拋異常,返回給前臺 objs = serializer.save() # 爲何要將新增的對象從新序列化給前臺:序列化與反序列化數據不對等 return APIResponse(result=serializers.BookModelSerializer(objs, many=True).data, http_status=201)