luffy02

文章目录

  • 昨日回顾
  • 今日内容
    • 一、luffy前台配置
      • 1.1 axios前后台交互
        • 安装:前端项目目录下的终端
        • 配置:main.js
      • 1.2 cookies操作
        • 安装:前端项目目录下的终端
        • 配置:main.js
      • 1.3 element-ui页面组件框架
        • 安装:前端项目目录下的终端
        • 配置:main.js
      • 1.4 bootstrap页面组件框架
        • 安装:前端项目目录下的终端
        • 配置jquery:vue.config.js
        • 配置bootstrap:main.js
    • 二、user模块User表
      • 2.1 创建user模块
      • 2.2 创建User表对应的model:user/models.py
      • 2.3 注册user模块,配置User表:dev.py
      • 2.4 配置media
        • media配置:dev.py
        • media目录配置
        • 主路由:luffyapi/urls.py
        • 子路由:user/urls.py
      • 2.5 数据库迁移
    • 三、封装全局Response对象和全局异常
      • 3.1 环境变量
        • dev.py
        • 在写项目直接导入utils文件夹也不’’错误提示’’
      • 3.2 封装logger
        • dev.py
        • utils/logging.py
      • 3.3 封装项目异常处理
        • utils/exception.py
        • settings.py
      • 3.4 二次封装Response模块
        • utils/response.py
      • 3.5 路由组件配置
        • utils/router.py
    • 四、跨域请求
      • 4.1 同源策略
      • 4.2 CORS(跨域资源共享)简介
      • 4.3 CORS基本流程
      • 4.4 CORS两种请求详解
      • 4.5 Django项目中支持CORS
      • 4.6 django 使用django-cors-headers 解决跨域问题
        • 1、使用pip安装
        • 2、添加到setting的app中
        • 3、添加中间件
        • 4、setting下面添加下面的配置
    • 五、前后端打通
    • 拓展

昨日回顾

1 软件开发规范
2 pip换源
	1、文件管理器文件路径地址栏敲:%APPDATA% 回车,快速进入 C:\Users\电脑用户\AppData\Roaming 文件夹中
    2、新建 pip 文件夹并在文件夹中新建 pip.ini 配置文件
    3、新增 pip.ini 配置文件内容 
3 虚拟环境(以后再写新项目,直接用虚拟环境,尽量一个项目一个虚拟环境)
	1 配置
    	-windows下
            -pip3 install virtualenv   # 虚拟环境模块
            -pip3 install virtualenvwrapper-win # workon命令,会产生一个可执行文件virtualenvwrapper.bat
            -环境变量:WORKON_HOME: D:\Virtualenvs
         -Linux,mac
        	-pip3 install virtualenv   # 虚拟环境模块
            -pip3 install virtualenvwrapper   # virtualenvwrapper.sh
			# 在 ~/.bash_profile 完成配置,virtualenvwrapper的默认默认存放虚拟环境路径是 ~/.virtualenvs
            # WORKON_HOME=自定义存放虚拟环境的绝对路径,需要自定义就解注
            VIRTUALENVWRAPPER_PYTHON=/usr/local/bin/python3
            source /usr/local/bin/virtualenvwrapper.sh
            # 在终端让配置生效:
            source ~/.bash_profile
    2 命令
    mkvirtualenv -p python3.6 虚拟环境名称
    
4 路飞后台
	-django-admin命令创建项目
    -目录调整
    luffyapi
        -manage.py   # 脚本文件(数据迁移,测试运行...)
        -scripts     # 测试脚本
        -logs
    	-luffyapi
            -urls.py  # 总路由,setting中配置
            -settings
                -dev.py # 开发阶段用的配置文件
                -pro.py # 上线阶段用的配置文件
            -libs      # 第三方的库
            -utils      # 自己写的公共方法
            -wsgi.py    # 上线阶段的启动文件
            -apps       # 所有的app
                -user   # user app
                -course
                -home
    -调整完能运行
    	-django启动是依据settings.py启动,配置文件路径配置正确
        -wsgi.py 后期上线要改
        -把项目根路径加入环境变量(导入模块,基于小luffyapi文件加导入)
        -把apps文件夹加入到环境变量(再配置文件中,注册app时候,直接写名字即可)
        -pycharm中导入报错(实质没错),把加入环境变量的文件加作为了source root
