Django框架基础DRF-01

前后端分离介绍

1.前后端不分离图解

2.前后端分离图解
    

3.为什么要学习DRF    DRF可以帮助我们开发者快速的开发⼀个依托于Django的前后后端分离的项目

RESTful 介绍
    1.认识 RESTful
        1.在前后端分离的应⽤模式⾥,后端API接⼝如何定义?
              需要⼀种规范和⻛格来约束后端程序员对接⼝的定义
              RESTful 就是⽤来约束后端程序员对接⼝的定义的⼀种⻛格
        2.描述
            REST,即Representational State Transfer的缩写。维基百科称其为“ 具象状态传输” ,国内⼤部分⼈理解为“ 表现层状态转化” 。
            RESTful是⼀种开发理念。维基百科说:REST是设计⻛格⽽不是标准
            RESTful架构就是:
                • 每⼀个URL代表⼀种资源;
                • 客户端和服务器之间,传递这种资源的某种表现层;
                • 客户端通过四个HTTP动词,对服务器端资源进⾏操作,实现" 表现层状态转化" 。
    2.RESTful 设计⽅法
        域名
        版本
        路径
        HTTP动词
        过滤信息
        状态码
        错误处理
        返回结果
        超媒体
        数据传输格式
    3.Django和 DRF对⽐
        1.Django可以实现前后端分离
            Django开发前后端分离的周期⻓
            Django如果要遵守RESTful设计⻛格需要⾃⼰写对应⻛格的路由
        2.DRF专⻔实现前后端分离
            DRF开发前后端分离的周期短
            默认遵守的是RESTful设计⻛格

使⽤Django定义REST API

0.⽬的 为了学习在没有DRF的情况下,如何使⽤Django原⽣的形式实现前后端分离且遵守RETSful设计⻛格的项⽬
    1.REST API 路由说明
        """
        GET /books/ 提供所有记录
        POST /books/ 新增⼀条记录
        GET /books/<pk>/ 提供指定id的记录
        PUT /books/<pk>/ 修改指定id的记录
        DELETE /books/<pk>/ 删除指定id的记录
        响应数据 JSON
        """
    2.提供所有记录

def get(self, request):
"""提供所有记录
GET /books/
"""
    # 查询所有记录 books = [BookInfo,BookInfo,BookInfo,BookInfo,BookInfo]
    books = BookInfo.objects.all()
    # 将模型列表转成字典列表
    book_list = []
    for book in books:
        book_list.append({
        'id': book.id,
        ' btitle' : book.btitle,
        ' bpub_date' : book.bpub_date,
        'bread': book.bread,
        ' bcomment' : book.bcomment,
        'image': book.image.url if book.image else ''
        })
    # 响应JSON数据
    return JsonResponse(book_list, safe= False)

3.新增⼀条记录

def post(self, request):
"""新增⼀条记录
POST /books/
"""
    # 读取客户端传⼊的JSON数据
    json_bytes = request.body
    json_str = json_bytes.decode()
    book_dict = json.loads( json_str)
    # 创建新的记录
    book = BookInfo.objects.create(
            btitle=book_dict.get(' btitle' ),
            bpub_date=datetime.strptime(book_dict.get(' bpub_date' ), '%Y-%m-%d').date(),
            bread = book_dict['bread'],
            bcomment = book_dict[' bcomment' ]
        )
    # 构造响应数据
    response_book_dict = {
                'id': book.id,
                ' btitle' : book.btitle,
                ' bpub_date' : book.bpub_date,
                'bread': book.bread,
                ' bcomment' : book.bcomment,
                'image': book.image.url if book.image else ''
                }
    # 响应结果
    return JsonResponse(response_book_dict, status= 201)

4.提供指定id的记录

def get(self, request, pk):
"""提供指定id的记录
GET /books/<pk>/
"""
    # 判断pk是否合法
    try:
        book = BookInfo.objects.get(id=pk)
        except BookInfo.DoesNotExist:
        return HttpResponse(status= 404)
    # 构造响应数据
    response_book_dict = {
                'id': book.id,
                ' btitle' : book.btitle,
                ' bpub_date' : book.bpub_date,
                'bread': book.bread,
                ' bcomment' : book.bcomment,
                'image': book.image.url if book.image else ''
                }
    # 响应结果
    return JsonResponse(response_book_dict)

5.修改指定id的记录

