python 全栈开发,Day100(restful 接口,DRF组件,DRF跨域(cors组件)) 昨日内容回顾 一、restful 接口 三、DRF跨域(cors组件)

1. 为什么要做前后端分离?
    - 前后端交给不同的人来编写,职责划分明确。方便快速开发
    - 针对pc,手机,ipad,微信,支付宝... 使用同一个接口
    
2. 简述http协议?
    - 基于socket
    - 数据格式:
        "GET /index?name=123&age=19 http1.1
host:www.luffyciti.com
content-type:application/json...

"
        
        "POST /index http1.1
host:www.luffyciti.com
content-type:application/json...

{name:'alex',age:18}"
        
        "POST /index http1.1
host:www.luffyciti.com
content-type:application/enform.....

name=alex&age=18&xx=19"
    - 无状态短链接
        一次请求一次响应之后断开连接
        
3. 简述restful 规范?
    https://www.luffycity.com/api/v1/courses/?sub_category=0
    看上面一段url,可以说出5个
    1. 使用https代替http  2.在URL中体现自己写的是API 3. 在URL中体现版本  4. 使用名词 5.参数要合理
    之后,请求方式,响应信息。可以说后面5个
    6. 根据请求方式不同,处理不同的操作 7.
    
    
4. django rest framework组件的作用?
    - 快速实现restful 规范
        
5. 列举django rest framework组件(10)?
    
6. 路飞的表结构
View Code

一、restful 接口

根据昨天代码,继续编写。

或者下载代码:

https://github.com/987334176/luffycity/archive/v1.2.zip

注意:删除api目录下的views.py文件,它没有用了

下载数据库使用:

https://github.com/987334176/luffycity/blob/master/db.sqlite3

第一种方式

修改api_urls.py

from django.conf.urls import url
from api.views import course,degreecourse

urlpatterns = [
    # url(r'login/$', views.LoginView.as_view()),
    url(r'courses/$',course.CoursesView.as_view()),
    url(r'courses/(?P<pk>d+)/$',course.CourseDetailView.as_view()),

    url(r'degreecourse/$',degreecourse.DegreeCourseView.as_view()),
    url(r'degreecourse/teachers/$',degreecourse.DegreeCourseTeachersView.as_view()),
    url(r'degreecourse/scholarship/$',degreecourse.DegreeCourseScholarshipView.as_view()),

]
View Code

修改views目录下的course.py

from rest_framework.views import APIView
from rest_framework.response import Response

from api import models
from api.serializers.course import CourseModelSerializer

from api.utils.response import BaseResponse
from api.utils.serialization_general import SerializedData


class CoursesView(APIView):

    def get(self, request, *args, **kwargs):
        """
        查询所有
        :param request:
        :param args:
        :param kwargs:
        :return:
        """
        queryset = models.Course.objects.all()
        serializer_class = CourseModelSerializer
        data = SerializedData(request, queryset, serializer_class).get_data()
        return Response(data)

    def post(self, request, *args, **kwargs):
        """
        增加一条
        :param request:
        :param args:
        :param kwargs:
        :return:
        """

class CourseDetailView(APIView):
    def get(self, request, pk,*args, **kwargs):
        """
        查询单个
        :param request:
        :param pk:
        :param args:
        :param kwargs:
        :return:
        """
    def put(self, request, pk,*args, **kwargs):
        """
        修改单个
        :param request:
        :param pk:
        :param args:
        :param kwargs:
        :return:
        """
    def delete(self, request, pk,*args, **kwargs):
        """
        删除单个
        :param request:
        :param pk:
        :param args:
        :param kwargs:
        :return:
        """
View Code

上面的方式,更趋近于原始

第二种方式(推荐)

django-rst-framework为我们提供了ViewSet类, ViewSet为我们提供了默认的URL结构, 使得我们能更专注于API本身. ViewSet类与View类几乎是相同的, 但提供的是read或update, 而不是http动作get或put.

ViewSet类在实例化后, 通过Router类, 最终将URL与ViewSet方法绑定

ViewSet类的父类ViewSetMixin,其实重写了as_view方法

@classonlymethod
    def as_view(cls, actions=None, **initkwargs):
        """
        Because of the way class based views create a closure around the
        instantiated view, we need to totally reimplement `.as_view`,
        and slightly modify the view function that is created and returned.
        """
        ...

那么url方式也发生了变化

修改api_urls.py

from django.conf.urls import url
from api.views import course

