• 斑马斑马-20-Django REST Framework (DRF)系列教程


    一、RESTful

    REST全称是Representational State Transfer,中文意思是表述(编者注:通常译为表征)性状态转移。一种软件设计风格

    1、RESTful API设计

    • 协议
      •   API与用户的通信协议,总是使用HTTPs协议
    • 域名
      •   尽量将API部署在专用域名之下 https://api.example.com
      •        也可以放在主域名之下  https://example.org/api
    • 版本
      •   将url版本号放入到url中 https://exmaple.com/v1/
    • 路径
      •   只能有名词,不能有动词 https://exmaple.com/v1/zoos
    • method
      •   GET(SELECT)  获取资源(一项、多项)
      •        POST (CREATE) 创建
      •        PUT(UPDATE)       在更新资源
      •        DELETE(DELETE) 删除资源
      •        PATCH(UPDATE)   更新资源(提供改变的属性)
      •        HEAD                          获取资源的元数据
      •        OPTIONS                    获取信息,关于资源的哪些属性是客户端可以改变的
    • 过滤
      •   ?limit=10:指定返回记录数量
      •        ?offset=10:偏移查询
      •        ?sortby=name:排序字段
    • 状态
      •   200 成功
      •        201 创建成功
      •        204 删除成功
      •        401 没有权限
      •   403 没有授权
      •        404 没有找到
      •        500 服务器内部错误
    • 错误处理
      •   {
      •              error:"错误信息"
      •        }
    • 返回结果
      •   json  

    2、RESTful API案例

    功能
    请求方式
    请求路径
    获取所有书籍
    GET
    /books
    创建单本书籍
    POST
    /books
    获取单本书籍
    GET
    /books/{pk}
    修改单本书籍
    PUT
    /books/{pk}
    删除单本书籍
    DELETE
    /books/{pk}

    3、创建Django项目

       1:使用MySQL数据库首先需要安装驱动程序    

    pip install PyMySQL
    

      2:在Django的工程同名子目录的__init__.py文件中添加如下语句  

    from pymysql import install_as_MySQLdb
    install_as_MySQLdb()
    

      3:配置setting中的DATABASES配置信息

    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'HOST': '39.99.213.203',  # 数据库主机
            'PORT': 3306,  # 数据库端口
            'USER': 'root',  # 数据库用户名
            'PASSWORD': 'mysql',  # 数据库用户密码
            'NAME': 'django_demo'  # 数据库名字
        }
    }
    setting数据库配置

      4:在MySQL中创建数据库

    create database django_demo default charset=utf8;
    

      5:创建应用booktest,在models.py 文件中定义模型类。

    from django.db import models
    
    #定义图书模型类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='逻辑删除')
    
        class Meta:
            db_table = 'tb_books'  # 指明数据库表名
            verbose_name = '图书'  # 在admin站点中显示的名称
            verbose_name_plural = verbose_name  # 显示的复数名称
    
        def __str__(self):
            """定义每个数据对象的显示信息"""
            return self.btitle
    
    #定义英雄模型类HeroInfo
    class HeroInfo(models.Model):
        GENDER_CHOICES = (
            (0, 'female'),
            (1, 'male')
        )
        hname = models.CharField(max_length=20, verbose_name='名称') 
        hgender = models.SmallIntegerField(choices=GENDER_CHOICES, default=0, verbose_name='性别')  
        hcomment = models.CharField(max_length=200, null=True, verbose_name='描述信息') 
        hbook = models.ForeignKey(BookInfo, on_delete=models.CASCADE, verbose_name='图书')  # 外键
        is_delete = models.BooleanField(default=False, verbose_name='逻辑删除')
    
        class Meta:
            db_table = 'tb_heros'
            verbose_name = '英雄'
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return self.hname
    定义模型类

      6:生成数据库  

      python manage.py makemigrations  

      python manage.py migrate

      ps:如果报django.core.exceptions.ImproperlyConfigured: mysqlclient 1.3.13 or newer is required; you have 0.9.3.错误

    在Django的工程同名子目录的__init__.py文件中添加如下语句

    from pymysql import install_as_MySQLdb
    import pymysql
    pymysql.version_info = (1, 3, 13, "final", 0)
    pymysql.install_as_MySQLdb()
    __init__.py

       7:初始化数据

    insert into tb_books(btitle,bpub_date,bread,bcomment,is_delete) values
    ('射雕英雄传','1980-5-1',12,34,0),
    ('天龙八部','1986-7-24',36,40,0),
    ('笑傲江湖','1995-12-24',20,80,0),
    ('雪山飞狐','1987-11-11',58,24,0);
    insert into tb_heros(hname,hgender,hbook_id,hcomment,is_delete) values
    ('郭靖',1,1,'降龙十八掌',0),
    ('黄蓉',0,1,'打狗棍法',0),
    ('黄药师',1,1,'弹指神通',0),
    ('欧阳锋',1,1,'蛤蟆功',0),
    ('梅超风',0,1,'九阴白骨爪',0),
    ('乔峰',1,2,'降龙十八掌',0),
    ('段誉',1,2,'六脉神剑',0),
    ('虚竹',1,2,'天山六阳掌',0),
    ('王语嫣',0,2,'神仙姐姐',0),
    ('令狐冲',1,3,'独孤九剑',0),
    ('任盈盈',0,3,'弹琴',0),
    ('岳不群',1,3,'华山剑法',0),
    ('东方不败',0,3,'葵花宝典',0),
    ('胡斐',1,4,'胡家刀法',0),
    ('苗若兰',0,4,'黄衣',0),
    ('程灵素',0,4,'医术',0),
    ('袁紫衣',0,4,'六合拳',0);
    View Code

    二、功能实现 

    1、利用CBV模式实现

      CBV(class base views) 就是在视图里使用类处理请求。

      1.1 项目同名的App路由中进行全局配置  

    from django.contrib import admin
    from django.urls import path
    from django.conf.urls import url,include
    from APP01 import url as app01_books_url
    
    
    urlpatterns = [
        url(r'^api/yango/v1/books/',include(app01_books_url))
    ]
    url.py
    api:表示接口
    yango:表示项目名
    v1:表示版本号
    books:表示资源类
    这时候会进一步进入到APP01下的url中
    from django.conf.urls import url
    from . import views
    urlpatterns=[
        url(r'^info$',views.BookesAPIView.as_view()),
    ]
    View Code

    资源明细内容

    info 表示获取所有

      1.2 获取所有书籍

    from django.shortcuts import render
    from django.views import View
    from .models import BookInfo
    from datetime import datetime
    from django.http import JsonResponse
    '''
    功能            请求方式    请求路径    
    获取所有书籍    GET         /books
    创建单本书籍    POST        /books
    获取单本书籍    GET         /books/{pk}
    修改单本书籍    PUT         /books/{pk}
    删除单本书籍    DELETE      /books/{pk}
    '''
    
    
    #1,列表视图
    class BookesAPIView(View):
        '''
        查询所有屠苏,增加图书
        '''
        def get(self,request):
            queryset=BookInfo.objects.all()
            book_list=[]
            for book in queryset:
                book_list.append({
                    "id":book.id,
                    "btitle":book.btitle,
                    "bpub_date":book.bpub_date,
                    "bread":book.bread,
                    "bcomment":book.bcomment
                })
            return JsonResponse(book_list,safe=False)
    View Code

      BookesAPIView中get方法,获取所有书籍数据

      

      1.3 完整版视图

    from django.shortcuts import render, HttpResponse
    from django.views import View
    from .models import BookInfo
    from datetime import datetime
    from django.http import JsonResponse
    import json
    
    '''
    功能            请求方式    请求路径    
    获取所有书籍    GET         /books
    创建单本书籍    POST        /books
    获取单本书籍    GET         /books/{pk}
    修改单本书籍    PUT         /books/{pk}
    删除单本书籍    DELETE      /books/{pk}
    '''
    
    
    # 1,列表视图
    class BooksAPIView(View):
        '''
        查询所有屠苏,增加图书
        '''
    
        def get(self, request):
            """
            查询所有图书
            路由:GET /books/info/
            """
            queryset = BookInfo.objects.all()
            book_list = []
            for book in queryset:
                book_list.append({
                    "id": book.id,
                    "btitle": book.btitle,
                    "bpub_date": book.bpub_date,
                    "bread": book.bread,
                    "bcomment": book.bcomment
                })
            return JsonResponse(book_list, safe=False)
    
        def post(self, request):
            """
            新增图书
            路由:POST /books/info/
            """
            json_bytes = request.body
            json_str = json_bytes.decode()
            book_dict = json.loads(json_str, encoding="utf-8")
    
            # 此处详细的校验参数省略
    
            book = BookInfo.objects.create(
                btitle=book_dict.get('btitle'),
                bpub_date=datetime.strptime(book_dict.get('bpub_date'), '%Y-%m-%d').date()
            )
    
            return JsonResponse({
                "id": book.id,
                "btitle": book.btitle,
                "bpub_date": book.bpub_date,
                "bread": book.bread,
                "bcomment": book.bcomment
            }, status=201)
    
    
    class BookAPIView(View):
        '''
        查询所有屠苏,增加图书
        '''
    
        def get(self, request, pk):
            """
            根据图书ID查询图书
            路由:GET /books/info/pk/
            """
            try:
                book = BookInfo.objects.get(id=pk)
            except BookInfo.DoesNotExist:
                return HttpResponse(status=404)
    
            return JsonResponse({
                "id": book.id,
                "btitle": book.btitle,
                "bpub_date": book.bpub_date,
                "bread": book.bread,
                "bcomment": book.bcomment
            }, status=201)
    
        def put(self, request, pk):
            """
            根据图书ID修改图书
            路由:PUT /books/info/pk/
            """
            try:
                book = BookInfo.objects.get(id=pk)
            except BookInfo.DoesNotExist:
                return HttpResponse(status=404)
            json_bytes = request.body
            json_str = json_bytes.decode()
            book_dict = json.loads(json_str)
    
            book.btitle = book_dict.get("btitle")
            book.save()
    
            return JsonResponse({
                "id": book.id,
                "btitle": book.btitle,
                "bpub_date": book.bpub_date,
                "bread": book.bread,
                "bcomment": book.bcomment
            })
    
        def delete(self, request, pk):
            """
            根据图书ID删除图书
            路由:DELETE /books/info/pk/
            """
            try:
                book = BookInfo.objects.get(id=pk)
            except BookInfo.DoesNotExist:
                return HttpResponse(status=404)
            book.delete()
            return JsonResponse({
                "id": book.id,
                "btitle": book.btitle,
                "bpub_date": book.bpub_date,
                "bread": book.bread,
                "bcomment": book.bcomment
            }, status=204)
    view.py

      1.4 测试(Postman) 

    1)获取所有图书数据 http://127.0.0.1:8000/api/yango/v1/books/info

    [
        {
            "id": 1,
            "btitle": "射雕英雄传",
            "bpub_date": "1980-05-01",
            "bread": 12,
            "bcomment": 34
        },
        {
            "id": 2,
            "btitle": "天龙八部",
            "bpub_date": "1986-07-24",
            "bread": 36,
            "bcomment": 40
        },
        {
            "id": 3,
            "btitle": "笑傲江湖",
            "bpub_date": "1995-12-24",
            "bread": 20,
            "bcomment": 80
        },
        {
            "id": 4,
            "btitle": "雪山飞狐",
            "bpub_date": "1987-11-11",
            "bread": 58,
            "bcomment": 24
        },
        {
            "id": 5,
            "btitle": "白马啸西风",
            "bpub_date": "2020-02-02",
            "bread": 0,
            "bcomment": 0
        },
        {
            "id": 7,
            "btitle": "连城诀",
            "bpub_date": "2020-02-02",
            "bread": 0,
            "bcomment": 0
        }
    ]
    返回结果

    2)获取单一图书数据 http://127.0.0.1:8000/api/yango/v1/books/info/1

    {
        "id": 1,
        "btitle": "射雕英雄传",
        "bpub_date": "1980-05-01",
        "bread": 12,
        "bcomment": 34
    }
    返回结果

    3)新增图书数据 http://127.0.0.1:8000/api/yango/v1/books/info

    {
        "btitle":"连城诀",
        "bpub_date":"2020-02-02"
    }
    请求数据
    {
        "id": 7,
        "btitle": "连城诀",
        "bpub_date": "2020-02-02",
        "bread": 0,
        "bcomment": 0
    }
    返回结果

    4)修改图书数据 http://127.0.0.1:8000/api/yango/v1/books/info/6/

    {
        "btitle":"白马啸西风1"
    }
    请求数据
    {
        "id": 6,
        "btitle": "白马啸西风1",
        "bpub_date": "2020-02-02",
        "bread": 0,
        "bcomment": 0
    }
    返回结果

    5)删除图书数据 http://127.0.0.1:8000/api/yango/v1/books/info/6/

    {
        "id": null,
        "btitle": "白马啸西风1",
        "bpub_date": "2020-02-02",
        "bread": 0,
        "bcomment": 0
    }
    返回结果

    三、代码上传 

    可参考  集腋成裘-21-git使用-03进阶篇   2.4 多人开发

  • 相关阅读:
    Dev C++ 工程没有调试信息 解决办法
    写一个函数,输入一个二叉树,树中每个节点存放了一个整数值,函数返回这棵二叉树中相差最大的两个节点间的差值绝对值。请注意程序效率。
    oracle10g登录em后,提示“java.lang.Exception: Exception in sending Request :: null”
    网站登录的破解
    sql 日志恢复
    Oracle expdp/impdp 使用示例
    Oracle数据库备份和恢复的基本命令
    检索 COM 类工厂中 CLSID 为 {{10020200-E260-11CF-AE68-00AA004A34D5}} 的组件时失败解决办法
    win7访问部分win2003速度慢
    公交车路线查询系统后台数据库设计--换乘算法改进与优化
  • 原文地址:https://www.cnblogs.com/YK2012/p/13227046.html
Copyright © 2020-2023  润新知