def put(self, request, pk):
"""修改指定id的记录
PUT /books/<pk>
"""
    # 判断pk是否合法
    try:
        book = BookInfo.objects.get(id=pk)
        except BookInfo.DoesNotExist:
        return HttpResponse(status= 404)
    # 读取客户端传⼊的JSON数据
    json_bytes = request.body
    json_str = json_bytes.decode()
    book_dict = json.loads( json_str)
    # 修改记录
    book.btitle = book_dict.get(' btitle' )
    book.save()
    # 构造响应数据
    response_book_dict = {
            'id': book.id,
            ' btitle' : book.btitle,
            ' bpub_date' : book.bpub_date,
            'bread': book.bread,
            ' bcomment' : book.bcomment,
            'image': book.image.url if book.image else ''
            }
    # 响应结果
    return JsonResponse(response_book_dict)

6.删除指定id的记录

def delete(self, request, pk):
"""删除指定id的记录
DELETE /books/<pk>/
"""
# 判断pk是否合法
    try:
        book = BookInfo.objects.get(id=pk)
        except BookInfo.DoesNotExist:
        return HttpResponse(status= 404)
    # 删除
    book.delete()
    # 响应
    return HttpResponse(status= 204)

序列化和反序列化介绍
0.提示
    在开发REST API接⼝时,视图中做的最主要有三件事:
        • 将请求的数据(如JSON格式)转换为模型类对象(反序列化)
        • 操作数据库
        • 将模型类对象转换为响应的数据(如JSON格式)(序列化)
    1.序列化
        1.概念 将程序中的⼀个数据结构类型转换为其他格式(字典、JSON、 XML等),例如将Django中的模型类对象装换为JSON字符串,这个转换过程我们称为序列化。
        2.序列化⾏为

# 判断pk是否合法
try:
    book = BookInfo.objects.get(id=pk)
    except BookInfo.DoesNotExist:
    return HttpResponse(status= 404)
# 构造响应数据
response_book_dict = {
    'id': book.id,
    ' btitle' : book.btitle,
    ' bpub_date' : book.bpub_date,
    'bread': book.bread,
    ' bcomment' : book.bcomment,
    'image': book.image.url if book.image else ''
    }
# 响应结果
return JsonResponse(response_book_dict)

3.序列化时机 当需要给前端响应模型数据时,需要将模型数据 序列化 成前端需要的格式

2.反序列化
        1.概念 将其他格式(字典、JSON、 XML等)转换为程序中的数据,例如将JSON字符串转换为Django中的模型类对象,这个过程我们称为反序列化。
        2.反序列化⾏为

# 读取客户端传⼊的JSON数据
json_bytes = request.body
json_str = json_bytes.decode()
book_dict = json.loads( json_str)
# 创建新的记录
book = BookInfo.objects.create(
btitle=book_dict.get(' btitle' ),
bpub_date=datetime.strptime(book_dict.get(' bpub_date' ), '%Y-%m-%d').date(),
bread = book_dict['bread'],
bcomment = book_dict[' bcomment' ]
)

3.反序列化时机 当需要将⽤户发送的数据存储到数据库之前,需要使⽤反序列化
        3.总结
            在开发REST API接⼝时,我们在视图中需要做的最核⼼的事是:
            • 将数据库数据序列化为前端所需要的格式,并返回;
            • 将前端发送的数据反序列化为模型类对象,并保存到数据库中。

1.DRF介绍
    1.序列化和反序列化提示
        1.在序列化与反序列化时,虽然操作的数据不尽相同,但是执⾏的过程却是相似的,也就是说这部分代码是可以复⽤简化编写的。
        2.在开发REST   API的视图中,虽然每个视图具体操作的数据不同,但增、删、改、查的实现流程基本套路化,所以这部分代码也是可以复⽤简化编写的:
            • 增 :校验请求数据 -> 执⾏反序列化过程 -> 保存数据库 -> 将保存的对象序列化并返回
            • 删 :判断要删除的数据是否存在 -> 执⾏数据库删除
            • 改 :判断要修改的数据是否存在 -> 校验请求的数据 -> 执⾏反序列化过程 -> 保存数据库 -> 将保存的对象序列化并返回
            • 查 :查询数据库 -> 将数据序列化并返回
        3.DRF将序列化和反序列化的业务逻辑进⾏了封装 程序员只需要将序列化和反序列化的数据传给DRF即可
    2.DRF作⽤ Django REST framework可以帮助我们简化序列化和反序列化部分的代码编写,⼤⼤提⾼REST API的开发速度。
    3.DRF特点
            • 提供了定义序列化器Serializer的⽅法,可以快速根据 Django ORM 或者其它库⾃动序列化/ 反序列化;
            • 提供了丰富的类视图、Mixin扩展类,简化视图的编写;
            • 丰富的定制层级:函数视图、类视图、视图集合到⾃动⽣成 API,满⾜各种需要;
            • 多种身份认证和权限认证⽅式的⽀持;
            • 内置了限流系统;
            • 直观的 API web 界⾯;
            • 可扩展性,插件丰富
    4.相关⽂档
          官⽅⽂档 http://www.django-rest-framework.org/
          源码 https://github.com/encode/django-rest-framework/tree/master

