drf--序列化組件

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()
View Code

路由相關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'  子表在主表中對應的外鍵屬性,反向引用
相關文章
相關標籤/搜索