5 数据库配置
	-创建数据库用户,授予luffy这个库的所有权限,创建luffy用户,密码是Luffy123?
     grant all privileges on luffy.* to 'luffy'@'%' identified by 'Luffy123?';
     grant all privileges on luffy.* to 'luffy'@'localhost' identified by 'Luffy123?';
     flush privileges;  #修改落到硬盘上了,把权限,用户更新到内存
        
        
     -再django配置文件中
        import os
	    user=os.environ.get('db_user','root')
        password=os.environ.get('db_password','123')
    	DATABASES = {
            'default': {
                'ENGINE': 'django.db.backends.mysql',
                'NAME': 'luffy', # 库名
                'USER': user, # 用户名
                'PASSWORD': password, 
                'HOST': 'localhost',
                'PORT': 3306
                }
            }
        import pymysql
        pymysql.install_as_MySQLdb()
	-使用环境变量配置数据库的用户名和密码
    	import os
		user=os.environ.get('db_user')
        password=os.environ.get('db_password')
        
6 前端创建项目
	-vue create luffycity
    -配置运行

今日内容

一、luffy前台配置

1.1 axios前后台交互

安装:前端项目目录下的终端
>: cnpm install axios
配置:main.js
import axios from 'axios'
Vue.prototype.$axios = axios;

1.2 cookies操作

安装:前端项目目录下的终端
>: cnpm install vue-cookies
配置:main.js
import cookies from 'vue-cookies'
Vue.prototype.$cookies = cookies;

1.3 element-ui页面组件框架

安装:前端项目目录下的终端
>: cnpm install element-ui
配置:main.js
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);

1.4 bootstrap页面组件框架

安装:前端项目目录下的终端
>: cnpm install jquery
>: cnpm install bootstrap@3
配置jquery:vue.config.js
const webpack = require("webpack");

module.exports = {
    configureWebpack: {
        plugins: [
            new webpack.ProvidePlugin({
                $: "jquery",
                jQuery: "jquery",
                "window.jQuery": "jquery",
                "window.$": "jquery",
                Popper: ["popper.js", "default"]
            })
        ]
    }
};
配置bootstrap:main.js
import 'bootstrap'
import 'bootstrap/dist/css/bootstrap.min.css'

二、user模块User表

2.1 创建user模块

前提:在 luffy 虚拟环境下

1.终端从项目根目录进入apps目录
>: cd luffyapi & cd apps

2.创建app
>: python ../../manage.py startapp user

2.2 创建User表对应的model:user/models.py

from django.db import models
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
    mobile = models.CharField(max_length=11, unique=True)
    # 需要pillow包的支持
    icon = models.ImageField(upload_to='icon', default='icon/default.png')

    class Meta:
        db_table = 'luffy_user'
        verbose_name = '用户表'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.username

2.3 注册user模块,配置User表:dev.py

INSTALLED_APPS = [
    # ...
    'user',
]

# 自定义User表
AUTH_USER_MODEL = 'user.User'

2.4 配置media

media配置:dev.py
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
media目录配置
"""
├── luffyapi
    └──	luffyapi/
       	└──	media/  	
			└──	icon 
				└── default.png
"""
主路由:luffyapi/urls.py
from django.contrib import admin
from django.urls import path, re_path, include
from django.views.static import serve
from django.conf import settings
urlpatterns = [
    path('admin/', admin.site.urls),

    path('user/', include('user.urls')),

    re_path('^media/(?P.*)', serve, {'document_root': settings.MEDIA_ROOT})
]
子路由:user/urls.py
from django.urls import path, include
from utils.router import router

# 注册ViewSet的路由
# router.register()

urlpatterns = [
    path('', include(router.urls)),
]

2.5 数据库迁移

"""
1)去向大luffyapi所在目录的终端

2)安装pillow模块
pip install pillow

3)数据库迁移
python manage.py makemigrations
python manage.py migrate
"""

三、封装全局Response对象和全局异常

3.1 环境变量

dev.py
# 环境变量操作:小luffyapiBASE_DIR与apps文件夹都要添加到环境变量
import sys
sys.path.insert(0, BASE_DIR)
APPS_DIR = os.path.join(BASE_DIR, 'apps')
sys.path.insert(1, APPS_DIR)
在写项目直接导入utils文件夹也不’’错误提示’’

luffy02_第1张图片

3.2 封装logger