2.DRF安装和配置
    1.DRF环境依赖
        • Python (2.7, 3.2, 3.3, 3.4, 3.5, 3.6)
        • Django (1.10, 1.11, 2.0)
        DRF是以Django扩展应⽤的⽅式提供的,所以我们可以直接利⽤已有的Django环境⽽⽆需从新创建。(若没有Django环境,需要先创建环境安装Django)
    2.安装DRF pip install djangorestframework
    3.添加rest_framework应⽤

INSTALLED_APPS = [
        ' django.contrib.admin' ,
        ' django.contrib.auth' ,
        ' django.contrib.contenttypes' ,
        ' django.contrib.sessions' ,
        ' django.contrib.messages' ,
        ' django.contrib.staticfiles' ,
        'rest_framework', # DRF
        'users.apps.UsersConfig', # 安装users应⽤, 演示基本使⽤
        'request_response.apps.RequestResponseConfig', # 演示请求和响应
        ' booktest.apps.BooktestConfig' , # 图书英雄管理应⽤
]

3.DRF初体验
    1.创建序列化器   booktest.serializers

from rest_framework import serializers
from .models import BookInfo
class BookInfoSerializer(serializers.ModelSerializer):
"""BookInfo模型类的序列化器"""
    class Meta:
        model = BookInfo
        fields = '__all__'

2.编写视图逻辑

from rest_framework.viewsets import ModelViewSet
from .models import BookInfo
from . import serializers
class BookInfoViewSet(ModelViewSet):
"""使⽤DRF实现增删改查的后端API"""
    # 指定查询集
    queryset = BookInfo.objects.all()
    # 指定序列化器
    serializer_class = serializers.BookInfoSerializer

3.定义路由

from django.conf.urls import url
from rest_framework.routers import DefaultRouter
from . import views
urlpatterns = [
# url(r'^books/$', views.BooksAPIView.as_view()),
# url(r'^books/(?P<pk>\d+)/$', views.BookAPIView.as_view()),
]
# 创建路由对象
router = DefaultRouter()
# 将视图集注册到路由
router.register(r'books', views.BookInfoViewSet)
# 视图集路由添加到urlpatterns
urlpatterns += router.urls

4.运⾏测试 GET http://127.0.0.1:8000/books/

Serializer序列化器
    1.序列化器的作⽤
        1. 进⾏数据的校验
        2. 对数据对象进⾏转换
    2.定义序列化器说明
        1.模型类

# 定义图书模型类BookInfo
class BookInfo(models.Model):
    btitle = models.CharField(max_length= 20, verbose_name= ' 名称' )
    bpub_date = models.DateField(verbose_name= ' 发布⽇期' )
    bread = models.IntegerField(default= 0 , verbose_name= ' 阅读量' )
    bcomment = models.IntegerField(default= 0 , verbose_name= ' 评论量' )
    is_delete = models.BooleanField(default= False, verbose_name= ' 逻辑删除' )
    image = models.ImageField(upload_to= 'book', verbose_name= ' 图书图⽚' , null= True)

2.序列化器

class BookInfoSerializer(serializers.Serializer):
"""图书数据序列化器"""
    id = serializers.IntegerField(label= 'ID', read_only= True)
    btitle = serializers.CharField(label= ' 名称' , max_length= 20, validators=[about_django])
    bpub_date = serializers.DateField(label= ' 发布⽇期' , required= False)
    bread = serializers.IntegerField(label= ' 阅读量' , required= False)
    bcomment = serializers.IntegerField(label= ' 评论量' , required= False)
    image = serializers.ImageField(label= ' 图⽚' , required= False)
    heroinfo_set = serializers.PrimaryKeyRelatedField(read_only= True, many= True)