urlpatterns = [
    url(r'courses/$', course.CoursesView.as_view({'get': 'list', 'post': 'create'})),
    url(r'courses/(?P<pk>d+)/$', course.CoursesView.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'}))
]
View Code

解释:看这一段{'get':'list','post':'create'}

它表示get请求时,转发到list方法。post请求转发到create方法。

这里面定义的方法名,都是约定俗成的。推荐使用这些名字!也可以自定义。

修改views目录下的course.py

from rest_framework.views import APIView
from rest_framework.viewsets import ViewSetMixin
from rest_framework.response import Response

from api import models
from api.serializers.course import CourseModelSerializer

from api.utils.response import BaseResponse
from api.utils.serialization_general import SerializedData


class CoursesView(ViewSetMixin,APIView):

    def list(self, request, *args, **kwargs):
        """
        查询所有
        :param request:
        :param args:
        :param kwargs:
        :return:
        """
        queryset = models.Course.objects.all()
        serializer_class = CourseModelSerializer
        data = SerializedData(request, queryset, serializer_class).get_data()
        return Response(data)

    def create(self, request, *args, **kwargs):
        """
        增加一条
        :param request:
        :param args:
        :param kwargs:
        :return:
        """

class CourseDetailView(APIView):
    def retrieve(self, request, pk,*args, **kwargs):
        """
        查询单个
        :param request:
        :param pk:
        :param args:
        :param kwargs:
        :return:
        """
    def update(self, request, pk,*args, **kwargs):
        """
        修改单个
        :param request:
        :param pk:
        :param args:
        :param kwargs:
        :return:
        """
    def destroy(self, request, pk,*args, **kwargs):
        """
        删除单个
        :param request:
        :param pk:
        :param args:
        :param kwargs:
        :return:
        """
View Code

以上方式适用于:用户请求处理时业务逻辑复杂的情况。

注意:如果继承了GenericViewSet,并且返回序列化数据使用了Response

必须要定义queryset属性,否则报错

python 全栈开发,Day100(restful 接口,DRF组件,DRF跨域(cors组件))
昨日内容回顾
一、restful 接口
三、DRF跨域(cors组件)

看源码

 python 全栈开发,Day100(restful 接口,DRF组件,DRF跨域(cors组件))
昨日内容回顾
一、restful 接口
三、DRF跨域(cors组件)

必须要定义queryset变量,否则执行assert(断言)。

还有一种解决方式,使用JSONRenderer。它也可以返回json数据,但是没有像Response那样,有好看的页面!

三、DRF跨域(cors组件)

运行的vue项目,发现出现跨域

python 全栈开发,Day100(restful 接口,DRF组件,DRF跨域(cors组件))
昨日内容回顾
一、restful 接口
三、DRF跨域(cors组件)

查看Pycharm控制台输出:

[18/Aug/2018 20:14:31] "GET /api/v1/courses/ HTTP/1.1" 200 212

可以发现,请求实际已经到达了后端。并且做了正确的返回,但是浏览器拒绝接收!

这为什么呢?这是因为浏览器的同源策略

python 全栈开发,Day100(restful 接口,DRF组件,DRF跨域(cors组件))
昨日内容回顾
一、restful 接口
三、DRF跨域(cors组件)

1.什么是同源策略

同源: 页面地址拥有相同的协议,域名,以及端口号。
 
同源策略: 页面A中的脚本不能访问不同源的页面B的cookie、localStorage以及IndexDB,也不能获取页面B的DOM信息, 另外在使用AJAX时也会受到相关限制。

2.同源策略的目的

主要是出于安全方面的考虑。现在的网页都用cookie来进行身份验证,如果不限制读取,网页B里的恶意脚本代码可以随意模仿真实用户进行操作。

关于更多的同源策略信息,请参考链接:

http://www.ruanyifeng.com/blog/2016/04/same-origin-policy.html

总结:

浏览器具有同源策略,打开某个网站后,通过ajax向另外一个网站发送http请求时候,数据回来时会被浏览器阻止(跨域)

解决跨域

方式一

在api端设置响应头 CORS

修改views目录下的course.py,增加响应头

from rest_framework.views import APIView
from rest_framework.viewsets import ViewSetMixin
from rest_framework.response import Response

from api import models
from api.serializers.course import CourseModelSerializer

from api.utils.response import BaseResponse
from api.utils.serialization_general import SerializedData


class CoursesView(ViewSetMixin,APIView):

    def list(self, request, *args, **kwargs):
        """
        查询所有
        :param request:
        :param args:
        :param kwargs:
        :return:
        """
        queryset = models.Course.objects.all()
        serializer_class = CourseModelSerializer
        data = SerializedData(request, queryset, serializer_class).get_data()
        # 增加响应头,http://localhost:8080表示前端的地址
        return Response(data,headers={'Access-Control-Allow-Origin': 'http://localhost:8080'})

    def create(self, request, *args, **kwargs):
        """
        增加一条
        :param request:
        :param args:
        :param kwargs:
        :return:
        """

class CourseDetailView(APIView):
    def retrieve(self, request, pk,*args, **kwargs):
        """
        查询单个
        :param request:
        :param pk:
        :param args:
        :param kwargs:
        :return:
        """
    def update(self, request, pk,*args, **kwargs):
        """
        修改单个
        :param request:
        :param pk:
        :param args:
        :param kwargs:
        :return:
        """
    def destroy(self, request, pk,*args, **kwargs):
        """
        删除单个
        :param request:
        :param pk:
        :param args:
        :param kwargs:
        :return:
        """
View Code

Access-Control-Allow-Origin字段,表示http://localhost:8080可以请求数据。该字段也可以设为星号,表示同意任意跨源请求

客户端浏览器检查自己的域是否在允许列表中,决定是否处理响应

刷新vue页面,发现没有报错了。说明接收了数据!

python 全栈开发,Day100(restful 接口,DRF组件,DRF跨域(cors组件))
昨日内容回顾
一、restful 接口
三、DRF跨域(cors组件)

上面是简单请求

简单请求 OR 非简单请求

条件:

1、请求方式:HEAD、GET、POST
2、请求头信息:
    Accept
    Accept-Language
    Content-Language
    Last-Event-ID
    Content-Type 对应的值是以下三个中的任意一个
        application/x-www-form-urlencoded
        multipart/form-data
        text/plain

注意:同时满足以上两个条件时,则是简单请求,否则为复杂请求

简单请求和非简单请求的区别

简单请求:一次请求
非简单请求:两次请求,在发送数据之前会先发一次请求用于做“预检”,只有“预检”通过后才再发送一次请求用

关于"预检"

- 请求方式:OPTIONS
- "预检"其实做检查,检查如果通过则允许传输数据,检查不通过则不再发送真正想要发送的消息
- 如何"预检"
     => 如果复杂请求是PUT等请求,则服务端需要设置允许某请求,否则"预检"不通过
        Access-Control-Request-Method
     => 如果复杂请求设置了请求头,则服务端需要设置允许某请求头,否则"预检"不通过
        Access-Control-Request-Headers        text/plain

数据展示

修改settings.py,将分页改成20

REST_FRAMEWORK = {
    'DEFAULT_VERSIONING_CLASS':'rest_framework.versioning.URLPathVersioning',
    'VERSION_PARAM':'version',
    'DEFAULT_VERSION':'v1',
    'ALLOWED_VERSIONS':['v1','v2'],
    'PAGE_SIZE':20,
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
}
View Code

修改vue项目的HelloWorld.vue

<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    <h1>课程列表</h1>
    <ul v-for="item in courseList">
      <li>{{item.name}}</li>
    </ul>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      msg: '欢迎使用路飞学城',
      courseList:[],
    }
  },
  mounted(){  //页面加载完成后
    this.initCourse();  //执行此方法
  },
  methods:{
    initCourse:function () {
      let that = this
      //向后台发送ajax请求
      this.$axios.request({
        url:'http://127.0.0.1:8000/api/v1/courses/',
        method:'GET',
        responseType:'json',
      }).then(function (arg) {
        //成功之后
        console.log(arg);
        if (arg.data.code == 1000){
          //更新数据
          that.courseList = arg.data.data;
        }else {
          //弹出错误
          alert(arg.data.error);
        }

      }).catch(function (err) {
        //发生错误
        console.log(err);
      })
    }
  },
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1, h2 {
  font-weight: normal;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
</style>
View Code

刷新网页,效果如下:

python 全栈开发,Day100(restful 接口,DRF组件,DRF跨域(cors组件))
昨日内容回顾
一、restful 接口
三、DRF跨域(cors组件)

第二种

使用自定义中间件

修改views目录下的course.py,去掉headers

    def list(self, request, *args, **kwargs):
        """
        查询所有
        :param request:
        :param args:
        :param kwargs:
        :return:
        """
        queryset = models.Course.objects.all()
        serializer_class = CourseModelSerializer
        data = SerializedData(request, queryset, serializer_class).get_data()
        return Response(data)
View Code

在api目录下创建md文件夹,在里面创建cors.py

from django.utils.deprecation import MiddlewareMixin
from django.conf import settings

class CorsMiddleware(MiddlewareMixin):

    def process_response(self,request,response):
        # 设置响应头
        response['Access-Control-Allow-Origin'] = 'http://localhost:8080'
       
        return response
View Code

修改settings.py,注册自定义中间件

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'api.md.cors.CorsMiddleware',
]
View Code

