drf-->ModelSerializer:mysql
相關: 1.setting配置; 2.路由分發,路由相關; 3.自定義異常處理; 4.model相關; 5.serializers序列化相關; 6.view相關;
settings.pylinux
INSTALLED_APPS = [ ... 'rest_framework', ] DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'dg_proj', 'USER': 'root', 'PASSWORD': '123', } } LANGUAGE_CODE = 'zh-hans' TIME_ZONE = 'Asia/Shanghai' USE_I18N = True USE_L10N = True USE_TZ = False
MEDIA_URL = '/media/' MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
項目名下__init__文件中git
import pymysql
pymysql.install_as_MySQLdb()
路由相關sql
# 主路由 from django.conf.urls import url, include from django.contrib import admin from django.views.static import serve from django.conf import settings urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^api/', include('api.urls')), url(r'^media/(?P<path>.*)', serve, {'document_root': settings.MEDIA_ROOT}), ] #子路由 urlpatterns = [ url(r'^books/$', views.Book.as_view()), url(r'^books/(?P<pk>.*)/$', views.Book.as_view()), url(r'^v2/books/$', views.V2Book.as_view()), url(r'^v2/books/(?P<pk>.*)/$', views.V2Book.as_view()), ]
model.py數據庫
基表:存儲有關數據庫的信息的底層表,在數據庫中獨創的對象 class BaseModel(models.Model): is_delete = modles.BooleanField(default=0) create_time = models.DateTimeField(auto_now_add=True) #做爲基表的model不能再數據庫中造成對應的表***** class Meta: abstract = True
class Book(BaseModel): name = models.CharField(max_length=64) price = models.DecimalField(max_digits=5, decimal_places=2) img = models.ImageField(upload_to='img', default='img/default.jpg') publish = models.ForeignKey( to='Publish', db_constraint=False, # 斷關聯 related_name='books', # 反向查詢字段:publish_obj.books 就能訪問全部出版的書 on_delete=models.DO_NOTHING, # 設置連表操做關係 ) authors = models.ManyToManyField( to='Author', db_constraint=False, related_name='books' ) # 序列化插拔式屬性 - 完成自定義字段名完成連表查詢 @property def publish_name(self): return self.publish.name @property def author_list(self): return self.authors.values('name', 'age', 'detail__mobile').all() class Publish(BaseModel): """name、address、is_delete、create_time""" name = models.CharField(max_length=64) address = models.CharField(max_length=64) class Meta: db_table = 'publish' verbose_name = '出版社' verbose_name_plural = verbose_name def __str__(self): return self.name class Author(BaseModel): """name、age、is_delete、create_time""" name = models.CharField(max_length=64) age = models.IntegerField() class Meta: db_table = 'author' verbose_name = '做者' verbose_name_plural = verbose_name def __str__(self): return self.name class AuthorDetail(BaseModel): """mobile, author、is_delete、create_time""" mobile = models.CharField(max_length=11) author = models.OneToOneField( to='Author', db_constraint=False, related_name='detail', on_delete=models.CASCADE, ) class Meta: db_table = 'author_detail' verbose_name = '做者詳情' verbose_name_plural = verbose_name def __str__(self): return '%s的詳情' % self.author.name
admin.pydjango
from . import models admin.site.register(models.Book) admin.site.register(models.AuthorDetail) admin.site.register(models.Author) admin.site.register(models.Publish)
django 腳本化啓動api
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "drfday1.settings") django.setup()
exception.py:自定義異常處理器服務器
from rest_framework.views import excepthon_handler as drf_excepthon_handler from rest_framework.views import Response from rest_framework import status def exception_handler(exc,context): #drf的 exception_handler作基礎處理 response = drf_exception_handler(exc,conteax) if response is None: print('%s-%s-%s'%(context['view'],context['request'].method,exc)) return Response({ 'detail':'服務器錯誤' },status=status.HTTP_500_INTERNAL_SERVER_ERROR,exception=True) return response
Serializer.pyide
from rest_frameword.serializers import ModelSerializer,serializerMethodField from . import models from rest_frameword.excepthon import ValidationError #序列化 class BookModelSerializer(ModelSerializer): class Meta: #(*****) #序列化類關聯的model類 model = models.Book #參與序列化的字段 fields = ('name','price','publish','author') #(***) #全部字段 fields = '__all__' #exclude 是除過fields查出的全部字段,與fields不能共存 exclude = ('id','img') #連表查詢深度 depth=1 #反序列化 class BookModelDeserializer(ModelSerializer): class Meta: model = models.Book # fields = ('name','price','publish','authors') # extra_kwargs 用來完成反序列化字段的 系統校驗規則 fields = '__all__' extra_kwargs ={ 'name':{ 'write_only':True, 'min_length':1, 'error_messages':{ 'required': '必填項', 'min_length': '不夠', } } } 單個字段的驗證 1.在序列化器裏定義校驗字段的鉤子方法 validate_字段 2.獲取字段的數據 3.驗證不經過,拋出異常 raise serializers.ValidationError("校驗不經過的說明") 4.驗證經過,直接返回字段數據 def validate_title(self,value): # 判斷value是否含有敏感字段 if "xx" in value: # 存在敏感字段,拋出異常並附上自定義的緣由 raise serializers.ValidationError("該字段含有敏感詞") # 不存在,則直接返回 return value 多個字段的驗證 1.在序列化器定義validate方法 2.attrs是全部數據組成的字典 3.不符合拋出異常 raise serializers.ValidationError("校驗不經過的說明") def validate(self, attrs):# arrrs是數據組成的字典 # 判斷linux的數是否在linux分類 if "linux" in attrs.get('title') and attrs['category_post'] == 2: return attrs else: raise serializers.ValidationError("圖書與分類不一致") 自定義驗證器 使用:在字段添加 validators=[自定義驗證器,] def my_validate(value): if "xxx" in value: raise serializers.ValidationError("該字段包含敏感詞!!!") else: return value title = serializers.CharField(max_length=32,validators=[my_validate,]) # 使用自定義驗證器 #序列化與反序列化整合版 (終極版本) class V2BookModelSerializer(ModelSerializer): """ 1) fields中設置全部序列化與反序列化字段 2) extra_kwargs劃分只序列化或只反序列化字段 write_only:只反序列化 read_only:只序列化 自定義字段默認只序列化(read_only) 3) 設置反序列化所需的 系統、局部鉤子、全局鉤子 等校驗規則 """ class Meta: model = models.Book fields = ('name','price','img','author_list','publish_name','publish','authors') extra_kwargs = { 'name':{ 'required':True, 'min_length':3, 'error_messages':{ 'required':'必填項', 'min_length':'最少3' } }, 'publish':{'write_only':True}, 'authors':{'write_only':True}, 'img':{'read_only':True}, 'author_list':{'read_only':True}, 'publish_name':{'read_only':True}, } #單字段校驗 def validate_name(self,value): if 'xx' in value.lower(): raise ValidationError('書名不符合規則') return value #多字段校驗 def validate(self,attrs): publish = attrs.get('publish') name = attrs.get('name') if models.Book.objects.filter(name=name,publish=publish): raise ValidationError('這本書已存在') return attrs
views.py:post
from . importo models,serializers from rest_framework.views import APIView from rest_framework.response import Pesponse class Books(APIView):# 繼承rest_framework的APIView def get(self,request,*args,**kwargs): pk = kwargs.get('pk') if pk: try: book_obj = models.Book.objects.get(pk=pk,is_delete=False) book_data = serializers.BookModelSerializer(book_obj).data except: return Response({ 'status':1, 'msg':'沒有這本書' }) else: book_query = models.Book.objects.all().filter(is_delete=False) book_data = serializers.BookModelSerializer(book_query,many=True).data return Response({ 'status':0, 'msg':'ok', 'results':book_data }) def post(self,request,*args,**kwargs): request_data = request.data book_ser = serializers.BookModelDeserializer(data=request_data) # 當校驗失敗,立刻終止當前視圖方法,拋異常返回給前臺 book_ser.is_valid(raise_exception=True) book_obj = book_ser.save()# 調用 create return Response({ 'status': 0, 'msg': 'ok', 'results': serializers.BookModelSerializer(book_obj).data }) class V2books(APIView): #查 def get(self,request,*args,**kwargs): pk = kwargs.get('pk') if pk: try: book_obj = models.Book.objects.filter(pk=pk,is_delete=False) book_data = serializers.V2BookModelSerializer(book_obj).data except: return Response({ 'status': 1, 'msg': '書籍不存在' }) else: book_list = models.Book.objects.all().filter(is_delete=False) book_data = serializers.V2BookModelSerializer(book_list,many=True).data return Response({ 'status': 0, 'msg': 'ok', 'results': book_data }) # 單增:傳的數據是與model對應的字典 # 羣增:傳的數據是 裝多個 model對應字典 的列表 def post(self,request,*args,**kwargs): request_data = request.data if isinstance(request_data,dict): many = False elif isinstance(request_data, list): many = True else: return Response({ 'status': 1, 'msg': '數據有誤', }) book_ser = serializers.V2BookModelSerializer(data=request_data,many=many) book_ser.is_valid(raise_exception=True) book_result = book_ser.save() return Response({ 'status': 0, 'msg': 'ok', 'results': serializers.V2BookModelSerializer(book_result, many=many).data }) # 單刪:有pk # 羣刪:有pks | {"pks": [1, 2, 3]} def delete(self,request,*args,**kwargs): pk = kwargs.get('pk') if pk: pks = [pk] else: pks = request.data.get('pks') if models.Book.objects.filter(pk__in=pks,is_delete=False).update(is_delete=True): return Response({ 'status': 0, 'msg': '刪除成功', }) return Response({ 'status': 1, 'msg': '刪除失敗', })
orm之 斷關聯多表關係
1、外鍵位置: 一對多 - 外鍵放多的一方 一對一 - 從邏輯正反向考慮,如做者表與做者詳情表,做者刪除級聯刪除詳情,詳情刪除做者依舊存在,因此建議外鍵在詳情表中 多對多 - 外鍵在關係表中 2、ORM正向方向連表查找: 正向:經過外鍵字段 eg: author_detial_obj.author 反向:經過related_name的值 eg:author_obj.detail 注:依賴代碼見下方 3、連表操做關係: 1)做者刪除,詳情級聯 - on_delete=models.CASCADE 2)做者刪除,詳情置空 - null=True, on_delete=models.SET_NULL 3)做者刪除,詳情重置 - default=0, on_delete=models.SET_DEFAULT 4)做者刪除,詳情不動 - on_delete=models.DO_NOTHING 注:拿做者與做者詳情表舉例 4、外鍵關聯字段的參數 - 如何實現 斷關聯、目前表間操做關係、方向查詢字段 i)做者詳情表中的 author = models.OneToOneField( to='Author', related_name='detail', db_constraint=False, on_delete=models.CASCADE ) ii)圖書表中的 publish = models.ForeignKey( to='Publish', related_name='books', db_constraint=False, on_delete=models.DO_NOTHING, ) authors = models.ManyToManyField( to='Author' related_name='books', db_constraint=False, ) 注: 1.ManyToManyField不能設置on_delete,OneToOneField、ForeignKey必須設置on_delete(django1.x系統默認級聯,可是django2.x必須手動明確) 2.db_constraint db_constraint 惟一約束 db_constraint = True 方便查詢 約束字段 db_constraint = fales(*) 不約束字段 同時也能夠查詢,就是保留跨表查詢的便利 3.on_delete 外鍵的刪除 1.on_delete = CASCADE:這就是默認的選項,級聯刪除,你無需顯性指定它 2.on_delete = PROTECT:保護模式,若是採用該選項,刪除的時候,會拋出ProtectedError錯誤 3.on_delete = SET_NULL:置空模式,刪除的時候,外鍵字段被設置爲空 注:前提就是blank=True, null=True,定義該字段的時候,容許爲空 4.on_delete = SET_DEFAULT: 置默認值,刪除的時候,外鍵字段設置爲默認值, 5.on_delete = DO_NOTHING: 該模式做者刪除,詳情不動 4 related_name = 'xxx' 子表在主表中對應的外鍵屬性,反向引用