3.定义序列化器字段类型和选项
        1.字段类型 类似于模型字段类型
        2.选项参数
        3.通⽤选项、参数

4.创建Serializer序列化器对象

1.构造⽅法
            Serializer的构造⽅法为:
            Serializer(instance=None, data=empty, **kwarg)
        2.构造⽅法说明
            1.⽤于序列化时
                将模型类对象传⼊instance参数
                Serializer(book)
                序列化 == 模型数据—>python字典 (⽤于输出,返回数据给前端)
            2.⽤于反序列化时
                将要被反序列化的数据传⼊data参数
                Serializer(data=data)
                反序列化 == 前端发送的数据—>经过验证—>python字典—>save—>模型类对象(⽤于输⼊,接受前端数据)
                
Serializer序列化器之序列化操作
    1.序列化⼀个模型对象
        >>> from booktest.models import BookInfo
        >>> book = BookInfo.objects.get(id=1)
        >>> book
        <BookInfo: 射雕英雄传>
        >>> from booktest.serializers import BookInfoSerializer
        >>> s = BookInfoSerializer(book)
        >>> s.data
        {'id': 1, 'btitle': '射雕英雄传', 'bpub_date': '1980-05-01', 'bread': 12, 'bcomment': 34, 'image': None}
    2.序列化多个模型对象
        >>> qs = BookInfo.objects.all()
        >>> qs
        <QuerySet [<BookInfo: 射雕英雄传>, <BookInfo: 天⻰⼋部>, <BookInfo: 笑傲江湖>, <BookInfo: 雪⼭⻜狐>, <BookInfo: ⻄游记>]>
        >>> s = BookInfoSerializer(qs, many=True)
        >>> s.data
    3.关联对象嵌套序列化
        1.增加HeroInfo对应的序列化器

class HeroInfoSerializer(serializers.Serializer):
"""英雄数据序列化器"""
    GENDER_CHOICES = (
    (0 , 'male'),
    (1 , 'female')
    )
    id = serializers.IntegerField(label= 'ID', read_only= True) # 只会做序列化(输出)
    hname = serializers.CharField(label= ' 名字' , max_length= 20)
    hgender = serializers.ChoiceField(choices=GENDER_CHOICES, label= ' 性别' , required= False)
    hcomment = serializers.CharField(label= ' 描述信息' , max_length= 200, required= False, allow_null= True)
    # 在序列化器中定义外键关联字段
    # 必须:read_only=True(让前端⽆法对外键进⾏输⼊操作,只能输出)
    hbook = serializers.PrimaryKeyRelatedField(label= ' 图书' , read_only= True)

2.序列化过程
            >>> from booktest.serializers import BookInfoSerializer, HeroInfoSerializer
            >>> from booktest.models import BookInfo, HeroInfo
            >>> hero = HeroInfo.objects.get(id=1)
            >>> hero
            <HeroInfo: 郭靖>
            >>> s = HeroInfoSerializer(hero)
            >>> s.data
            {'id': 1, 'hname': '郭靖', 'hgender': 1, 'hcomment': '降⻰⼗⼋掌', 'hbook': 1}
    4.many参数
        1.增加⼀查多的关系字段

class BookInfoSerializer(serializers.Serializer):
"""图书数据序列化器"""
    id = serializers.IntegerField(label= 'ID', read_only= True) # 只会做序列化(输出)
    btitle = serializers.CharField(label= ' 名称' , max_length= 20)
    bpub_date = serializers.DateField(label= ' 发布⽇期' , required= False)
    bread = serializers.IntegerField(label= ' 阅读量' , required= False)
    bcomment = serializers.IntegerField(label= ' 评论量' , required= False)
    image = serializers.ImageField(label= ' 图⽚' , required= False)
    # 定义⼀关联多的序列化器字段
    # many=True : 表示⼀对多
    heroinfo_set = serializers.PrimaryKeyRelatedField(read_only= True, many= True) # 新增

2.序列化过程
            >>> from booktest.models import BookInfo, HeroInfo
            >>> from booktest.serializers import BookInfoSerializer
            >>> book = BookInfo.objects.get(id=1)
            >>> book
            <BookInfo: 射雕英雄传>
            >>> s = BookInfoSerializer(book)
            >>> s.data
            {'id': 1, 'btitle': '射雕英雄传', 'bpub_date': '1980-05-01', 'bread': 12, 'bcomment': 34, 'image': None, 'heroinfo_set': [1, 2, 3, 4, 5]}

