Django总结


typora-root-url: img

Django学习

1 MVC 与MVT流程介绍

2 安装虚拟环境

2.1 window下安装虚拟环境
  1. 安装python

  2. 创建虚拟环境

    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下安装虚拟环境
  1. 安装 python3 pip3

    # 1. 输入pip3, python3    然后根据提示完成安装
    
  2. 安装虚拟环境

    sudo apt install python3-virtualenv
    pip3 install virtualenvwrapper
    
  3. 配置环境变量

    在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
    
    
  4. 使用虚拟环境

    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
  1. 安装mysql 和 navicat

    具体内容步骤安装包里都有
    
  2. 安装 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和使用
  1. 安装

    # 分别执行下面三条命令
    sudo apt-get install mysql-server   
    sudo apt-get install mysql-client
    sudo apt-get install libmysqlclient-dev
    
  2. 设置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密码
    
  3. 设置远程连接

    # 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使用
  1. 打开navicat 先点击连接, 选择mysql, 配置下数据
  2. 创建数据库
    • 字符集选择 : utf8 – UTF-8 Unicode
    • 排序规则选择 : utf8_general_ci
  3. 新建表, 为id设置主键, 并且设置自动递增, 设置好属性以后, 点击保存
  4. 填充表的数据
3.3.2 Django配置与使用mysql
  1. 在settings中 设置 DATABASES :

    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'NAME': 'family',  # 数据库名字
            'USER': 'root', # 用户
            'PASSWORD': '.123456glm', # 密码
            'HOST': '139.199.81.62', # 主机地址
            'PORT': '3306' # 端口
        }
    }
    
  2. 在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   (13都有)
- 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 开发阶段 外网能访问的配置

  1. 在settings.py中配置允许外网访问的ip, 或者域名

    ALLOWED_HOSTS = ['139.199.81.62']   或者直接'*'
    
  2. 执行启动项目

    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
  1. 找到 nginx的默认配置文件,修改文件内容

     有以下两个文件配置, 我选择的是第二个
     # /etc/nginx/nginx.conf
     # /etc/nginx/sites-enabled/default
    
  2. 操作

    # 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 创建应用
  1. 在虚拟环境下, 下载Django

    • 指定版本号 : Django==1.8.2
    pip install -i https://pypi.doubanio.com/simple/ Django  
    
  2. 创建Django项目

django-admin startproject mysite
  1. 进入mysite, 创建packages.txt记录当前所用的所有包
pip freeze > packages.txt
  1. git拉取代码后安装重建包
pip install -r packages.txt -i https://pypi.doubanio.com/simple/
  1. 启动
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 创建应用程序
  1. 执行如下命令
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
    
  1. 此时在polls目录下创建 views.py文件编写如下

    from django.http import HttpResponse
    
    def index(request):
        return HttpRresonse('hello world!!')
    def myset(request):
        return HttpRresonse(request.GET)
    
  2. 在polls目录下的urls.py文件增加部分内容, 内容如下 :

    from django.urls import path
    from . import views
    
    urlpatterns = [
        path('', views.index, name="index"),
        path('/makelove', views.makeLove, name="index"),
    ]
    
  3. 在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
  1. 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(服务端开发使用)
  1. 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)

  1. 在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会寻找在厂景
  1. views.py,这是第一个(原始)情况下发生的情况

  2. views/__init__.py,这是第二种情况。在这里,__init__.py能够提供view1方法,因为它可以导入它。

使用这种解决方案,你可能无需更改import或更改urlpattern参数urls.py

如果每个新视图文件中都有许多方法,那么views/__init__.py使用导入可能会很有用*,如下所示:

from viewsa import *
from viewsb import *
12.6 设置静态文件存放vue打包好的文件

注意 : 仅仅开发环境下使用, 生产环境则需要设置nginx代理处理

  1. 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',
                ],
            },
        },
    ]
    
  2. 将打包好的静态文件中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
  1. 说明 :

    ajax发送一个请求, post会被forbidden,get不会,主要原因是csrf中间件, 需要注释掉, 在settings.py中找到 MIDDLEWARE

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',
]
  1. 获取值

    • 前端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

  • 类名字必须写死, 或者写以下几种 :
    1. __init__ : 服务器响应第一个请求
    2. process_request : 在产生url对象,进行url匹配之前调用
    3. process_view : 是url匹配之后, 调用视图函数之前
    4. process_response : 视图函数调用之后, 内容返回给浏览器之前
    5. 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.middleware.common.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安装服务
  1. 解压好软件放在桌面 (每次使用都要打开):

    链接: https://pan.baidu.com/s/1az_2rNfhceuQubkaDh1YJw 提取码: 9sza

  2. 然后双击 redis-server.exe 即可

12.11.1.1 安装驱动和设置与使用
  • 和下面 ubuntu 使用方法一样
12.11.2 ubuntu安装服务
12.11.2.1 安装
  1. 安装服务

    sudo apt-get install redis-server
    
  2. 安装驱动

    pip install django-redis
    
12.11.2.2设置
  1. 在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.net/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  })
    
  1. 封装一个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.com')
    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.com')
    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
  1. 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)

  1. 中间件中,验证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请求

注意点 :

  1. axios需要重新导入, 因为使用了axios拦截器的axios, 不能进行FormData数据传递, aixos默认用的是json,手动在axios中请求头中加入token
  2. 以下案例使用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")
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值