刷新vue页面,效果同上!

模拟复杂请求

修改HelloWorld.vue,增加登录按钮。发送固定的用户名和密码,指定数据格式为json

<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    <button v-on:click="doLogin">登录</button>
    <h1>课程列表</h1>
    <ul v-for="item in courseList">
      <li>{{item.name}}</li>
    </ul>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      msg: '欢迎使用路飞学城',
      courseList:[],
    }
  },
  mounted(){  //页面加载完成后
    this.initCourse();  //执行此方法
  },
  methods:{
    initCourse:function () {
      let that = this
      //向后台发送ajax请求
      this.$axios.request({
        url:'http://127.0.0.1:8000/api/v1/courses/',
        method:'GET',
        responseType:'json',
      }).then(function (arg) {
        //成功之后
        console.log(arg);
        if (arg.data.code == 1000){
          //更新数据
          that.courseList = arg.data.data;
        }else {
          //弹出错误
          alert(arg.data.error);
        }

      }).catch(function (err) {
        //发生错误
        console.log(err);
      })
    },
    doLogin(){
      this.$axios.request({
        url:'http://127.0.0.1:8000/api/v1/auth/',
        method:'POST',
        data:{
          //用户名和密码
          user:'xiao',
          pwd:'123',
        },
        //增加headers头
        headers:{
          //指定数据格式
          'Content-Type':'application/json',
        },
        //响应格式为json
        responseType:'json',
      }).then(function (arg) {
        //成功之后
        console.log(arg);
      }).catch(function (err) {
        //发生错误
        console.log(err);
      })
    }
  },
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1, h2 {
  font-weight: normal;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
</style>
View Code

修改api_urls.py,增加路径

from django.conf.urls import url
from api.views import course,auth

urlpatterns = [
    url(r'auth/$', auth.AuthView.as_view({'post': 'login'})),
    url(r'courses/$', course.CoursesView.as_view({'get': 'list', 'post': 'create'})),
    url(r'courses/(?P<pk>d+)/$', course.CoursesView.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'}))
]
View Code

在views目录下,创建文件auth.py

from rest_framework.views import APIView
from rest_framework.viewsets import ViewSetMixin
from rest_framework.response import Response

from api import models
from api.serializers.course import CourseModelSerializer

from api.utils.response import BaseResponse
from api.utils.serialization_general import SerializedData


class AuthView(ViewSetMixin,APIView):
    def login(self, request, *args, **kwargs):
        print('用户发了POST请求了',request)
        return Response({'code':'ok'})
View Code

刷新vue页面,点击登录

查看Console,提示对方不允许

python 全栈开发,Day100(restful 接口,DRF组件,DRF跨域(cors组件))
昨日内容回顾
一、restful 接口
三、DRF跨域(cors组件)

查看Network,它是一个OPTIONS请求

python 全栈开发,Day100(restful 接口,DRF组件,DRF跨域(cors组件))
昨日内容回顾
一、restful 接口
三、DRF跨域(cors组件)

查看Pycharm控制台输出:

[18/Aug/2018 21:37:04] "OPTIONS /api/v1/auth/ HTTP/1.1" 200 163

通过以上信息,可以看出。浏览器发送OPTIONS请求,也就是在预检。但是后端没有同意,所以浏览器没有发送POST请求。

怎么才能让它通过预检呢?

修改md目录下的cors,做一个if判断,允许一下!

from django.utils.deprecation import MiddlewareMixin
from django.conf import settings

class CorsMiddleware(MiddlewareMixin):

    def process_response(self,request,response):
        # 设置响应头
        response['Access-Control-Allow-Origin'] = 'http://localhost:8080'
        # 当为OPTIONS时
        if request.method == "OPTIONS":
            # 允许通过的请求方式
            response["Access-Control-Allow-Methods"] = "POST,PUT,DELETE"
            # 允许通过的请求头
            response["Access-Control-Allow-Headers"] = "Content-Type"
            
        return response
View Code

刷新页面,再次点击登录

查看Console,发现请求正常

python 全栈开发,Day100(restful 接口,DRF组件,DRF跨域(cors组件))
昨日内容回顾
一、restful 接口
三、DRF跨域(cors组件)

查看Network,发现有2次请求

python 全栈开发,Day100(restful 接口,DRF组件,DRF跨域(cors组件))
昨日内容回顾
一、restful 接口
三、DRF跨域(cors组件)

查看第一个请求,它是OPTIONS请求方式python 全栈开发,Day100(restful 接口,DRF组件,DRF跨域(cors组件))
昨日内容回顾
一、restful 接口
三、DRF跨域(cors组件)

查看第二个请求,它是POST请求方式

python 全栈开发,Day100(restful 接口,DRF组件,DRF跨域(cors组件))
昨日内容回顾
一、restful 接口
三、DRF跨域(cors组件)

查看Pycharm控制台输出:

[18/Aug/2018 21:43:24] "GET /api/v1/courses/ HTTP/1.1" 200 394
[18/Aug/2018 21:43:32] "OPTIONS /api/v1/auth/ HTTP/1.1" 200 163
用户发了POST请求了 <rest_framework.request.Request object at 0x0000024630CD85C0>
[18/Aug/2018 21:43:32] "POST /api/v1/auth/ HTTP/1.1" 200 13

通过以上信息,可以看到。数据接收正常!

通过这样,无论是简单,还是复杂,都允许。

django cors组件

CORS,全称为跨域资源共享。它允许 Web 应用服务器进行跨域访问控制,从而使跨域数据传输得以安全进行。

上面的cors.py,帮我们实现了cors。这个手写的,但是官方提供了cors组件,专门用来解决跨域问题的!

1.安装django-cors-headers

pip install django-cors-headers

2.配置settings.py文件

INSTALLED_APPS = [
    ...
    'corsheaders',  # 注册应用cors
 ] 

MIDDLEWARE_CLASSES = (
    ...
    'corsheaders.middleware.CorsMiddleware', # 注册组件cors

)
#跨域增加忽略
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_ALLOW_ALL = True
CORS_ORIGIN_WHITELIST = (
    '*'
)

CORS_ALLOW_METHODS = (
    'DELETE',
    'GET',
    'OPTIONS',
    'PATCH',
    'POST',
    'PUT',
    'VIEW',
)

CORS_ALLOW_HEADERS = (
    'XMLHttpRequest',
    'X_FILENAME',
    'accept-encoding',
    'authorization',
    'content-type',
    'dnt',
    'origin',
    'user-agent',
    'x-csrftoken',
    'x-requested-with',
    'Pragma',
)
View Code

注释掉自定义组件,settings.py完整代码如下:

"""
Django settings for s11luffycity project.

Generated by 'django-admin startproject' using Django 1.11.

For more information on this file, see
https://docs.djangoproject.com/en/1.11/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.11/ref/settings/
"""

import os

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '-i@r%a=tf*0n6!kzd=m#gx9g82i7@!x=n9jx=jta&(7%zw67#!'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'api.apps.ApiConfig',
    'rest_framework',
    'corsheaders',  # 注册应用cors
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    # 'api.md.cors.CorsMiddleware',
    'corsheaders.middleware.CorsMiddleware',  # 注册组件cors
]

ROOT_URLCONF = 's11luffycity.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')]
        ,
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 's11luffycity.wsgi.application'


# Database
# https://docs.djangoproject.com/en/1.11/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}


# Password validation
# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/1.11/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.11/howto/static-files/

STATIC_URL = '/static/'
REST_FRAMEWORK = {
    'DEFAULT_VERSIONING_CLASS':'rest_framework.versioning.URLPathVersioning',
    'VERSION_PARAM':'version',
    'DEFAULT_VERSION':'v1',
    'ALLOWED_VERSIONS':['v1','v2'],
    'PAGE_SIZE':20,
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
}

#跨域增加忽略
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_ALLOW_ALL = True
CORS_ORIGIN_WHITELIST = (
    '*'
)

CORS_ALLOW_METHODS = (
    'DELETE',
    'GET',
    'OPTIONS',
    'PATCH',
    'POST',
    'PUT',
    'VIEW',
)

CORS_ALLOW_HEADERS = (
    'XMLHttpRequest',
    'X_FILENAME',
    'accept-encoding',
    'authorization',
    'content-type',
    'dnt',
    'origin',
    'user-agent',
    'x-csrftoken',
    'x-requested-with',
    'Pragma',
)
View Code

重启django项目,刷新页面,重启登录。效果同上!

OK!问题解决!

本文参考:

https://blog.****.net/apple9005/article/details/54427902