dev.py
# 真实项目上线后,日志文件打印级别不能过低,因为一次日志记录就是一次文件io操作
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'verbose': {
            'format': '%(levelname)s %(asctime)s %(module)s %(lineno)d %(message)s'
        },
        'simple': {
            'format': '%(levelname)s %(module)s %(lineno)d %(message)s'
        },
    },
    'filters': {
        'require_debug_true': {
            '()': 'django.utils.log.RequireDebugTrue',
        },
    },
    'handlers': {
        'console': {
            # 实际开发建议使用WARNING
            'level': 'DEBUG',
            'filters': ['require_debug_true'],
            'class': 'logging.StreamHandler',
            'formatter': 'simple'
        },
        'file': {
            # 实际开发建议使用ERROR
            'level': 'INFO',
            'class': 'logging.handlers.RotatingFileHandler',
            # 日志位置,日志文件名,日志保存目录必须手动创建,注:这里的文件路径要注意BASE_DIR代表的是小luffyapi
            'filename': os.path.join(os.path.dirname(BASE_DIR), "logs", "luffy.log"),
            # 日志文件的最大值,这里我们设置300M
            'maxBytes': 300 * 1024 * 1024,
            # 日志文件的数量,设置最大日志数量为10
            'backupCount': 10,
            # 日志格式:详细格式
            'formatter': 'verbose',
            # 文件内容编码
            'encoding': 'utf-8'
        },
    },
    # 日志对象
    'loggers': {
        'django': {
            'handlers': ['console', 'file'],
            'propagate': True, # 是否让日志信息继续冒泡给其他的日志处理系统
        },
    }
}
utils/logging.py
import logging
logger = logging.getLogger('django')

3.3 封装项目异常处理

