python 全栈开发,Day94(Promise,箭头函数,Django REST framework,生成json数据三种方式,serializers,Postman使用,外部python脚本调用

昨日内容回顾

1. 内容回顾
    1. VueX
                    VueX分三部分
    1. state         2. mutations         3. actions
    存放数据       修改数据的惟一方式        异步操做
    
    修改state中数据的步骤:
    1. 页面上交互 触发数据的变化
    2. 去后端获取新的数据(异步操做 ajax请求)
    3. dispatch('获取新数据')                                       --> 放在actions中
    4. 拿到了新数据了
    5. 去更新state中对应的数据(同步操做 state.noteList=[xx,xx,xx])--> 放在mutations中

添加新笔记
    1. 把新的笔记数据发送到后端
        dispatch('添加新笔记数据')       --> dispatch('从新拉取笔记数据')
             --> commit('大仓库添加笔记')
View Code

 

举例:css

新建一个项目mysite,修改urls.py,增长路径html

from app01 import views
urlpatterns = [
    path('admin/', admin.site.urls),
    path('index/', views.index),
    path('ajax_test/', views.ajax_test),
]
View Code

修改views.py,增长视图函数前端

from django.shortcuts import render
from django.http import JsonResponse

# Create your views here.
def index(request):
    return render(request,"index.html")

def ajax_test(request):
    return JsonResponse({"code":0})
View Code

增长index.html,注意:ajax的路径是故意写错的python

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<button id="b1">点我</button>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
<script>
    function sendAjax() {  //发送ajax请求
        $.ajax({
                url: '/ajax_123/',
                type: 'get',
                success: function (res) {
                    console.log('成功咯!');
                    console.log(res);
                },
                error:function (err) {
                    console.log('出错啦!');
                    console.log(err);
                }
            })
    };

    $('#b1').click(function () {
        var ret = sendAjax();  //执行方法
        console.log(ret);
    });
</script>
</body>
</html>
View Code

启动django项目,访问首页,点击按钮jquery

发现ret的值为undefined,执行sendAjax方法时,没法知道异步请求的状态是成功仍是失败git

 

修改成正确的url,改成ajax_testgithub

刷新页面,再次点击面试

发现ret的值仍是为undefined,为何呢?由于ajax是异步请求。ret不会等待ajax请求完毕,就直接执行下面一行,因此输出undefined。ajax

因此说,ajax不能向上面那样封装函数!若是不封装函数,代码有多是这样的sql

$.ajax({
    url: '/ajax_123/',
    type: 'get',
    success: function (res) {
       $.ajax({
            url: '/ajax_456/',
            type: 'get',
            success: function (res) {
               ...
            },
            error:function (err) {
                ...
            }
        })
    },
    error:function (err) {
        ...
    }
})
View Code

代码太冗长了,必需要封装函数。

针对不能获取值的问题,使用Promise,就能够解决!

 

1、Promise

Promise,他是一个对象,是用来处理异步操做的,可让咱们写异步调用的时候写起来更加优雅,更加美观便于阅读。顾名思义为承诺、许诺的意思,意思是使用了Promise以后他确定会给咱们答复,不管成功或者失败都会给咱们一个答复,因此咱们就不用担忧他跑了哈哈。因此,Promise有三种状态:pending(进行中),resolved(完成),rejected(失败)。只有异步返回的结构能够改变其状态。因此,promise的过程通常只有两种:pending->resolved或者pending->rejected。

promise对象还有一个比较经常使用的then方法,用来执行回调函数,then方法接受两个参数,第一个是成功的resolved的回调,另外一个是失败rejected的回调,第二个失败的回调参数可选。而且then方法里也能够返回promise对象,这样就能够链式调用了。接下来上代码:

 

修改index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<button id="b1">点我</button>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
<script>
    function sendAjax(arg) {
        return new Promise(function (resolve, reject) {
            $.ajax({
                url: arg,
                type: 'get',
                success: function (res) {
                    console.log("成功咯");
                    resolve(res)
                },
                error:function (err) {
                    console.log("出错啦");
                    reject(err)
                }
            })
        })
    };

    $('#b1').click(function () {
        //执行方法,指定url为/ajax_test/
        var ret = sendAjax('/ajax_test/');
        ret.then(function (value) {  //成功时,执行
            console.log(value);
        }).catch(function (err) {   //失败时,执行
            console.log(err)
        });
    })
</script>
</body>
</html>
View Code

上边代码中,定义了一个ret变量,而后执行sendAjax函数,函数返回一个Promise对象,而后对象里边接收一个匿名函数,分别把resolve跟reject方法当参数传进去,用ajax来模拟异步请求

当执行resolve方法后就会调用then方法的一个函数。结果以下:

这样的话,就能够指定ajax异步请求的状态是成功仍是失败。

在小程序应用中,会大量应用到Promise。

若是想往前端方向发展,有一个面试题,手写一个promise。固然不是上面的代码,而是写底层原理!

 

2、箭头函数

箭头函数就是个简写形式的函数表达式,而且它拥有词法做用域的this值(即不会新产生本身做用域下的this,arguments,super和new.target等对象)。此外,箭头函数老是匿名的。

基础语法

(param1, param2, …, paramN) => { statements }
(param1, param2, …, paramN) => expression
         // equivalent to:  => { return expression; }
 
// 若是只有一个参数,圆括号是可选的:
(singleParam) => { statements }
singleParam => { statements }
 
// 无参数的函数须要使用圆括号:
() => { statements }

each() 

each() 方法为每一个匹配元素规定要运行的函数。

提示:返回 false 可用于及早中止循环。

语法

$(selector).each(function(index,element))

 

举例:打印this

修改index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<button id="b1">点我</button><br/>
<hr>
<div>div1</div>
<div>div2</div>
<div>div3</div>

<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
<script>
    $('#b1').click(function () {
        console.log(this);  //this指的是button
        $("div").each(function () {  //循环遍历div
            console.log(this);  //this指的是div
        })
    })
</script>
</body>
</html>
View Code

刷新网页,点击按钮,查看console

注意:这2个this是不同的。上面的this是butthon,下面的this是div

 

通常请求下,若是想让$("div").each(function () {...}这里面的代码获取到button按钮,

须要在上层定义个变量_this=$(this),而后下面调用_this就能够了。

可是这样作比较麻烦,使用箭头函数,就能够解决

将匿名函数改为箭头函数

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<button id="b1">点我</button><br/>
<hr>
<div>div1</div>
<div>div2</div>
<div>div3</div>

<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
<script>
    $('#b1').click(function () {
        console.log(this);  //this指的是button
        $("div").each(()=> {  //循环遍历div
            console.log(this);
        })
    })
</script>
</body>
</html>
View Code

刷新网页,从新点击,效果以下:

总结:

想要内层的this和外层的this同样,使用箭头函数,就能够实现!将匿名函数换成箭头函数

FBV

FBV(function base views) 就是在视图里使用函数处理请求。

看代码:

views.py

def index(request):
    if request.method == "POST":
        print(request.POST)
        # 修改数据库
        return JsonResponse("OK")
    return render(request, "index.html")

def index2(request):
    if request.method == "GET":
        return render(request, "index.html")

    print(request.POST)
    # 修改数据库
    return JsonResponse("OK")
View Code

上面就是FBV的使用。

这2个视图函数,都是实现一样的功能!

那么问题来了,哪一个更好一点呢?

答案是第一种,为何呢?在咱们的现有的理念里面,只知道GET和POST。因此这2个视图函数,是没有任何区别的。

可是若是一旦上线,对于我的用户,它能够发送其余类型的,好比PUT。那么线上就会报错!

因此:对于比较重大的操做,好比修改数据库,使用if单独判断请求类型!

那么咱们推荐使用第一种方式!

若是想使用第二种方式,则须要使用if分支判断,这样更严谨一点。

def index2(request):
    if request.method == "GET":
        return render(request, "index.html")
    elif request.method == "POST":
        print(request.POST)
        # 修改数据库
        return JsonResponse("OK")
View Code

 

CBV

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

将上述代码中的views.py 修改成以下:

from django import views

class index(views.View):
    def get(self,request):
        return render(request, "index.html")

    def post(self,request):
        print(request.POST)
        # 修改数据库
        return JsonResponse("OK")
View Code

注意事项:
1. CBV定义必定要继承django.views.View
2. 注册路由的时候要写 类名.as_view()
3. 具体原理是:dispatch()方法 中 利用反射 找到 每一个请求要执行的方法

更多详细介绍,请参考连接:

http://www.javashuo.com/article/p-wvtgwopo-bg.html

 

3、Django REST framework

django-rest-framework是一个功能强大且灵活的工具包,用于构建Web API。

您可能但愿使用REST框架的一些缘由:

 

官方网址:

http://www.django-rest-framework.org/

中文文档:

https://q1mi.github.io/Django-REST-framework-documentation/

 

上面说了那么多的 RESTful API,实际上是为了引出django-rest-framework。它就是专门用来写API接口的!

通常应用是先后端分离的

前端:

APP、PC网站、手机网页、手机APP、ipad平板

后端:提供API,返回 JSON格式的数据,就能支撑前端的5种业务!

 

Web API

官方定义以下,强调两个关键点,便可以对接各类客户端(浏览器,移动设备),构建http服务的框架。

为何要用 Web API

Web API最重要的是能够构建面向各类客户端的服务。另外与WCF REST Service不一样在于,Web API利用Http协议的各个方面来表达服务(例如 URI/request response header/caching/versioning/content format),所以就省掉不少配置。

 

安装Django rest framework

pip install djangorestframework

提示如下信息,表示安装成功

Installing collected packages: djangorestframework
Successfully installed djangorestframework-3.8.2

 

4、生成json数据三种方式

准备工做

安装虚拟环境

在公司开发,通常使用虚拟环境,虚拟环境的安装,请参考连接:

http://www.javashuo.com/article/p-wvtgwopo-bg.html

安装虚拟环境以后,安装django,指定版本为1.11.11

pip安装包临时指定 从国内的清华pip源下载:

pip install django==1.11.11 -i https://pypi.tuna.tsinghua.edu.cn/simple

将虚拟环境的依赖包关系导出到requirements.txt

pip freeze > requirements.txt

注意:约定成熟使用requirements.txt,一些开源的django项目,里面通常使用这个名字!

查看requirements.txt文件,内容以下:

Django==1.11.11
pytz==2018.5

 

若是须要按照 requirements.txt 安装项目依赖的第三方包,使用命令:

pip install -r requirements.txt

新建一个虚拟环境,测试一下,就能够了!

 

新建项目about_drf

新建项目时,指定虚拟环境,使用django 1.11.11

修改models.py,增长表

from django.db import models

# Create your models here.


# 文章表
class Article(models.Model):
    title = models.CharField(max_length=32)
    # 文章发布时间
    # auto_now每次更新的时候会把当前时间保存
    create_time = models.DateField(auto_now_add=True)
    # auto_now_add 第一次建立的时候把当前时间保存
    update_time = models.DateField(auto_now=True)
    # 文章的类型
    type = models.SmallIntegerField(
        choices=((1, "原创"), (2, "转载")),
        default=1
    )
    # 来源
    school = models.ForeignKey(to='School', on_delete=models.CASCADE)
    # 标签
    tag = models.ManyToManyField(to='Tag')


# 文章来源表
class School(models.Model):
    name = models.CharField(max_length=16)


# 文章标签表
class Tag(models.Model):
    name = models.CharField(max_length=16)
View Code

说明:

SmallIntegerField 
小整数字段,相似于IntegerField,取值范围依赖于数据库特性,[-32768 ,32767]的取值范围对Django所支持的数据库都是安全的

SmallIntegerField长度是5位,IntegerField长度是10位

 

choices

用于页面上的选择框标签,须要先提供一个二维的二元元组,第一个元素表示存在数据库内真实的值,第二个表示页面上显示的具体内容。在浏览器页面上将显示第二个元素的值

 

auto_now_add和auto_now,对于一个字段而言,不能同时写,只能有一个!

on_delete=models.CASCADE 表示级联删除。也就是说,有关系的记录,会一并删除!

ManyToManyField 表示多对多,它会自动建立关系表

 

使用2个命令,生成表

python manage.py makemigrations
python manage.py migrate

使用navicat打开sqlite3数据库

 

增长表数据

执行如下sql语句

# 标签表
INSERT INTO app01_tag ("id", "name") VALUES (1, 'Python');
INSERT INTO app01_tag ("id", "name") VALUES (2, 'Django');
INSERT INTO app01_tag ("id", "name") VALUES (3, 'Vue');

# 校区表
INSERT INTO app01_school ("id", "name") VALUES (1, '北京校区');
INSERT INTO app01_school ("id", "name") VALUES (2, '上海校区');
INSERT INTO app01_school ("id", "name") VALUES (3, '深圳校区');

# 文章表
INSERT INTO app01_article ("id", "title", "create_time", "type", "school_id", "update_time") VALUES (1, 'Python三年用不上', '2018-07-31', 1, 1, '2018-07-31');
INSERT INTO app01_article ("id", "title", "create_time", "type", "school_id", "update_time") VALUES (2, '你不可能知道Vue有多简单!', '2018-07-31', 2, 2, '2018-07-31');
INSERT INTO app01_article ("id", "title", "create_time", "type", "school_id", "update_time") VALUES (3, 'MySQL一点都不难', '2018-07-31', 1, 3, '2018-07-31');

# 文章和标签关系表
INSERT INTO app01_article_tag ("id", "article_id", "tag_id") VALUES (1, 1, 1);
INSERT INTO app01_article_tag ("id", "article_id", "tag_id") VALUES (2, 1, 2);
View Code

 

json支持7种数据格式

python 原始类型向 json 类型的转化对照表:

Python JSON
dict object
list, tuple array
str, unicode string
int, long, float number
True true
False false
None null

 

 

 

 

 

 

日期转化为字符串

在项目根目录下,建立文件date_trans.py

import datetime

# 获取当前时间
now = datetime.datetime.now()
print(now, type(now))

#格式化时间,格式为年-月-日
format_time = now.strftime('%Y-%m-%d')
print(format_time, type(format_time))
View Code

执行输出:

2018-07-31 19:07:47.346727 <class 'datetime.datetime'>
2018-07-31 <class 'str'>

 

能够发现,格式化以后,数据类型为字符串

 

第一个版本:使用json

修改urls.py,增长路径

from app01 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^article_list/', views.article_list),
]
View Code

修改views.py,增长视图函数

from django.shortcuts import render,HttpResponse
from django.http import JsonResponse
from app01 import models
import json

# Create your views here.

def article_list(request):
    # 去数据库查询全部的文章数据
    query_set = models.Article.objects.all().values("id", "title", "create_time", "type", "school__name")
    # 序列化成json格式
    # 1. 先把时间对象转换成字符串格式
    for i in query_set:
        i["create_time"] = i["create_time"].strftime('%Y-%m-%d')

    data = json.dumps(list(query_set), ensure_ascii=False)
    # 返回
    return HttpResponse(data)
View Code

注意:json只支持7种数据类型,ORM查询出来的结果为QuerySet类型,它是不支持的。

日期对象也是不支持的,须要转化为字符串。

启动django项目,访问url: http://127.0.0.1:8000/article_list/

页面输出:

[{"create_time": "2018-07-31", "school__name": "北京校区", "id": 1, "type": 1, "title": "Python三年用不上"}, {"create_time": "2018-07-31", "school__name": "上海校区", "id": 2, "type": 2, "title": "你不可能知道Vue有多简单!"}, {"create_time": "2018-07-31", "school__name": "深圳校区", "id": 3, "type": 1, "title": "MySQL一点都不难"}]
View Code

每个时间,都要转换为字符串,太麻烦了。

 

第二个版本:JsonResponse

JsonResponse 对象:

class JsonResponse(data, encoder=DjangoJSONEncoder, safe=True, json_dumps_params=None,**kwargs)

这个类是HttpRespon的子类,它主要和父类的区别在于:

  • 1.它的默认Content-Type 被设置为: application/json
  • 2.第一个参数,data应该是一个字典类型,当 safe 这个参数被设置为:False ,那data能够填入任何能被转换为JSON格式的对象,好比list, tuple, set。 默认的safe 参数是 True. 若是你传入的data数据类型不是字典类型,那么它就会抛出 TypeError的异常
  • 3.json_dumps_params参数是一个字典,它将调用json.dumps()方法并将字典中的参数传入给该方法。

 

from django.shortcuts import render,HttpResponse
from django.http import JsonResponse
from app01 import models
import json

# Create your views here.

def article_list(request):
    # 去数据库查询全部的文章数据,返回queryset,每个元素都是字典
    query_set = models.Article.objects.all().values("id", "title", "create_time", "type", "school")
    print(query_set)
    for i in query_set:
        print(i)
        # 学校对象
        school_obj = models.School.objects.filter(id=i['school']).first()
        # 学校id
        id = school_obj.id
        # 学校的名字
        name = school_obj.name
        # 修改字典,key为school的值
        i["school"] = {"id": id, "name": name}

    # 返回json对象,safe=False表示填入任何能被转换为JSON格式的对象
    return JsonResponse(list(query_set), safe=False)
View Code

刷新网页,页面输出:

[{"title": "Python\u4e09\u5e74\u7528\u4e0d\u4e0a", "type": 1, "create_time": "2018-07-31", "school": {"name": "\u5317\u4eac\u6821\u533a", "id": 1}, "id": 1}, {"title": "\u4f60\u4e0d\u53ef\u80fd\u77e5\u9053Vue\u6709\u591a\u7b80\u5355\uff01", "type": 2, "create_time": "2018-07-31", "school": {"name": "\u4e0a\u6d77\u6821\u533a", "id": 2}, "id": 2}, {"title": "MySQL\u4e00\u70b9\u90fd\u4e0d\u96be", "type": 1, "create_time": "2018-07-31", "school": {"name": "\u6df1\u5733\u6821\u533a", "id": 3}, "id": 3}]
View Code

使用json格式化工具,效果以下:

它将每个数据类型作了自动转换。

 

查看JsonResponse源代码

def __init__(self, data, encoder=DjangoJSONEncoder, safe=True,
             json_dumps_params=None, **kwargs):
    if safe and not isinstance(data, dict):
        raise TypeError(
            'In order to allow non-dict objects to be serialized set the '
            'safe parameter to False.'
        )
    if json_dumps_params is None:
        json_dumps_params = {}
    kwargs.setdefault('content_type', 'application/json')
    data = json.dumps(data, cls=encoder, **json_dumps_params)
    super(JsonResponse, self).__init__(content=data, **kwargs)
View Code

看这一行,是它来处理的。注意:cls表示这个类自己

data = json.dumps(data, cls=encoder, **json_dumps_params)

 

从上面的代码中,能够看出。针对查询对应的学校信息,使用了for循环。它是一个外键字段,

那若是再查询一个外键字段呢?再来一个for循环?代码太冗长了!

 

第三个版本:serializers

下面会详细介绍

 

5、serializers

 serializer 容许复杂数据(好比 querysets 和 model 实例)转换成python数据类型,而后能够更容易的转换成 json 或 xml 等。同时,serializer也提供了反序列化功能,容许解析数据转换成复杂数据类型。

中文文档连接:

https://q1mi.github.io/Django-REST-framework-documentation/api-guide/serializers_zh/

 

声明序列化器

class DBG(serializers.Serializer):  # 声明序列化器
    id = serializers.IntegerField()
    title = serializers.CharField()
    create_time = serializers.DateField()
    type = serializers.IntegerField()
    school = serializers.CharField(source="school.name")
View Code

注意:source="school.name" 表示school表中的name字段

 

可使用它来序列化和反序列化与DBG对象相应的数据。

声明一个序列化器看起来很是像声明一个form。咱们以前学习form组件时,将须要的字段的类型都指定好了!

 

声明ModelSerializer

一般你会想要与Django模型相对应的序列化类。

ModelSerializer类可以让你自动建立一个具备模型中相应字段的Serializer类。

这个ModelSerializer类和常规的Serializer类同样,不一样的是

  • 它根据模型自动生成一组字段。
  • 它自动生成序列化器的验证器,好比unique_together验证器。
  • 它默认简单实现了.create()方法和.update()方法。

 

声明一个ModelSerializer以下:

class CYM(serializers.ModelSerializer):
    type = serializers.CharField(source='get_type_display')

    class Meta:
        model = models.Article
        fields = "__all__"  # ("id", "title", "type")
        depth = 1  # 官方推荐不超过10层
View Code

默认状况下,全部的模型的字段都将映射到序列化器上相应的字段。

模型中任何关联字段好比外键都将映射到PrimaryKeyRelatedField字段。默认状况下不包括反向关联,除非像serializer relations文档中规定的那样显示包含。

 

Model.get_FOO_display

查看官方文档

https://docs.djangoproject.com/en/dev/ref/models/instances/#django.db.models.Model.get_FOO_display

对于具备选择集的每一个字段,该对象将具备一个get_FOO_display()方法,其中FOO是该字段的名称。 此方法返回字段的“可读”值。

 

参数解释:

source='get_type_display' 表获取type字段中选择集的值。

不懂?看一下models.py中的Article表,看这一段

# 文章的类型
    type = models.SmallIntegerField(
        choices=((1, "原创"), (2, "转载")),
        default=1
    )

ORM是查询表的数据,那么这个type在真正存储时,是1或2。

可是我想要获得"原创"和"转载",怎么办?那就须要我上面提到的get_type_display。

注意:type的变量名和字段名必须保持一致,那么使用serializers后,结果集中type的值为"原创"和"转载",而不是1和2

 

model = models.Article  表示Article表

fields = "__all__"   表示全部字段,若是须要指定字段。能够写成这样fields = ("id", "title", "type")

depth = 1   表示深度为1层。有外键关联时,才须要设置depth参数

由于Article表和School表,是一对多的关系,它们之间的关系只有一层。假设说:School表和另一个表(简称B表)有关系。Article表经过School表,要去查询B表的数据,那么层数就是2,以此类推!

 

使用ModelSerializer

def article_list(request):  # 查询全部
    # 去数据库查询全部的文章数据
    query_set = models.Article.objects.all()
    xbg = CYM(query_set, many=True)
    print(xbg.data)
    # 返回
    return JsonResponse(xbg.data, safe=False)
View Code

参数解释:

many=True  表示能序列化多个对象

什么意思?article表有多条数据,每一条数据,就是一个对象。咱们须要查询表的全部记录,因此必须指定many=True。返回一条数据时,不须要指定many=True

 

获取多条数据

views.py完整代码以下:

from django.shortcuts import render,HttpResponse
from django.http import JsonResponse
from app01 import models
import json
from rest_framework import serializers

# Create your views here.

class DBG(serializers.Serializer):  # 声明序列化器
    id = serializers.IntegerField()
    title = serializers.CharField()
    create_time = serializers.DateField()
    type = serializers.IntegerField()
    school = serializers.CharField(source="school.name")


class CYM(serializers.ModelSerializer):  # 声明ModelSerializer
    #
    type = serializers.CharField(source='get_type_display')

    class Meta:
        model = models.Article
        fields = "__all__"  # ("id", "title", "type")
        depth = 1  # 官方推荐不超过10层


def article_list(request):  # 查询全部
    # 去数据库查询全部的文章数据
    query_set = models.Article.objects.all()
    xbg = CYM(query_set, many=True)
    print(xbg.data)
    # 返回
    return JsonResponse(xbg.data, safe=False)
View Code

刷新页面,将数据复制一下,使用json格式化工具,效果以下:

能够看到type的值不是数字,而是选择集中的值,它作了替换。是下面这一行,作了替换

type = serializers.CharField(source='get_type_display')

school的值,也能显示相关联的数据。

 

CYM是通用的,能够多条,也能够一条。

注意:多条的时候,须要加参数many=True。而一条,则不用!

 

获取一条数据

修改urls.py,增长一个路径

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^article_list/', views.article_list),
    url(r'article_detail/(\d+)', views.article_detail),
]
View Code

