• drf框架


    1.多表与基表概念

    2.多表断关联关系分析

    3.多表序列化组件

    4.自定义序列化深度连表查询

    5.多表反序列化组件

    6.序列化反序列化整合(重点)

    7.群增接口实现

    8.单删群删接口实现

    课程准备:配置settings.py

     1 INSTALLED_APPS = [
     2     # ...
     3     'rest_framework',
     4 ]
     5 
     6 DATABASES = {
     7     'default': {
     8         'ENGINE': 'django.db.backends.mysql',
     9         'NAME': 'dg_proj',
    10         'USER': 'root',
    11         'PASSWORD': '123',
    12     }
    13 }
    14 """
    15 任何__init__文件
    16 import pymysql
    17 pymysql.install_as_MySQLdb()
    18 """
    19 
    20 LANGUAGE_CODE = 'zh-hans'
    21 TIME_ZONE = 'Asia/Shanghai'
    22 USE_I18N = True
    23 USE_L10N = True
    24 USE_TZ = False
    25 
    26 MEDIA_URL = '/media/'
    27 MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
    代码

    路由:

     1 #
     2 from django.conf.urls import url, include
     3 from django.contrib import admin
     4 from django.views.static import serve
     5 from django.conf import settings
     6 urlpatterns = [
     7     url(r'^admin/', admin.site.urls),
     8     url(r'^api/', include('api.urls')),
     9     url(r'^media/(?P<path>.*)', serve, {'document_root': settings.MEDIA_ROOT}),
    10 ]
    11 
    12 #
    13 from django.conf.urls import url
    14 from . import views
    15 urlpatterns = [
    16     
    17 ]
    代码

    一.多表与基表概念

    多表设计(有哪些表):

     1 """
     2 Book表:name、price、img、authors、publish、is_delete、create_time
     3 
     4 Publish表:name、address、is_delete、create_time
     5     
     6 Author表:name、age、is_delete、create_time
     7 
     8 AuthorDetail表:mobile, author、is_delete、create_time
     9     
    10 BaseModel基表
    11     is_delete、create_time
    12 上面四表继承基表,可以继承两个字段
    13 """
    代码

    什么是基表:

    # 基表,其他的表需要用到的就继承
    class BaseModel(models.Model):
        is_delete = models.BooleanField(default=False)
        create_time = models.DateTimeField(auto_now_add=True)
    
        # 设置 abstract = True 来声明基表,作为基表的Model不能再数据库中形成对应的表
        class Meta:
            abstract = True

    二.多表断关联关系分析

    多表断关联关系所有知识点:

     1 """
     2 1、外键位置:
     3     一对多 - 外键放多的一方
     4     一对一 - 从逻辑正反向考虑,如作者表与作者详情表,作者删除级联删除详情,详情删除作者依旧存在,所以建议外键在详情表中
     5     多对多 - 外键在关系表中
     6     
     7 2、ORM正向方向连表查找:
     8     正向:通过外键字段 eg: author_detial_obj.author 
     9     反向:通过related_name的值 eg:author_obj.detail
    10     注:依赖代码见下方
    11     
    12 3、连表操作关系:
    13     1)作者删除,详情级联 - on_delete=models.CASCADE
    14     2)作者删除,详情置空 - null=True, on_delete=models.SET_NULL
    15     3)作者删除,详情重置 - default=0, on_delete=models.SET_DEFAULT
    16     4)作者删除,详情不动 - on_delete=models.DO_NOTHING
    17     注:拿作者与作者详情表举例
    18     
    19 4、外键关联字段的参数 - 如何实现 断关联、目前表间操作关系、方向查询字段
    20     i)作者详情表中的
    21     author = models.OneToOneField(
    22         to='Author',
    23         related_name='detail', 反向查询的时候就不用表名小写了,可以写你自定义的
    24         db_constraint=False, 断关联
    25         on_delete=models.CASCADE 级联
    26     )
    27     
    28     ii)图书表中的
    29     publish = models.ForeignKey(
    30         to='Publish',
    31         related_name='books',
    32         db_constraint=False,
    33         on_delete=models.DO_NOTHING,  删除一方,另一方不动
    34     )
    35     authors = models.ManyToManyField(
    36         to='Author'
    37         related_name='books',
    38         db_constraint=False,
    39     )
    40     注:ManyToManyField不能设置on_delete,OneToOneField、ForeignKey必须设置on_delete(django1.x系统默认级联,但是django2.x必须手动明确)
    41 """
    知识点

    model类:

      1 from django.db import models
      2 
      3 # Create your models here.
      4 
      5 
      6 # 基表,其他的表需要用到的就继承
      7 class BaseModel(models.Model):
      8     is_delete = models.BooleanField(default=False)
      9     create_time = models.DateTimeField(auto_now_add=True)
     10 
     11     # 设置 abstract = True 来声明基表,作为基表的Model不能再数据库中形成对应的表
     12     class Meta:
     13         abstract = True
     14 
     15 # 图书管理系统表:Book,Author,AuthorDetail,Publish
     16 '''
     17 Book表: name、price、img、authors、publish、is_delete、create_time
     18 Publish表: name、address、is_delete、create_time
     19 Author表: name、age、is_delete、create_time
     20 AuthorDetail表: mobile, author、is_delete、create_time
     21 '''
     22 class Book(BaseModel):
     23     name = models.CharField(max_length=64)
     24     price = models.DecimalField(max_digits=5,decimal_places=2)
     25     img = models.ImageField(upload_to='img',default='img/default.jpg')
     26     # 书籍表一对多出版社
     27     publish = models.ForeignKey(
     28         to='Publish',
     29         db_constraint=False, # 断关联
     30         related_name='books', # 反向查询字段:publish_obj.books 就能访问所有出版的书
     31         on_delete=models.DO_NOTHING,# 设置连表操作关系
     32     )
     33     # 就是一个方法属性,可以利用插拔式给前台返回数据
     34         # 序列化插拔式属性 - 完成自定义字段名完成连表查询
     35     @property
     36     def publish_name(self):
     37         return self.publish.name
     38 
     39     @property
     40     def author_list(self):
     41         return self.authors.values('name','age','detail__mobile').all()
     42 
     43 
     44 
     45 
     46     # 数据表对多对作者表
     47     authors = models.ManyToManyField(
     48         to='Author',
     49         db_constraint=False,
     50         related_name='books',
     51 
     52     )
     53     class Meta:
     54         db_table = 'book'
     55         verbose_name = '书籍'
     56         verbose_name_plural = verbose_name
     57     def __str__(self):
     58         return self.name
     59 
     60 
     61 class Publish(BaseModel):
     62     name = models.CharField(max_length=64)
     63     address = models.CharField(max_length=64)
     64 
     65     class Meta:
     66         db_table = 'publish'
     67         verbose_name = '出版社'
     68         verbose_name_plural = verbose_name
     69     def __str__(self):
     70         return self.name
     71 
     72 class Author(BaseModel):
     73     name = models.CharField(max_length=64)
     74     age = models.IntegerField()
     75 
     76     class Meta:
     77         db_table = 'author'
     78         verbose_name = '作者'
     79         verbose_name_plural = verbose_name
     80 
     81     def __str__(self):
     82         return self.name
     83 
     84 
     85 class AuthorDetail(BaseModel):
     86     mobile = models.CharField(max_length=11)
     87     # 一多一作者表
     88     author = models.OneToOneField(
     89         to='Author',
     90         db_constraint=False, # 断关联,数据库没有了联系,但是逻辑上还有
     91         # 现在反向查可以直接通过自定义的这个名字
     92         related_name='detail',
     93         on_delete=models.DO_NOTHING,
     94 
     95 
     96     )
     97 
     98     class Meta:
     99         db_table = 'author_detail'
    100         verbose_name = '作者详情'
    101         verbose_name_plural = verbose_name
    102 
    103     def __str__(self):
    104         return '%s的详情'% self.author.name
    model类里面的代码

    三.多表序列化组件

    序列化层:api/serializers.py

    1 from rest_framework.serializers import ModelSerializer
    2 from . import models
    3 class BookModelSerializer(ModelSerializer):
    4     class Meta:
    5         # 需要序列化的model类,
    6         model = models.Book
    7         # 我要返回给前台哪些字段 也可以称为插拔式,不想反回了,就不写
    8         fields = ('name','price','publish_name','author_list')
    重点代码
     1 from rest_framework.serializers import ModelSerializer, SerializerMethodField
     2 from rest_framework.exceptions import ValidationError
     3 from . import models
     4 
     5 # 可以单独作为Publish接口的序列化类,也可以作为Book序列化外键publish辅助的序列化组件
     6 class PublishModelSerializer(ModelSerializer):
     7     class Meta:
     8         # 序列化类关联的model类
     9         model = models.Publish
    10         # 参与序列化的字段
    11         fields = ('name', 'address')
    12 
    13 class BookModelSerializer(ModelSerializer):
    14     # 了解: 该方式设置的序列化字段,必须在fields中声明
    15     # publish_address = SerializerMethodField()
    16     # def get_publish_address(self, obj):
    17     #     return obj.publish.address
    18 
    19     # 自定义连表深度 - 子序列化方式 - 该方式不能参与反序列化,使用在序列化反序列化共存时,不能书写
    20     publish = PublishModelSerializer()
    21 
    22     class Meta:
    23         # 序列化类关联的model类
    24         model = models.Book
    25         # 参与序列化的字段
    26         fields = ('name', 'price', 'img', 'author_list', 'publish')
    27 
    28         # 了解知识点
    29         # 所有字段
    30         # fields = '__all__'
    31         # 与fields不共存,exclude排除哪些字段
    32         # exclude = ('id', 'is_delete', 'create_time')
    33         # 自动连表深度
    34         # depth = 1
    详细代码,还有一些了解知识点 自定义序列化深度连表查询

    视图层:api/views.py

     1 # 负责请求过来的
     2 from rest_framework.views import APIView
     3 # 负责响应的
     4 from rest_framework.response import Response
     5 # 负责模型与序列化的
     6 from . import models,serializers
     7 
     8 class Book(APIView):
     9     def get(self,request,*args,**kwargs):
    10         pk = kwargs.get('pk')
    11         if pk:
    12             try:
    13                 book_obj = models.Book.objects.get(pk=pk)
    14                 book_data = serializers.BookModelSerializer(book_obj).data
    15             except:
    16                 return Response({
    17                     'status':1,
    18                     'msg':'书籍不存在',
    19                 })
    20         else:
    21             book_query = models.Book.objects.all()                  # 因为是一个列表,有多个值
    22             book_data = serializers.BookModelSerializer(book_query,many=True).data
    23         return Response({
    24             'status': 0,
    25             'msg': 'ok',
    26             'results':book_data
    27         })
    视图层代码

    路由层:api/urls.py

     1 子路由:
     2 from django.conf.urls import url
     3 from . import views
     4 
     5 # 子路由
     6 urlpatterns = [
     7     url(r'^books/$',views.Book.as_view()),
     8     url(r'^books/(?P<pk>.*)/$',views.Book.as_view()),
     9 
    10 ]
    11 
    12 主路由:
    13 # 路由分发先导入include
    14 from django.conf.urls import url,include
    15 from django.contrib import admin
    16 from django.conf import settings
    17 from django.views.static import serve
    18 
    19 urlpatterns = [
    20     url(r'^admin/', admin.site.urls),
    21     # 路由分发
    22     url(r'^api/', include('api.urls')),
    23     # 把放置图片的文件接口开放
    24     url(r'^media/(?P<path>.*)', serve, {'document_root': settings.MEDIA_ROOT}),
    25 ]
    路由层代码

    五.多表反序列化组件

    序列化层:api/serializers.py

    注意点:  ModelSerializer类已经帮我们实现了 create 与 update 方法

         extra_kwargs 用来完成反序列化字段的 系统校验规则

     1 class BookModelDeserializer(ModelSerializer):
     2     class Meta:
     3         # 需要序列化的model类,
     4         model = models.Book
     5         # 我要返回给前台哪些字段 也可以称为插拔式,不想反回了,就不写
     6         fields = ('name', 'price','publish','authors')
     7 
     8         # extra_kwargs 用来完成反序列化字段的系统校验规则
     9         # required=True 就是代表这个字段也要校验,error_messages自定义报错信息
    10         extra_kwargs = {
    11             'name':{
    12                 'required':True,
    13                 'min_length':1,
    14                 'error_messages':{
    15                     'required':'必填项',
    16                     'min_length':'太短',
    17                 }
    18             }
    19         }
    20 
    21     #局部钩子
    22     def validate_name(self,value):
    23         # 书名不能包含g字符
    24         if 'g' in value.lower():
    25             raise ValidationError('书名不能包含g')
    26         # 如果不包含g就可以出版
    27         return value
    28 
    29     #全局钩子 同一个出版社不能出名字相同的书
    30     def validate(self, attrs):
    31         publish = attrs.get('publish')
    32         name = attrs.get('name')
    33         # 如果判断成立就抛异常
    34         if models.Book.objects.filter(name=name,publish=publish):
    35         # 全局的可以规定一下key和value
    36             raise ValidationError({'book':'该书已存在'})
    37         return attrs
    序列化层代码

    视图层:api/views.py

     1 class Book(APIView):
     2     def post(self, request, *args, **kwargs):
     3         request_data = request.data
     4         book_ser = serializers.BookModelDeserializer(data=request_data)
     5         # raise_exception=True:当校验失败,马上终止当前视图方法,抛异常返回给前台
     6         book_ser.is_valid(raise_exception=True)
     7         book_obj = book_ser.save()
     8         return Response({
     9             'status': 0,
    10             'msg': 'ok',
    11             'results': serializers.BookModelSerializer(book_obj).data
    12         })
    视图层代码

    路由层:api/urls.py

     1 主路由:
     2 # 路由分发先导入include
     3 from django.conf.urls import url,include
     4 from django.contrib import admin
     5 from django.conf import settings
     6 from django.views.static import serve
     7 
     8 urlpatterns = [
     9     url(r'^admin/', admin.site.urls),
    10     # 路由分发
    11     url(r'^api/', include('api.urls')),
    12     # 把放置图片的文件接口开放
    13     url(r'^media/(?P<path>.*)', serve, {'document_root': settings.MEDIA_ROOT}),
    14 ]
    15 
    16 子路由:
    17 from django.conf.urls import url
    18 
    19 from . import views
    20 
    21 urlpatterns = [
    22     url(r'^books/$', views.Book.as_view()),
    23     url(r'^books/(?P<pk>.*)/$', views.Book.as_view()),
    24 
    25 ]
    路由层代码

    六.序列化反序列化整合(重点)里面包含了群增接口实现,单删群删接口实现

    序列化层:api/serializers.py

    注意点:

    """
    1) fields中设置所有序列化与反序列化字段
    2) extra_kwargs划分只序列化或只反序列化字段
        write_only:只反序列化
        read_only:只序列化
        自定义字段默认只序列化(read_only)
     自定义字段也可以不需要写,因为自定义的字段是只读,数据库不需要,默认就是read_only
    3) 设置反序列化所需的 系统、局部钩子、全局钩子 等校验规则
    """
     1 # 序列化与反序列化整合版本
     2 class V2BookModelSerializer(ModelSerializer):
     3     class Meta:
     4         # 需要序列化的model类,
     5         model = models.Book
     6         # 我要返回给前台哪些字段 也可以称为插拔式,不想反回了,就不写
     7         # 因为现在序列化和反序列化整合在一起了,所以不管序列化数据还是反序列化数据都要写上
     8         # 但是也出现了一些问题,就是序列化的时候,反序列化的字段也出现了,这个时候就需要用到了extra_kwargs
     9         fields = ('name', 'price','img','author_list','publish_name','publish','authors')
    10         extra_kwargs = {
    11             'name': {
    12                 'required': True,
    13                 'min_length': 1,
    14                 'error_messages': {
    15                     'required': '必填项',
    16                     'min_length': '太短',
    17                 }
    18             },
    19             'publish':{
    20                 # 只参加反序列化的字段
    21                 'write_only':True
    22             },
    23             'author':{
    24                 'write_only':True
    25             },
    26             # 只参加序列化的字段
    27             'img':{
    28                 'read_only':True
    29             },
    30             # 下面俩个字段也可以不需要,因为自定义的字段是只读,数据库不需要,默认就是read_only
    31             'author_list': {
    32                 'read_only': True
    33             },
    34             'publish_name': {
    35                 'read_only': True
    36             }
    37 
    38         }
    39         # 局部钩子
    40 
    41     def validate_name(self, value):
    42         # 书名不能包含g字符
    43         if 'g' in value.lower():
    44             raise ValidationError('书名不能包含g')
    45         # 如果不包含g就可以出版
    46         return value
    47 
    48         # 全局钩子 同一个出版社不能出名字相同的书
    49 
    50     def validate(self, attrs):
    51         publish = attrs.get('publish')
    52         name = attrs.get('name')
    53         # 如果判断成立就抛异常
    54         if models.Book.objects.filter(name=name, publish=publish):
    55             # 全局的可以规定一下key和value
    56             raise ValidationError({'book': '该书已存在'})
    57         return attrs
    代码

    视图层:api/views.py

    注意点:

    单查:有pk
    群查:无pk
        # 单增:传的数据是与model对应的字典
        # 群增:传的数据是 装多个model对应字典的列表
    
    
        # 单删:有pk
        # 群删:有pks  群删的形式:{"pks":[1,2,3]}
        # 单删和群删不需要序列化的处理,因为它就是改一下字段
    如果是群增和群删需要指定一个参数:many=True
     1 # 负责请求过来的
     2 from rest_framework.views import APIView
     3 # 负责响应的
     4 from rest_framework.response import Response
     5 # 负责模型与序列化的
     6 from . import models,serializers
     7 
     8 # 序列化与反序列化整合版本
     9 class V2Book(APIView):
    10     # 单查:有pk
    11     # 群查:无pk
    12     def get(self,request,*args,**kwargs):
    13         pk = kwargs.get('pk')
    14         if pk:
    15             try:
    16                 book_obj = models.Book.objects.get(pk=pk)
    17                 book_data = serializers.V2BookModelSerializer(book_obj).data
    18             except:
    19                 return Response({
    20                     'status':1,
    21                     'msg':'书籍不存在',
    22                 })
    23         else:
    24             book_query = models.Book.objects.all()                  # 因为是一个列表,有多个值
    25             book_data = serializers.V2BookModelSerializer(book_query,many=True).data
    26         return Response({
    27             'status': 0,
    28             'msg': 'ok',
    29             'results':book_data
    30         })
    31 
    32     # 单增:传的数据是与model对应的字典
    33     # 群增:传的数据是 装多个model对应字典的列表
    34     def post(self, request, *args, **kwargs):
    35         request_data = request.data
    36         # 如何完成群增,可以把问题想的简单一点,就字典就是单增,列表就是群增
    37         # 判断如果request_data就走单增的逻辑
    38         if isinstance(request_data,dict):
    39             many = False  # 单增就是many=False ,也就是说不需要many
    40         elif isinstance(request_data, list):
    41             # 如果是list就走群增的逻辑 ,只要写了many=True就可以序列化和反序列化多个
    42             many = True
    43         else:
    44             # 如果都不成立就是数据有问题
    45             return Response({
    46                 'status': 1,
    47                 'msg': '数据有误',
    48             })
    49         book_ser = serializers.V2BookModelSerializer(data=request_data, many=many)
    50         # 当校验失败,马上终止当前视图方法,抛异常返回给前台
    51         book_ser.is_valid(raise_exception=True)
    52         book_result = book_ser.save() # 序列化的结果调用保存方法
    53         return Response({
    54             'status': 0,
    55             'msg': 'ok',                       # 如果要是多增,返回给前台数据也需要many=True
    56             'results': serializers.V2BookModelSerializer(book_result,many=many).data
    57         })
    58 
    59     # 单删:有pk
    60     # 群删:有pks  群删的形式:{"pks":[1,2,3]}
    61     # 单删和群删不需要序列化的处理,因为它就是改一下字段
    62     def delete(self, request, *args, **kwargs):
    63         pk = kwargs.get('pk')
    64         if pk:
    65             # 把单删和群删统一了
    66             pks = [pk]
    67         else:
    68             pks = request.data.get('pks')         # 不能重复删除
    69         if models.Book.objects.filter(pk__in=pks,is_delete=False).update(is_delete=True):
    70             return Response({
    71                 'status':0,
    72                 'msg':'删除成功',
    73             })
    74         else:
    75             return Response({
    76                 'status': 1,
    77                 'msg': '删除失败',
    78             })
    视图层代码

    路由层:api/urls.py

    urlpatterns = [
        url(r'^v2/books/$', views.V2Book.as_view()),
        url(r'^v2/books/(?P<pk>.*)/$', views.V2Book.as_view()),
    ]
    class BookModelDeserializer(ModelSerializer):
    class Meta:
    # 需要序列化的model类,
    model = models.Book
    # 我要返回给前台哪些字段 也可以称为插拔式,不想反回了,就不写
    fields = ('name', 'price','publish','authors')

    # extra_kwargs 用来完成反序列化字段的系统校验规则
    # required=True 就是代表这个字段也要校验,error_messages自定义报错信息
    extra_kwargs = {
    'name':{
    'required':True,
    'min_length':1,
    'error_messages':{
    'required':'必填项',
    'min_length':'太短',
    }
    }
    }

    #局部钩子
    def validate_name(self,value):
    # 书名不能包含g字符
    if 'g' in value.lower():
    raise ValidationError('书名不能包含g')
    # 如果不包含g就可以出版
    return value

    #全局钩子 同一个出版社不能出名字相同的书
    def validate(self, attrs):
    publish = attrs.get('publish')
    name = attrs.get('name')
    # 如果判断成立就抛异常
    if models.Book.objects.filter(name=name,publish=publish):
    # 全局的可以规定一下key和value
    raise ValidationError({'book':'该书已存在'})
    return attrs
  • 相关阅读:
    ContentProvider简单介绍
    hdu 1087 Super Jumping! Jumping! Jumping!(dp 最长上升子序列和)
    点点文刊 -- 记录生活的色彩
    【struts2+hibernate4】小型电子商务站点
    IOS学习之蓝牙4.0
    POJ 1988 Cube Stacking (种类并查集)
    Android开发之 shape的使用
    妄想性仮想人格障害 新手教程 +改动器
    Spring 的 ApplicationEvent and ApplicationListener
    Offer是否具有法律效力?
  • 原文地址:https://www.cnblogs.com/zahngyu/p/11695816.html
Copyright © 2020-2023  润新知