相关源码连接:

github,技术交流,欢迎指教

django 学习之DRF (一)的更多相关文章

  1. django 学习之DRF (三)

    Django学习之DRF-03 视图集    1.视图集介绍    2.视图集基本使⽤        1.需求 使⽤视图集获取列表数据和单⼀数据        2.实现 class BookInfoV ...

  2. django 学习之DRF (二)

    Django学习之DRF02 Serializer序列化器之反序列化操作    1.调⽤序列化器进⾏验证        0.准备序列化器 class BookInfoSerializer(serial ...

  3. 今天主要推荐一下django学习的网址!

    前言:每个月忙碌的头20天后,在上班时间投入到django理论学习的过程中,花了差不多3天时间简单的研究了一下django,着实废了我不少脑细胞. 采用虫师前辈的一张图和话: 如果你把这过程梳理清晰了 ...

  4. Django 学习笔记之四 QuerySet常用方法

    QuerySet是一个可遍历结构,它本质上是一个给定的模型的对象列表,是有序的. 1.建立模型: 2.数据文件(test.txt) 3.文件数据入库(默认的sqlite3) 入库之前执行 数据库同步命 ...

  5. Django 学习笔记之三 数据库输入数据

    假设建立了django_blog项目,建立blog的app ,在models.py里面增加了Blog类,同步数据库,并且建立了对应的表.具体的参照Django 学习笔记之二的相关命令. 那么这篇主要介 ...

  6. Django学习系列之Form基础

     Django学习系列之Form基础 2015-05-15 07:14:57 标签:form django 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追 ...

  7. Django学习笔记(五)—— 表单

    疯狂的暑假学习之  Django学习笔记(五)-- 表单 參考:<The Django Book> 第7章 1. HttpRequest对象的信息 request.path         ...

  8. Django学习笔记(三)—— 型号 model

    疯狂暑期学习 Django学习笔记(三)-- 型号 model 參考:<The Django Book> 第5章 1.setting.py 配置 DATABASES = { 'defaul ...

  9. django学习之Model(二)

    继续(一)的内容: 1-跨文件的Models 在文件头部import进来,然后用ForeignKey关联上: from django.db import models from geography.m ...

随机推荐

  1. python第十一天-----补:缓存操作

    memcached,首先下载python-memcached模块,在cmd中执行pip install python-memcached即可 memcached比较简单,默认情况仅支持简单的kv存储, ...

  2. 2011-03-17免Oracle客户端连远程Oracle的方法

    1.http://www.oracle.com/technetwork/topics/winsoft-085727.html上下载对应版本的instanctclinet zip包 34M 解压后92M ...

  3. RegisterUserFunc为测试对象添加新方法或重写已有方法

    QTP中为了提高扩展性,提供了一个为测试对象添加一个新的自定义方法,或者重写测试对象已有的方法的函数RegisterUserFunc,在此给大家分享一下. RegisterUserFunc:为测试对象 ...

  4. Android添加Menu菜单

    在安卓中添加Menu菜单十分简单. 步骤: 1.在menu文件夹中的main.xml文件中添加要添加的项目. <menu xmlns:android="http://schemas.a ...

  5. Python之list的创建以及使用

    list是一种有序的集合,可以随意添加和删除里面的元素. 空的list的定义:L = [] list当中的元素用[]概括起来. 在list当中可以使用索引来进行访问: 在这里我们要注意我们在进行索引的 ...

  6. Android 自定义Camera 随笔

      一.权限 <uses-permission android:name="android.permission.CAMERA" /> <uses-permiss ...

  7. springmvc 类型转换器 自定义类型转换器

    自定义类型转换器的步骤: 1.定义类型转换器 2.类型转换器的注册(在springmvc配置文件处理) 来解决多种日期格式的问题: springmvc 类型转换器 表单数据填错后返回表单页面(接上面的 ...

  8. springmvc配置式开发下的视图解析器

    多个视图解析器优先级:

  9. Contentprovider的创建和使用流程概述

    首先在provider类中继承并实现provider的几个必要方法 -- boolean onCreate(),用来执行一些初始化的工作. -- cursor query(Uri, String[], ...

  10. js转化与排序

    1.对象转化为数组 object.keys() var obj={a:3,b:7,c:8,d:false} alert(Object.keys(obj)) 注意此函数会把对象的key转化为数组 spl ...