utils/exception.py
from rest_framework.views import exception_handler as drf_exception_handler
from rest_framework.views import Response
from rest_framework import status
from utils.logging import logger
import logging
logging.getLogger('django')
def exception_handler(exc, context):
    response = drf_exception_handler(exc, context)
    if response is None:
        # 记录服务器异常
        logger.critical('%s' % exc)
        response = Response({'detail': '服务器异常,请重试...'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    return response
settings.py
REST_FRAMEWORK = {
    'EXCEPTION_HANDLER': 'utils.exception.exception_handler',
}

3.4 二次封装Response模块

utils/response.py
from rest_framework.response import Response

class APIResponse(Response):
    def __init__(self, status=0, msg='ok', http_status=None, headers=None, exception=False, **kwargs):
        data = {
            'status': status,
            'msg': msg,
        }
        if kwargs:
            data.update(kwargs)
        super().__init__(data=data, status=http_status, headers=headers, exception=exception)

3.5 路由组件配置

utils/router.py
from rest_framework.routers import Route, DynamicRoute, SimpleRouter as DRFSimpleRouter

class SimpleRouter(DRFSimpleRouter):
    routes = [
        # List route.  /资源s/
        Route(
            url=r'^{prefix}{trailing_slash}$',
            mapping={
                'get': 'list',  # 群查
                'post': 'create',  # 单增、群增
                'put': 'multiple_update',  # 群整改
                'patch': 'multiple_partial_update',  # 群局改
                'delete': 'multiple_destroy',  # 群删
            },
            name='{basename}-list',
            detail=False,
            initkwargs={'suffix': 'List'}
        ),
        # Dynamically generated list routes. Generated using
        # @action(detail=False) decorator on methods of the viewset.
        DynamicRoute(
            url=r'^{prefix}/{url_path}{trailing_slash}$',
            name='{basename}-{url_name}',
            detail=False,
            initkwargs={}
        ),
        # Detail route.  /资源s/(pk)/
        Route(
            url=r'^{prefix}/{lookup}{trailing_slash}$',
            mapping={
                'get': 'retrieve',  # 单查
                'put': 'update',  # 单整改
                'patch': 'partial_update',  # 单局改
                'delete': 'destroy'  # 单删
            },
            name='{basename}-detail',
            detail=True,
            initkwargs={'suffix': 'Instance'}
        ),
        # Dynamically generated detail routes. Generated using
        # @action(detail=True) decorator on methods of the viewset.
        DynamicRoute(
            url=r'^{prefix}/{lookup}/{url_path}{trailing_slash}$',
            name='{basename}-{url_name}',
            detail=True,
            initkwargs={}
        ),
    ]

# 对外提供十大接口的router对象
router = SimpleRouter()
# eg: router.register('users', UserModelViewSet, basename='user')
"""
/users/
'get': 'list',  # 群查
'post': 'create',  # 单增、群增
'put': 'multiple_update',  # 群整改
'patch': 'multiple_partial_update',  # 群局改
'delete': 'multiple_destroy',  # 群删

/users/(pk)/
'get': 'retrieve',  # 单查
'put': 'update',  # 单整改
'patch': 'partial_update',  # 单局改
'delete': 'destroy'  # 单删
"""

四、跨域请求

4.1 同源策略

同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现

请求的url地址,必须与浏览器上的url地址处于同域上,也就是域名,端口,协议相同.

比如:我在本地上的域名是127.0.0.1:8000,请求另外一个域名:127.0.0.1:8001一段数据

浏览器上就会报错,个就是同源策略的保护,如果浏览器对javascript没有同源策略的保护,那么一些重要的机密网站将会很危险

已拦截跨源请求:同源策略禁止读取位于 http://127.0.0.1:8001/SendAjax/ 的远程资源。(原因:CORS 头缺少 'Access-Control-Allow-Origin')。

但是注意,项目2中的访问已经发生了,说明是浏览器对非同源请求返回的结果做了拦截

4.2 CORS(跨域资源共享)简介

CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。

整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。

因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。

4.3 CORS基本流程

浏览器将CORS请求分成两类:简单请求(simple request)非简单请求(not-so-simple request)。
浏览器发出CORS简单请求只需要在头信息之中增加一个Origin字段。
浏览器发出CORS非简单请求会在正式通信之前,增加一次HTTP查询请求,称为”预检”请求(preflight)。浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错。

4.4 CORS两种请求详解

只要同时满足以下两大条件,就属于简单请求。

1) 请求方法是以下三种方法之一:
HEAD
GET
POST
(2)HTTP的头信息不超出以下几种字段:
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

支持跨域,简单请求

服务器设置响应头:Access-Control-Allow-Origin = ‘域名’ 或 ‘*’

支持跨域,复杂请求

由于复杂请求时,首先会发送“预检”请求,如果“预检”成功,则发送真实数据。

  • “预检”请求时,允许请求方式则需服务器设置响应头:Access-Control-Request-Method
  • “预检”请求时,允许请求头则需服务器设置响应头:Access-Control-Request-Headers

4.5 Django项目中支持CORS

在返回的结果中加入允许信息(简单请求)

def test(request):
    import json
    obj=HttpResponse(json.dumps({'name':'lqz'}))
    # obj['Access-Control-Allow-Origin']='*'
    obj['Access-Control-Allow-Origin']='http://127.0.0.1:8004'
    return obj

放到中间件处理复杂和简单请求:

from django.utils.deprecation import MiddlewareMixin
class CorsMiddleWare(MiddlewareMixin):
    def process_response(self,request,response):
        if request.method=="OPTIONS":
            #可以加*
            response["Access-Control-Allow-Headers"]="Content-Type"
        response["Access-Control-Allow-Origin"] = "http://localhost:8080"
        return response

4.6 django 使用django-cors-headers 解决跨域问题

1、使用pip安装
pip install django-cors-headers
2、添加到setting的app中
INSTALLED_APPS = (
	...
	'corsheaders',
	...
)
3、添加中间件
MIDDLEWARE = [  # Or MIDDLEWARE_CLASSES on Django < 1.10
	...
	'corsheaders.middleware.CorsMiddleware',
	'django.middleware.common.CommonMiddleware',
	...
]
4、setting下面添加下面的配置
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',
)

五、前后端打通

mounted() {
  // this.$axios.get('http://127.0.0.1:8000/user/test/')
  this.$axios.get(this.$settings.base_url+'/user/test/').then(res=>{
      console.log(res.data)
  })
},

拓展

1 Python 获取环境变量的几种方式(django项目中配置文件,数据库用户和密码通过环境变量获取)
2 cookie,localstorage,sessionstorage区别(https://www.cnblogs.com/pengc/p/8714475.html)
3 pyechars的使用(研究一下)
4 2.2.2需要改源码的原因,你使用了pymysql来操作mysql数据库
	-如果使用mysqlclient操做mysql,就不需要改源码了,并且
    import pymysql
	pymysql.install_as_MySQLdb()
    -mysqlclient安装麻烦,解决起来:http://liuqingzheng.top/python/%E5%85%B6%E4%BB%96/01-%E5%90%84%E4%B8%BB%E6%B5%81Linux%E7%B3%BB%E7%BB%9F%E8%A7%A3%E5%86%B3pip%E5%AE%89%E8%A3%85mysqlclient%E6%8A%A5%E9%94%99/

你可能感兴趣的:(luffy,python)