修改views.py,增长视图函数

from django.shortcuts import render,HttpResponse
from django.http import JsonResponse
from app01 import models
import json
from rest_framework import serializers

# Create your views here.

class DBG(serializers.Serializer):  # 声明序列化器
    id = serializers.IntegerField()
    title = serializers.CharField()
    create_time = serializers.DateField()
    type = serializers.IntegerField()
    school = serializers.CharField(source="school.name")


class CYM(serializers.ModelSerializer):  # 声明ModelSerializer
    #
    type = serializers.CharField(source='get_type_display')

    class Meta:
        model = models.Article
        fields = "__all__"  # ("id", "title", "type")
        depth = 1  # 官方推荐不超过10层


def article_list(request):  # 查询全部
    # 去数据库查询全部的文章数据
    query_set = models.Article.objects.all()
    xbg = CYM(query_set, many=True)
    print(xbg.data)
    # 返回
    return JsonResponse(xbg.data, safe=False)


def article_detail(request, id):  # 查询单条数据
    article_obj = models.Article.objects.filter(id=id).first()
    xcym = CYM(article_obj)
    return JsonResponse(xcym.data)
View Code

注意:使用这一行代码

from rest_framework import serializers

必需要用pip install djangorestframework  安装!!!

 

刷新页面,访问url:  http://127.0.0.1:8000/article_detail/1

