typora-root-url: img
Django学习
1 MVC 与MVT流程介绍
2 安装虚拟环境
2.1 window下安装虚拟环境
-
安装python
-
创建虚拟环境
2.1 : 安装 virtualenv
pip install -i https://pypi.doubanio.com/simple/ virtualenv
2.2 : 安装 virtualenvwrapper-win
pip install -i https://pypi.doubanio.com/simple/ virtualenvwrapper-win
2.3 设置环境变量
计算机-->属性-->高级系统设置-->环境变量-->系统变量-->新建 变量名 : WORKON_HOME 路径 : 当前想存储的路径
2.4 基本虚拟环境的命令
1. 创建虚拟环境 mkvirtualenv -p python3 glm_test # 加 -p python3 的原因是指定copy的是python3 而不是python2 2. 进入虚拟环境 workon 虚拟环境名称 3. 退出虚拟环境 deactivate 4. 删除虚拟环境 rmvirtualenv 虚拟环境名称 5. 列出所有虚拟环境列表 workon
2.5 虚拟环境注意事项
cmd进入的时候, 必须进入到指定的虚拟环境路径下才能操作东西, 否则, 比如直接在桌面cmd进入虚拟环境, 那么下载的文件之后会在当前环境的路径下下载
2.2 ubuntu下安装虚拟环境
-
安装 python3 pip3
# 1. 输入pip3, python3 然后根据提示完成安装
-
安装虚拟环境
sudo apt install python3-virtualenv pip3 install virtualenvwrapper
-
配置环境变量
在home目录创建 没有
.bashrc
文件的话需要创建这个文件, 有的话就不用# 1. 创建文件 touch .bashrc # 2. 查看virtualenvwrapper.sh在哪里 whereis virtualenvwrapper.sh # 3. 进入.bashrc文件 vi .bashrc # 4. 进入编辑模式 输入字母 a # 5. 在最后面加入以下两行 export WORKON_HOME=$HOME/.virtualenvs source /usr/local/bin/virtualenvwrapper.sh # 6. 保存退出 按下 esc, 接着输入 :wq! # 7. 使.bashrc生效 source .bashrc
-
使用虚拟环境
1. 创建虚拟环境 mkvirtualenv -p python3 glm_test # 加 -p python3 的原因是指定copy的是python3 而不是python2 2. 进入虚拟环境 workon 虚拟环境名称 3. 退出虚拟环境 deactivate 4. 删除虚拟环境 rmvirtualenv 虚拟环境名称 5. 列出所有虚拟环境列表 workon
3 安装mysql
3.1 window下安装mysql
-
安装mysql 和 navicat
具体内容步骤安装包里都有
-
安装 mysqlclient (驱动)
# 0. 执行以下代码 pip install mysqlclient 如果没用, 那么用以下方法 : # 1. 进入下面地址, 下载安装包 : https://www.lfd.uci.edu/~gohlke/pythonlibs/#mysqlclient (因为pip的时候一直报错, 根据网上查的, 暂时使用这个方法) # 2. 找到 mysqlclient-1.4.6-cp38-cp38-win32.whl (注意点 : 1. 找32位的, 64不知道为啥没用, 2. cp38代表的是配合python2.8使用) # 3. 将下载的文件放至虚拟环境中 # 4. 在放至文件的虚拟环境目录下执行 : pip install mysqlclient-1.4.6-cp38-cp38-win32.whl # 5. 安装成功
3.2 ubuntu云服务器安装mysql和使用
-
安装
# 分别执行下面三条命令 sudo apt-get install mysql-server sudo apt-get install mysql-client sudo apt-get install libmysqlclient-dev
-
设置root密码
# 1. 切换到root目录下 sudo su # 2. 进入mysql mysql # 3. 配置数据库root权限,主要是修改密码 mysql> update mysql.user set authentication_string=PASSWORD('123456'), plugin='mysql_native_password' where user='root'; # 4、设置生效和退出mysql、root模式 mysql> flush privileges; mysql> exit; Bye # 5. 重启MySQL服务 sudo /etc/init.d/mysql restart # 6. 重新进入MySQL mysql -uroot -p # 7. 接着输入刚刚设置好的mysql密码
-
设置远程连接
# 1. 执行如下 sudo vi /etc/mysql/mysql.conf.d/mysqld.cnf # 2. 点击a, 进入编辑模式 # 3. 注释掉以下代码 bind-address = 127.0.0.1 # 4. 保存退出, 按下 esc, 接着输入 :wq! # 5. 进入mysql服务,执行授权命令 mysql -uroot -p mysql> grant all on *.* to root@'%' identified by '123456' with grant option; mysql> flush privileges; mysql> exit # 6. 重启MySQL服务 sudo /etc/init.d/mysql restart
3.3 Django使用mysql
3.3.1 navicat使用
- 打开navicat 先点击连接, 选择mysql, 配置下数据
- 创建数据库
- 字符集选择 : utf8 – UTF-8 Unicode
- 排序规则选择 : utf8_general_ci
- 新建表, 为id设置主键, 并且设置自动递增, 设置好属性以后, 点击保存
- 填充表的数据
3.3.2 Django配置与使用mysql
-
在settings中 设置 DATABASES :
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'family', # 数据库名字 'USER': 'root', # 用户 'PASSWORD': '.123456glm', # 密码 'HOST': '139.199.81.62', # 主机地址 'PORT': '3306' # 端口 } }
-
在views.py中使用
from django.shortcuts import render from django.http import HttpResponse from django.db import connection # 导入连接方法 def index(request): print(request.GET.get('name')) # 打印get请求的name参数 cursor = connection.cursor() # 定义连接自定义 cursor.execute("select * from person") # 编写自定义sql代码 rows = cursor.fetchall() # 获取返回的数据 rows = list(rows) # 整理数据, 默认返回的是元组 result = [] for key in rows: list_value = list(key) result.append(list_value) print(result) return HttpResponse(result) # 返回所有数据
4 mysql操作
4.1 基础增删改查
# 增加
insert into students(name,age) values('liming',18) # 或者
insert into students set name='龚帅',age=72;
- 添加多个 -
insert into students values('(*  ̄3)(ε ̄ *)',99),('刘诗诗',87),('刘亦菲',76)
# 删除
delete from students where id=7
- 删除全部 -
delete from students
# 修改
update students set name='利明欧巴',age=50 where id=1
- 修改全部 -
update students set name='利明欧巴'
# 查询
- 1. 查询全部 -
select * from students
- 2. 查询某个 -
select name from student where id=1
其中 ( >, <, =, !=, <=, >=) 都可使用
- 3. in - 查询in中集合部分
select * from students where id in (1,2,3)
- 4. between and - 查询中间部分
select * from students where id between 1 and 3 (1到3都有)
- 5. not between and - 查询外部部分
- 6. 空值查询 is -
select * from students where name is null
- 7. 过滤重复 -
select distinct age from students
- 8. like关键字查询
% : 任意字符(通配符)
_ : 单个字符(通配符)
select * from students where name like 'g%'
select * from students where concat(id,username,psw,label,weight) like "%search%"
- 9. and or -
select * from students where name='龚利明' and id=10
- 10 聚合函数
10.1 : count 查询有多少条数据
select count(*) from students
10.2 : sum 该字段的数字总和
select sum(id) from students
10.3 : avg 平均值
10.4 : max 最大值
10.5 : min 最小值
- 11. order by 字段名 [asc | desc] 对查询的字段排序 asc 升序, desc 降序
select * from students order by age asc
- 12. limit 限制查询结果数量 - limit [offset] 几条, offset为偏移数, 不写的话为0 几条是必须写的
select * from students limit 4 : 查询四条数据, offset已经省略
select * from students limit 4,4 : 从第四条数据开始查询四条数据
4.2 中级mysql操作
5 git
5.1 安装git
sudo apt-get install -i https://pypi.doubanio.com/simple/ git
5.2 我的 github 资料
账户 : 13145846564.@163.com
地址 : https://github.com/gongliming-qd/
6 FTP(fileFreeze)
7 xshell
8 开发阶段 外网能访问的配置
-
在settings.py中配置允许外网访问的ip, 或者域名
ALLOWED_HOSTS = ['139.199.81.62'] 或者直接'*'
-
执行启动项目
python manage.py runserver 0:8000
9 uwsgi
9.1 安装
pip install uwsgi
9.2 创建文件
-
在项目根目录下创建
uwsgi.ini
文件 -
并且输入一下内容 :
[uwsgi]
# 使用 nginx 时使用
socket=0.0.0.0:7000
# 直接web服务器使用 python runserver 0:8000
http=0.0.0.0:8000 #(注释这个)
# 项目目录
chdir=/home/ubuntu/all_project/first_one/python_dgango
# 项目中wsgi.py文件的目录, 相对于项目目录
wsgi-file=mysite/wsgi.py
# 指定启动的工作进程数
processes=4
# 指定工作的线程数
threads=2
master=True
# 保存启动之后主进程的pid
pidfile=uwsgi.pid
# 设置uwsgi后台运行, uwsgi保存日志保存
daemonize=uwsgi.log
# 设置虚拟环境的路径
virtualenv=/home/ubuntu/.virtualenvs/glm_django
9.3 启动, 停止
启动:uwsgi --ini uwsgi.ini
停止:uwsgi --stop uwsgi.pid
重启:uwsgi --reload uwsgi.pid
查看进程号:ps -ef|grep uwsgi
查看进程号:ps -aux|grep uwsgi
结束所有进程 killall -s INT uwsgi
10 Nginx
10.1 ubuntu安装
sudo apt-get install nginx
10.2 启动,停止,重启
# 启动
service nginx start
# 关闭
service nginx stop
# 重启
service nginx restart
# 修改文件重启
sudo nginx -s reload
10.3 配置
10.3.1 收集静态文件
# 1. 在 settings.py中指定 STATIC_ROOT
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
# 2. 创建static文件夹存放所以的静态文件, 文件名与上面指定的一致
# 3. 收集所有的静态文件
python manage.py collectstatic
# 4. 上传git
10.3.2 修改Django项目配置文件
# 1. 修改 uwsgi.ini文件, 开启socket, 注释掉http
[uwsgi]
socket=0.0.0.0:7000
; http=0.0.0.0:7000
chdir=/home/ubuntu/all_project/first_one/python_dgango
wsgi-file=mysite/wsgi.py
processes=4
threads=2
master=True
pidfile=uwsgi.pid
daemonize=uwsgi.log
virtualenv=/home/ubuntu/.virtualenvs/python_dgango
# 2. 修改setting.py 中的DEBUG 和 ALLOWED_HOSTS
DEBUG = False
ALLOWED_HOSTS = ['*']
10.3.3 服务器配置nginx
-
找到 nginx的默认配置文件,修改文件内容
有以下两个文件配置, 我选择的是第二个 # /etc/nginx/nginx.conf # /etc/nginx/sites-enabled/default
-
操作
# 1. 打开文件 sudo vi /etc/nginx/sites-enabled/default # 2. 点击a 进去修改文件 # 3. 参考以下被 # 包围的内容 server { listen 80 default_server; listen [::]:80 default_server; root /var/www/html; index index.html index.htm index.nginx-debian.html; server_name _; ##################################################### location / { include uwsgi_params; # 传递请求的值 uwsgi_pass 139.199.81.62:7000; # 转发到7000端口 } location /static { alias /var/www/python_dgango/static/; #设置静态文件 } location = / { proxy_pass http://139.199.81.62; # 会自动转到静态文件夹下的 index.html文件 } ##################################################### } # 4. git代码拉取下来 git pull # 5. 在 /var/www 目录下创建 /python_dgango/static/ # 6. 将 收集到的静态文件拷贝到 /var/www/python_dgango/static/ 中 sudo cp -a 源文件 目标文件 # 7. 重启nginx sudo nginx -s reload # 8. 关闭所有uwsgi killall -s INT uwsgi # 9. 进入到项目目录, 开启7000端口的 uwsgi uwsgi --ini uwsgi.ini
11 绑定域名
- 进入到云服务器中, 解析域名
11.1 上传ssl证书, 绑定 https
# 1. 进入腾讯云控制台
# 2. 总览==> 域名管理
# 3. 更多 ==> 证书下载
# 4. 过一段时间后, 会申请成功.
选择nginx文件夹. (包含两个文件)
1_www.gongliming.com_bundle.crt
2_www.gongliming.com.key
# 5. 通过git将两个文件上传到服务器
# 6. 将两个文件存在 /etc/nginx/conf.d
# 7. 设置nginx中端口为443部分
7.1 cd /etc/nginx/sites-enabled/
sudo vi default
############ 添加一下文件 ###########################################
server {
listen 443;
server_name www.gongliming.com; # 改为绑定证书的域名
# ssl 配置
ssl on;
ssl_certificate /etc/nginx/conf.d/1_www.gongliming.com_bundle.crt; # 改为自己申请得到的 crt 文件的路径
ssl_certificate_key /etc/nginx/conf.d/2_www.gongliming.com.key; # 改为自己申请得到的 key 文件的路径
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4:!DH:!DHE;
location /api {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
include uwsgi_params;
uwsgi_pass 139.199.81.62:7000;
}
location / {
alias /var/www/python_dgango/static/;
}
}
12 Django基本使用
12.1 创建应用
-
在虚拟环境下, 下载Django
- 指定版本号 : Django==1.8.2
pip install -i https://pypi.doubanio.com/simple/ Django
-
创建Django项目
django-admin startproject mysite
- 进入mysite, 创建packages.txt记录当前所用的所有包
pip freeze > packages.txt
- git拉取代码后安装重建包
pip install -r packages.txt -i https://pypi.doubanio.com/simple/
- 启动
python manage.py runserver
12.2 文件目录介绍
mysite/
manage.py
mysite/
__init__.py
settings.py
urls.py
asgi.py
wsgi.py
- 外部 mysiye : 根目录, 项目的容器
- manage.py : 按照目前来说就是一个入口文件
- /mysite/
__init__
.py : 一个空文件, 告诉python该目录为应视为python的软件包 - /mysite/settings.py : 此Django的项目的设置与配置,
- /mysite/urls.py : url的配置,相当于路由的配置
- /mysite/asgi.py : 与ASGI兼容的Web服务器为您的项目提供服务的入口点
- /mysite/wsgi.py : 与WSGI兼容的Web服务器为您的项目提供服务的入口点
12.3 创建应用程序
- 执行如下命令
py manage.py startapp polls
会自动创建文件夹, 包含以下内容
polls/
__init__.py
admin.py
apps.py
migrations/
__init__.py
models.py
tests.py
views.py
mysite/
__init__.py
settings.py
urls.py
asgi.py
wsgi.py
manage.py
-
此时在polls目录下创建 views.py文件编写如下
from django.http import HttpResponse def index(request): return HttpRresonse('hello world!!') def myset(request): return HttpRresonse(request.GET)
-
在polls目录下的urls.py文件增加部分内容, 内容如下 :
from django.urls import path from . import views urlpatterns = [ path('', views.index, name="index"), path('/makelove', views.makeLove, name="index"), ]
-
在mysite目录下的urls.py中添加如下内容 :
from django.contrib import admin from django.urls import path, include urlpatterns = [ path('polls/nihao', include('polls.urls')), path('admin/', admin.site.urls), ]
12.4 返回类型
12.4.1 JsonResponse
- JsonResponse, 需要指定 safe为false
from django.http import HttpResponse, JsonResponse
import json
def index(request):
print(request.GET.get('name'))
cursor = connection.cursor()
cursor.execute("select * from member")
rows = cursor.fetchall()
rows = list(rows)
result = []
for key in rows:
list_value = list(key)
result.append({'id': list_value[0], 'name': list_value[1], 'sec': list_value[2], 'bobby': list_value[3], 'introduction': list_value[4]})
result.append(list_value)
return JsonResponse(result, safe=False)
12.4.2 render(服务端开发使用)
- views.py内容 :
from django.shortcuts import render
from django.http import HttpResponse
def index(request):
aaa = {"name": 'handsome'}
return render(request, 'glm.html', aaa)
def myset(request):
return HttpResponse(request.GET)
- 在template种创建 glm.html
# 并且包含 {{name}}在其中
#但是此时并不能把所有的vue打包好的放在这使用, 具体问题还不知道
12.5 views.py拆分多个文件
- 在Django中,所有内容都是Python模块(* .py)。你可以创建一个具有
__init__.py
内部视图的文件夹,并且仍然可以导入视图,因为这也实现了Python模块。但是一个例子会更好。
你的原始图片views.py
可能如下所示:
def view1(arg):
pass
def view2(arg):
pass
使用以下文件夹/文件结构,它将起到相同的作用:
views/
__init__.py
viewsa.py
viewsb.py
viewsa.py :
def view1(arg):
pass
viewsb.py :
def view2(arg):
pass
init.py :
from viewsa import view1
from viewsb import view2
- 在快速的解释是:当你写
from views import view1
的Python会寻找在厂景
-
views.py
,这是第一个(原始)情况下发生的情况 -
views/__init__.py
,这是第二种情况。在这里,__init__.py
能够提供view1方法,因为它可以导入它。
使用这种解决方案,你可能无需更改import或更改urlpattern参数urls.py
如果每个新视图文件中都有许多方法,那么views/__init__.py
使用导入可能会很有用*,如下所示:
from viewsa import *
from viewsb import *
12.6 设置静态文件存放vue打包好的文件
注意 : 仅仅开发环境下使用, 生产环境则需要设置nginx代理处理
-
settings.py设置两个地方 :
# 1. 设置静态文件 STATIC_URL = '/static/' # 1. 以 static开头的请求, 会先在static文件夹中寻找 STATICFILES_DIRS = [ # 设置静态文件夹为 template os.path.join(BASE_DIR, "templates") ] # 设置TEMPLATES TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'templates')], # 也设置为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', ], }, }, ]
-
将打包好的静态文件中index.html所引用的静态文件前面加个 /static/
<link href=/css/app.d608e4f8.css rel=preload as=style> <link href=/js/app.19055ea5.js rel=preload as=script> <link href=/js/chunk-vendors.ae709be3.js rel=preload as=script> <link href=/css/app.d608e4f8.css rel=stylesheet> <script src=/static/js/chunk-vendors.ae709be3.js></script> <script src=/static/js/app.19055ea5.js></script>
12.7 处理在服务器中请求数据
1、引入包
import requests,json
2、
(1)requests.post方法调三方接口(用的是data)
r = requests.post(url+'company/add_friend/', data={'id': zid, 'com_key': com_key})
# 这一步将返回值转成json
key = json.loads(r.text)
(2)requests.get方法调三方接口(用的是params)
r = requests.get(url + 'company/search_user/', params={'id': id, 'pub_key': pub_key})
# 这一步将返回值转成json
key = json.loads(r.text)
12.8 获取到get,post等请求的数据
12.8.1 get
def index(request):
username = request.GET.get('username')
print(username)
return JsonResponse(result, safe=False)
12.8.2 post
-
说明 :
ajax发送一个请求, post会被forbidden,get不会,主要原因是csrf中间件, 需要注释掉, 在settings.py中找到 MIDDLEWARE
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middlewaremon.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware', # 注释掉这个
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
-
获取值
- 前端axios传递的值为json格式, 所以这里用 request.body的方式来获取json形式的数据, request.POST是www.xxxxxxxx的形式
def index(request): username = json.loads(request.body)['username'] psw = json.loads(request.body)['psw'] print(username) return JsonResponse(result, safe=False)
12.8.3 获取请求头
- header key必须大写,前缀必须是"HTTP",后面如果连接符是横线“-”,要改成下划线“_”。例如你的header的key为api_auth,那在Django中应该使用request.META.get(“HTTP_API_AUTH”)来获取请求头的数据
12.9 中间件
12.9.1 中间件文件编写
在polls文件下, 新建文件 middleware.py
- 类名字必须写死, 或者写以下几种 :
__init__
: 服务器响应第一个请求- process_request : 在产生url对象,进行url匹配之前调用
- process_view : 是url匹配之后, 调用视图函数之前
- process_response : 视图函数调用之后, 内容返回给浏览器之前
- process_exception : 视图函数出现异常, 会调用这个函数
from django.utils.deprecation import MiddlewareMixin
class polls_middleware_class(MiddlewareMixin):
def process_view(self, request, view_func, *view_args, **view_kwares):
print('1111111')
12.9.2 setting中设置
- 设置 : MIDDLEWARE ‘polls.middleware.polls_middleware_class’
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middlewaremon.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'polls.middleware.polls_middleware_class' # 加的是这个
]
12.10 封装mysql数据库操作方法
- 在 /utils/use_mysql.py目录中
from django.db import connection
# 对数据库操作, 返回的是元组
def use_mysql(sql):
cursor = connection.cursor()
cursor.execute(sql)
rows = cursor.fetchall()
return rows
- 返回数组,键值对
from django.db import connection
def dictfetchall(cursor):
"Return all rows from a cursor as a dict"
columns = [col[0] for col in cursor.description]
return [
dict(zip(columns, row))
for row in cursor.fetchall()
]
def use_mysql_by_dict(sql):
cursor = connection.cursor()
cursor.execute(sql)
rows = dictfetchall(cursor)
return rows
12.11 redis数据库
12.11.1 window安装服务
-
解压好软件放在桌面 (每次使用都要打开):
链接:
https://pan.baidu/s/1az_2rNfhceuQubkaDh1YJw
提取码: 9sza -
然后双击 redis-server.exe 即可
12.11.1.1 安装驱动和设置与使用
- 和下面 ubuntu 使用方法一样
12.11.2 ubuntu安装服务
12.11.2.1 安装
-
安装服务
sudo apt-get install redis-server
-
安装驱动
pip install django-redis
12.11.2.2设置
-
在settings.py添加下面内容
CACHES = { 'default': { 'BACKEND': 'django_redis.cache.RedisCache', 'LOCATION': 'redis://127.0.0.1:6379', "OPTIONS": { "CLIENT_CLASS": "django_redis.client.DefaultClient", }, }, }
12.11.2.3使用
- 在views.py中使用
from django.core.cache import cache #引入缓存模块
# 测试存储数据
def testredis(request):
username = request.GET.get('username')
cache.set(username, username, 30*60) # 存储半个小时
results = cache.has_key(username)
return JsonResponse(results, safe=False)
# 测试能否获得数据
def getredis(request):
username = request.GET.get('username')
results = cache.get(username)
return JsonResponse(results, safe=False)
12.12 token的使用
12.12.1 用redis存储
-
写得好的文章 :
https://blog.csdn/cfy137000/article/details/79189252
- python 字符串补充 :
results = use_mysql('INSERT INTO token (username, token) VALUES("%s","%s")'%(username, token)) results = use_mysql('INSERT INTO token (username, token) VALUES("%(username)s","%(token)s")'%{ "username":username, "token":token })
- 封装一个utils.py的文件
- create_token(username) : 创建 token,存入redis中
- check_token(token) : 检验 token 是否正确
- get_username(token): 解密token
- encrypt_other(username): 创建token,不存入redis中
import time
from django.core import signing
import hashlib
from django.core.cache import cache #引入缓存模块
# 加密
def encrypt(obj):
"""加密"""
value = signing.dumps(obj, key='liming', salt='www.gongliming')
value = signing.b64_encode(value.encode()).decode()
return value
# 解密
def decrypt(src):
"""解密"""
src = signing.b64_decode(src.encode()).decode()
raw = signing.loads(src, key='liming', salt='www.gongliming')
return raw
# 创建token
def create_token(username):
"""生成token信息"""
# 1. 加密头信息
header = encrypt({'typ': 'JWP', 'alg': 'default'})
# 2. 构造Payload
payload = {"username": username, "iat": time.time()}
payload = encrypt(payload)
# 3. 生成签名
md5 = hashlib.md5()
md5.update(("%s.%s" % (header, payload)).encode())
signature = md5.hexdigest()
token = "%s.%s.%s" % (header, payload, signature)
# 存储到缓存中
cache.set(username, token, 30*60)
return token
def get_payload(token):
payload = str(token).split('.')[1]
payload = decrypt(payload)
return payload
# 通过token获取用户名
def get_username(token):
payload = get_payload(token)
return payload['username']
pass
# 检测token
def check_token(token):
username = get_username(token)
print(username)
results_token = cache.get(username)
print(results_token)
print(token)
if results_token:
return results_token == token
return False
# 加密其它内容
def encrypt_other(username):
"""生成token信息"""
# 1. 加密头信息
header = encrypt({'typ': 'JWP', 'alg': 'default'})
# 2. 构造Payload
payload = {"username": username, "iat": time.time()}
payload = encrypt(payload)
# 3. 生成签名
md5 = hashlib.md5()
md5.update(("%s.%s" % (header, payload)).encode())
signature = md5.hexdigest()
token = "%s.%s.%s" % (header, payload, signature)
# 存储到缓存中
return token
- views.py中登录注册接口
import json
from .utils.use_mysql import use_mysql
from .utils.utils import create_token, check_token, get_username, encrypt_other
from django.http import HttpResponse, JsonResponse
# # 个人信息修改部分 -----------------------------------------------------------
# 1. 获取用户信息
def get_api_username_all_info(request):
# 1. 取出所有数据
weight = request.GET.get('weight',None)
xxx = (())
if weight:
xxx = use_mysql('select * from login_username_psw where weight="%(weight)s"' %{"weight": weight})
else:
results = {'code': 0, "state": 'true', "results": {"message": "无权限参数", "lists": None}}
return JsonResponse(results, safe=False)
if weight == '0':
xxx = use_mysql('select * from login_username_psw')
rows = list(xxx)
result = []
for key in rows:
list_value = list(key)
print(get_username(list_value[2]))
print(list_value[2])
result.append({'id': list_value[0], 'username': list_value[1], 'psw': get_username(list_value[2]), 'avatar_address': list_value[3],
'label': list_value[4],'weight': list_value[5]})
results = {'code': 0, "state": 'true', "results": {"message": "获取数据成功", "lists": result}}
return JsonResponse(results, safe=False)
# 1. 获取关键字搜索用户信息
def get_api_username_all_info_by_search(request):
# 1. 取出所有数据
weight = request.GET.get('weight', None)
search = request.GET.get('search', None)
xxx = (())
print(weight)
print(search)
if weight == '0':
xxx = use_mysql('select * from login_username_psw where concat(id,username,psw,label,weight) like "%(search)s"' %{"search": search})
elif weight == None :
results = {'code': 0, "state": 'true', "results": {"message": "无权限参数", "lists": None}}
return JsonResponse(results, safe=False)
else:
xxx = use_mysql('select * from login_username_psw where weight="%(weight)s" and concat(id,username,psw,label,weight) like "%(search)s"' %{"weight": weight,"search":search})
rows = list(xxx)
result = []
for key in rows:
list_value = list(key)
print(get_username(list_value[2]))
print(list_value[2])
result.append({'id': list_value[0], 'username': list_value[1], 'psw': get_username(list_value[2]), 'avatar_address': list_value[3],
'label': list_value[4],'weight': list_value[5]})
results = {'code': 0, "state": 'true', "results": {"message": "获取数据成功", "lists": result}}
return JsonResponse(results, safe=False)
# 2. 新增用户
def add_api_username_all_info(request):
if request.method == 'POST':
username = json.loads(request.body)['username']
psw = json.loads(request.body)['psw']
label = json.loads(request.body)['label']
weight = json.loads(request.body)['weight']
# 1. 验证该用户是否已经存在
num = use_mysql('select count(*) from login_username_psw where username="%(username)s"'%{"username": username})[0][0]
if num == 0:
# 1.1 说明不存在可以注册
# 1.1.2.1 写入数据库中
results_sql = use_mysql(
'insert into login_username_psw(username, psw, label, weight) values ("%(username)s","%(psw)s","%(label)s","%(weight)s")' % {
"username": username, "psw": encrypt_other(psw), "label": label, "weight": weight})
results = {'code': 0, "state": 'success', "results": {"message": results_sql}}
return JsonResponse(results, safe=False)
else:
# 1.2 说明不存在不能注册
results = {'code': 0, "state": 'false', "results": {"message": '当前用户已注册'}}
return JsonResponse(results, safe=False)
# 3. 修改用户
def update_api_username_all_info(request):
if request.method == 'POST':
id = json.loads(request.body)['id']
username = json.loads(request.body)['username']
psw = json.loads(request.body)['psw']
label = json.loads(request.body)['label']
weight = json.loads(request.body)['weight']
results_sql = use_mysql(
'update login_username_psw set username="%(username)s", psw="%(psw)s", label="%(label)s", weight="%(weight)s" where id=%(id)s' % {
"username": username, "psw": encrypt_other(psw), "label": label, "weight": weight, "id": id})
results = {'code': 0, "state": 'success', "results": {"message": results_sql}}
return JsonResponse(results, safe=False)
# 1.2 说明不存在不能注册
# 4. 删除用户
def dele_api_username_all_info(request):
if request.method == 'POST':
id = json.loads(request.body)['id']
print(id)
results_sql = use_mysql(
'delete from login_username_psw where id="%(id)s"' % {
"id": id})
results = {'code': 0, "state": 'success', "results": {"message": results_sql}}
return JsonResponse(results, safe=False)
- 中间件中,验证token是否正确
from django.http import HttpResponse, JsonResponse
from django.utils.deprecation import MiddlewareMixin
from .utils.utils import create_token, check_token, get_username
from .utils.use_mysql import use_mysql
class polls_middleware_class(MiddlewareMixin):
EXCLUDE_IPS=['127.0.0.1']
def process_view(self, request, view_func, *view_args, **view_kwares):
# 0. 获取图片
if '/api/get_img/' in request.path:
return
# 1. 如果不是登录接口, 都要进行token验证
if request.path != '/api/tologin/':
# 2. 获取token
token = request.META.get("HTTP_AUTHORIZATION")
# 3. 判断是否有传递token
if token != 'hello_world':
# 3.1 验证token信息
results = check_token(token)
if results:
# 3.1.1. 不做任何事情
print('token验证通过')
else:
# 3.1.2 返回false
results = {'code': 200, "state": 'false', "results": {"message": "token验证不通过"}}
return JsonResponse(results, safe=False)
else:
# 3.2 返回false
results = {'code': 200, "state": 'false', "results": {"message": "token验证不通过"}}
return JsonResponse(results, safe=False)
12.12.2 前端axios请求拦截和响应拦截配合使用
import axios from 'axios'
import Vue from 'vue'
import Router from '../router/index'
// 每次请求携带cookies信息
axios.defaults.withCredentials = true
//
let baseURL = ''
process.env.NODE_ENV === 'development'? baseURL='/glm' : baseURL = '/'
export const http = axios.create({
baseURL
})
// 登录前请求头的设置
// 添加请求拦截器
http.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
config.headers.Authorization = window.sessionStorage.getItem('token')||'hello_world'
return config
});
// 添加响应拦截器
http.interceptors.response.use(function (response) {
// 对响应数据做点什么
if(response.data.results.message == 'token验证不通过' && response.data.state == 'false'){
Vue.prototype.$message.warning('请重新登录哦!')
Router.push('/login')
}else{
return response;
}
return response;
});
12.12.3 前端反向代理
// vue.config.js
module.exports = {
// 打包的根路径 使用的是相对
publicPath: './',
// 移除map文件
productionSourceMap: false,
// 设置反向代理
devServer: {
open:true,
proxy: {
'/glm': {
target: 'http://127.0.0.1:8000/', //目标地址
// target: 'http://139.199.81.62/', //目标地址
ws: false, 是否启用websockets
changeOrigin: true, //开启代理:在本地会创建一个虚拟服务端,然后发送请求的数据,并同时接收请求的数据,这样服务端和服务端进行数据的交互就不会有跨域问题
pathRewrite: {
'^/glm': '/' //这里重写路径
}
}
}
}
}
12.13 文件处理
12.13.1 前端formData请求
注意点 :
- axios需要重新导入, 因为使用了axios拦截器的axios, 不能进行FormData数据传递, aixos默认用的是json,手动在axios中请求头中加入token
- 以下案例使用element-ui框架
<template>
<div>
<div>
<el-form
:model="ruleForm"
status-icon
ref="ruleForm"
label-width="100px"
class="demo-ruleForm"
>
<el-form-item label="密码" prop="pass">
<el-input type="password" v-model="ruleForm.pass" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="确认密码" prop="checkPass">
<el-input type="password" v-model="ruleForm.checkPass" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="文件" prop="age">
<input type="file" @change="get_add_file">
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('ruleForm')">提交</el-button>
<el-button @click="resetForm('ruleForm')">重置</el-button>
</el-form-item>
</el-form>
</div>
<img :src="count_img" alt="">
</div>
</template>
<script>
import axios from "axios";
export default {
data() {
return {
ruleForm: {
pass: "",
checkPass: "",
img: ""
},
};
},
computed:{
// /api/get_img/?img_name 是我设定的服务器请求. 开发模式下需要做代理, 生产环境下, 就不需要了
count_img(){
if(process.env.NODE_ENV === 'development'){
return 'http://127.0.0.1:8000/api/get_img/?img_name=touxiang.jpg'
}else{
return '/api/get_img/?img_name=touxiang.jpg'
}
}
},
methods: {
// 1. 点击提交
submitForm(formName) {
this.$refs[formName].validate(valid => {
if (valid) {
// 处理数据
let formData = new FormData();
formData.append("psw", this.ruleForm.pass);
formData.append("checkPass", this.ruleForm.checkPass);
formData.append("file_img", this.ruleForm.img);
axios({
method: "post",
url: "/glm/api/check_pass/",
data: formData,
headers: {'Authorization': window.sessionStorage.getItem('token')||'hello_world'},
}).then(function(response) {
console.log(response);
});
} else {
console.log("error submit!!");
return false;
}
});
},
// 2. 选择文件
get_add_file(e){
let file = e.target.files[0]
this.ruleForm.img = file
},
// 3. 重置表单
resetForm(formName) {
this.$refs[formName].resetFields();
}
},
};
</script>
<style scoped lang="less">
</style>
12.13.2 后端处理
from django.http import HttpResponse, JsonResponse
from django.db import connection
from .utils.utils import create_token, check_token, get_username, encrypt_other
from .utils.use_mysql import use_mysql
# 存储图片
def check_pass(request):
psw = request.POST.get('psw');
file_img = request.FILES.get('file_img')
print(file_img)
# 加密文件名
file_name = encrypt_other(file_img.name)
# 文件名和上传的数据填到数据库中
# 文件存储到文件夹
with open('upload/img/'+file_name, 'wb') as pic:
for c in file_img.chunks():
pic.write(c)
results = {'code': 0, "message": 'true'}
return JsonResponse(results, safe=False)
def get_img(request):
# 获取用户名 touxiang.jpg
# 通过用户名到数据库中求取图片的名字
img_name = request.GET.get('img_name')
# 通过名字, 到文件夹中读取, 并返回到前端中
image_data = open('upload/img/' + img_name, "rb").read()
return HttpResponse(image_data, content_type="image/png")
更多推荐
Django总结
发布评论