使用格式化工具,效果以下:

总结:

使用ORM对象转换为json对象时,推荐使用serializers

 

6、Postman使用

Postman一款很是流行的API调试工具。不只能够调试简单的css、html、脚本等简单的网页基本信息,它还可以发送任何类型的HTTP 请求 (GET, HEAD, POST, PUT..),附带任何数量的参数+ headers。对于开发过程当中去调试接口,Postman确实足够的简单方便,并且功能强大。

官网地址:

www.getpostman.com

使用windows安装以后,打开主程序,跳过登陆

 

 访问文章列表 http://127.0.0.1:8000/article_list/

 

访问文章详情   http://127.0.0.1:8000/article_detail/1

 总结:

1. 使用Django 的视图 本身序列化
    1. HttpResponse
    2. JsonResponse
    3. serializers

2. 使用Django REST Framework 框架的序列化工具类
    1. 安装
        pip install djangorestframework
    2. 导入
        from rest_framework import serializers
    3. 使用
        class ArticleSerializer(serializers.Serializer):
            ...
View Code

 

7、外部python脚本调用django

有些状况下,咱们须要使用python脚原本调用django,从而方便使用django提供的一些指令!

调试ORM

在django项目根目录下建立文件test_orm.py,它和manage.py是同级的

import os

if __name__ == "__main__":
    # 设置django环境
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "about_drf.settings")
    import django
    django.setup()

    from app01 import models

    obj = models.Article.objects.filter(id=1).values()
    print(obj)
View Code

执行脚本,输出以下:

<QuerySet [{'title': 'Python三年用不上', 'id': 1, 'school_id': 1, 'type': 1, 'update_time': datetime.date(2018, 7, 31), 'create_time': datetime.date(2018, 7, 31)}]>

 

清理过时session

若是用户主动退出,session会自动清除,若是没有退出就一直保留,记录数愈来愈大,要定时清理没用的session。

django中已经提供了这个方法,推荐把它加入到crontab中自动清理过时的session,防止session表记录过大,影响访问速度。

python E:\python_script\django框架\day15\about_drf\manage.py clearsessions
相关文章
相关标签/搜索