路飞项目的前期准备

软件开发流程

企业软件开发流程

# 真正的企业里软件从立项到交付整个过程
	-立项:确定公司要开发这个软件   公司高层
    	-软件来源
        	-产品经理设计出来的----》互联网项目      互联网公司
            -用户(医院,政府部门,企业。。)          传统软件公司
    -需求分析
        # 互联网项目
            -需求调研和分析:产品经理设计出来的
        # 传统软件
            -需求调研和分析:市场人员跟客户对接
    		-产品经理 ,开发人员跟客户对接,生成需求文档
	-原型设计:产品经理 
		-懂业务
        -画出原型图:app,网页款
    -分任务开发
    	-UI设计
        	-根据原型图设计 切图
    	-前端团队
            -前端拿着切图写代码(pc,小程序,移动端)
            -mock数据:搞假数据,先把功能开发出来
        -后端团队
        	-组里开会,需求文档和原型图,设计后台
        	-架构,数据库设计
            -分任务开发:用户,商品板块
        -测试(质量控制部)
        	-普通功能测试
            -接口测试
            -压力测试,jmeter
            -自动化测试
        -联调测试
        
    -项目上线(运维)
    
    -持续维护项目

后端开发,公司开发流程

# 作为后端开发,公司里开发的流程
	-开新项目,先开会,设计技术选型,数据库设计
    	-产品,原型图做好了
        -老大在项目管理平台(禅道)分配任务给我
        -进入到管理平台就能看到任务,相关功能的原型图
        	-需求,原型图,实现的效果
        -开发---有不明白的需求,找产品对接----》自测
        -提交到版本仓库(git,svn)
        -管理平台点完成
        -所有都开发完了,分支合并
        -跟前端联调
        -发版
    
    -如果是老项目
        	-老大在项目管理平台(禅道)分配任务给我
            -进入到管理平台就能看到任务,相关功能的原型图
                -需求,原型图,实现的效果
            -开发---有不明白的需求,找产品对接----》自测
            -提交到版本仓库(git,svn)

            -所有都开发完了,分支合并
            -跟前端联调
            -发版

image

路飞项目需求

关于路飞项目
	-商城类
	-知识付费项目
 		-主站vue
       -后台管理 simpleui
    
需求
	-首页功能
    	-首页轮播图
       -推荐课程
    -用户功能
    	-用户名密码登录
       -手机号验证码登录
    	-发送手机验证码
       -验证手机号是否注册过
    	-注册接口
       -查看用户信息(自己写)
    	-修改用户信息(自己写)
    -课程列表功能
    	-课程列表接口,课程列表展示
       -排序,过滤,分页
   	-课程详情
    	-课程详情接口
       -视频播放功能
    		-视频托管(第三方,自己平台)文件托管
       -下单功能
    		-支付宝支付,生成支付链接,付款,回调修改订单状态
       	  -购买成功功能

pip永久换源

pip3 install django
	-第三方开发者,开发了第三方模块,把模块打包传到了pypi上
 	-根据名字,把这个打包好的模块下载下来
   -以下在公司中出现的情况
		-公司不能上外网
    		-xx.whl 文件提交下好,再安装--》pip install 路径/xx.whl
          -已经有项目,模块装完了,想把这个项目所有的模块导出---》导入到别的项目
     	-可以顺利上外网
        	下载会很慢,因为在国外
            国内有些镜像站:建议用阿里云
          
Windows换源操作
"""换源操作"""
# 配置本地镜像站为阿里云,以后只要pip install 就是去阿里云下载
	- 1、文件管理器文件路径地址栏敲:%APPDATA% 回车,快速进入 C:\Users\电脑用户\AppData\Roaming 文件夹中
	-2、新建 pip 文件夹并在文件夹中新建 pip.ini 配置文件
	-3、新增 pip.ini 配置文件内容
        [global]
        index-url = https://mirrors.aliyun.com/pypi/simple
        [install]
        use-mirrors =true
        mirrors =https://mirrors.aliyun.com/pypi/simple
        trusted-host =mirrors.aliyun.com
MacOS、Linux换源操作
1、在用户根目录下 ~ 下创建 .pip 隐藏文件夹,如果已经有了可以跳过
	-- mkdir ~/.pip
2、进入 .pip 隐藏文件夹并创建 pip.conf 配置文件
	-- cd ~/.pip && touch pip.conf
3、启动 Finder(访达) 按 cmd+shift+g 来的进入,输入 ~/.pip 回车进入
4、新增 pip.conf 配置文件内容


[global]
index-url = https://mirrors.aliyun.com/pypi/simple
[install]
use-mirrors =true
mirrors =https://mirrors.aliyun.com/pypi/simple
trusted-host =mirrors.aliyun.com

虚拟环境

# 虚拟环境是什么?
	-有个系统环境  安装的python3.8 ,装模块,都装在 解释器文件夹的Lib\site-packages
    -现在有两个django项目,一个基于django3 写的,一个基于django2 写的
    -把两个项目都打开,同时开发
    -每个项目都用自己独立的环境,装的模块相互不影响
    -两种解决方案:
    	Virtualenv
        pipenv
        
        
# 如何安装和配置
	-1 安装两个模块
    	pip3 install virtualenv    # 虚拟环境是它
		pip3 install virtualenvwrapper-win # 对虚拟环境的加强,以后只需要简单的命令就可以使用和创建虚拟环境
    -2 配置虚拟环境管理器工作目录
    	-在环境变量中新建:WORKON_HOME: D:\Virtualenvs
        -在D盘创建文件夹,以后新建的虚拟环境,都会在这个文件夹下
   -3 去向Python3的安装目录 => Scripts文件夹 => virtualenvwrapper.bat => 双击
        
        
# 如何创建和使用虚拟环境
	-创建并进入到虚拟环境: 创建一个虚拟环境叫luffy,会放在D:\Virtualenvs
    	mkvirtualenv -p python3 luffy
    -cmd 窗口中带着虚拟环境名字,表示在虚拟环境中,以后安装的所有模块,都是给虚拟环境安装的
        
    -退出虚拟环境
    	deactivate
        
    -查看有哪些
    	workon
    -进入虚拟环境
    	workon luffy
        
    -删除虚拟环境
    	rmvirtualenv 虚拟环境名称
   


# 本地有了虚拟环境,pycharm使用虚拟环境
	-已有项目,配置虚拟环境如何做
    -新建项目,使用已有虚拟环境
		django-admin
        pycharm创建



# 了解 使用pycharm创建虚拟环境
	-新建项目,新建虚拟环境        

路飞项目前后端创建

# 创建路飞后端
	-创建路飞项目前,虚拟环境中先装好 django 3.2.2
    -选中虚拟环境,起名叫luffy_api
    
    
# 前端项目创建
	vue create luffy_city

包导入

模块和包的区别
	-模块就是一个py文件
  	-包是一个文件夹下有__init__.py里面有很多py文件
   -以后下载第三方包或自己写包,如何导入

python 导入包
	-pycharm会把项目路径加入到环境变量,命令行中不会加入
 	-from 的路径,需要从环境变量开始
    	-安装的第三方模块,都在环境变量
       -内置模块,os,sys也在环境变量中,可以直接导入
   -在包内部,推荐使用相对导入
		-一旦使用相对导入,该文件就不能以脚本形式运行了(不能右键运行)
    	-在同一个目录下的推荐使用相对导入
       -不同目录下的推荐使用绝对导入

后端项目调整目录

# 调整目录后成
"""
├── luffy_api
	├── logs/				# 项目运行时/开发时日志目录 - 包
    ├── manage.py			# 脚本文件
    ├── luffy_api/      		# 项目主应用,开发时的代码保存 - 包
     	├── apps/      		# 开发者的代码保存目录,以模块[子应用]为目录保存 - 包
        ├── libs/      		# 第三方类库的保存目录[第三方组件、模块] - 包
    	├── settings/  		# 配置目录 - 包
			├── dev.py   	# 项目开发时的本地配置
			└── prod.py  	# 项目上线时的运行配置
		├── urls.py    		# 总路由
		└── utils/     		# 多个模块[子应用]的公共函数类库[自己开发的组件]
    └── scripts/       		# 保存项目运行时的脚本文件,小的测试脚本 - 文件夹,不提交到git上
"""

调整后运行不了

1.原因:找不到配置文件---》django项目运行,第一步就要加载配置文件
 	-开发阶段:python manage.py run server---》找不到配置文件就报错---》开manage.py
   os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'djangoProject14.settings.dev')
# 这里的sev其实是原来的settings配置改名后的文件
	 -上线阶段:uwsgi运行----》
        asgi.py
        wsgi.py
   os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'luffy_api.settings.prod')

2.项目能运行
	-创建app
    -python manage.py startapp home 命令在哪执行,app就创建在哪
    -cd到apps路径下创建app
    	-python ../../manage.py startapp app名字
        
    -注册app
    	-首先在app下的apps.py修改name(后面就可以不改了)
     
    -以后想直接写app名字,所以要把apps的路径加入到环境变量中,加载配置文件的一开始
    -在配置文件中把apps和小路飞路径加入到环境变量
    BASE_DIR = Path(__file__).resolve().parent.parent  # 小项目的路径
    path = os.path.join(BASE_DIR, 'apps')  # 将apps的路径加入小项目的路径中
    sys.path.insert(0, path)  # 将apps的路径加入系统环境变量
    sys.path.insert(0, BASE_DIR)  # 将小羡慕的路径添加系统环境变量
    
-导入模块,编辑机爆红,爆红不一定是真的错
	-把加入到环境变量的路径,右键,做为source root

后台日志封装

项目肯定要记录日志的
    -日志可以打印到控制台
    -日志可以写到日志文件中
    -日志存到某个库中
    -所有项目日志统一管理 sentry:django写的服务,收集日志的
  
# 以后,在项目中不要出现print了,以后都用日志 logger.info(),以后项目上线,只需要调整日志级别,低级别的日志就不打印了,于是日志输出不用删掉

操作步骤:django中集成日志步骤,django使用的就是python内置的日志模块
    
    -1.在配置文件中加入日志配置  ---大字典
    -2.utils新建 common_logger.py,得到日志对象
    	import logging 
       logger = logging.getLogger('django')
   	-3.在任意想用日志的地方,导入使用即可
    	from utils.comment_logger import logger
      	logger.info('info级别的日志')
    	 logger.error('error级别的日志')
            

日志配置代码

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': 'INFO',
            'filters': ['require_debug_true'],
            'class': 'logging.StreamHandler',
            'formatter': 'simple'
        },
        'file': {
            # 实际开发建议使用ERROR
            'level': 'WARNING',
            '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,  # 是否让日志信息继续冒泡给其他的日志处理系统
        },
    }
}

前后端分析的rbac项目演示

# 后台:https://gitee.com/liuqingzheng/rbac_manager
# 前端:https://gitee.com/liuqingzheng/vue_admin

全局异常处理封装

前端 要接收的格式,要统一无论后端是否出错

三大认证,视图类的方法只要出了异常,就会执行一个函数,但是这个函数只能处理drf异常---》我们需要自己写个函数,既能处理drf异常,又能处理django异常,这样统一返回格式,前端看到格式都统一

使用步骤:
    1.在utils中新建 common_exceptions.py
    2.写个函数
    3.配置文件,以后只要出了异常,都会走咱们的函数
    4.REST_FRAMEWORK = {
            'EXCEPTION_HANDLER': 'utils.common_exceptions.exception_handler',
        }
    5.勇敢大胆写代码,即便报错,程序不会蹦,并且会记录日志,并且处理成统一格式

全局异常处理代码

from rest_framework.views import exception_handler as drf_exception_handler
from rest_framework.response import Response
from .common_logger import logger


def exception_handler(exc, context):
    # 记录日志:哪个ip地址,用户id是多少,访问哪个路径,执行哪个视图函数,出了什么错
    # 获取当前用户的request对象
    request = context.get('request')
    # 获取用户访问的视图
    view = context.get('view')
    # 获取用户的ip地址
    ip = request.META.get('REMOTE_ADDR')
    # 获取用户的id
    user_id = request.user.pk
    # 获取用户访问的路径
    path = request.get_full_path()
    # 执行原来的drf异常捕获
    response = drf_exception_handler(exc, context)
    # 如果有值,则证明是drf的异常,原来的函数返回的是一个response对象
    if response:
        logger.warning('drf出了异常,异常是【%s】' % str(exc))
        res = Response({'code': '999', 'msg': response.data.get('detail')})
    # 没有值,则证明是其他异常
    else:
        logger.error('用户【%s】,ip地址【%s】,访问地址为【%s】,执行视图函数为【%s】,出错是【%s】' % (user_id, ip, path, view, str(exc)))
        res = Response({'code': '101', 'msg': '服务器异常,请联系管理员'})
    return res

封装Response

本身drf有Response,但是有的公司会规定,前端收到的格式都是固定的
    -{'code':'100','msg':{'data':}}
    -{code:100,msg:提示,token:asdfasd,user:lqz}
 
对Response进行封装,封装后,code,msg可以不传,不传就用默认的

使用步骤:
    1.在utils下新建common_response.py
    2.封装APIResponse
    3.导入使用,视图函数的办法,返回时,都使用自己的

封装的代码

from rest_framework.response import Response


class APIResponse(Response):
    def __init__(self, code=100, msg='成功', status=None, headers=None, **kwargs):
        data = {'code': code, 'msg': msg}
        # 如果kwargs有值,证明接收到了token或者其他的什么字典
        if kwargs:
            data.update(kwargs)  # 这里使用字典更新的方法
        super().__init__(data=data, status=status, headers=headers)  # 子类调用父类的方法

luffy数据库创建

创建用户创建库

创建luffy数据库
之前项目操作数据库,都是使用root用户,root用户权限太高了,在公司里,一般不会给你root用户权限

# 如果开发人员是root权限,数据安全性就很差

# 开发人员,专门创建一个用户,用户只对当前项目的库有操作权限

# 创建一个luffy库,创建luffy用户,luffy用户支队luffy库有操作权限

创建luffy数据库
"""
1.管理员连接数据库
mysql -uroot -p

2.创建数据库
create database luffy default charset=utf8

3.查看用户
select user,host,password from mysql.user;
只有root用户,要创建luffy用户

5.7版本往后查看用户:
select user,host,authentication_string from mysql.user;
"""

创建路飞用户,授予luffy库所有权限
"""
设置权限账号密码:grant 权限(create,update) on 库.表 to '账号'@'host' identified by '密码'

1.配置任意ip都可以连入数据库的账户
grant all privileges on luffy.* to 'luffy'@'%' identified by 'Luffy123?';

2.由于数据库版本的问题,可能本地还连接不上,就给本地用户单独配置
grant all privileges on luffy.* to 'luffy'@'localhost' identified by 'Luffy123?';

3.刷新一下权限
>: flush privileges;

只能操作luffy数据库的账户
账号:luffy
密码:Luffy123?
"""

使用项目连接库

# 项目操作mysql,需要安装模块
	-pymysql
    -mysqlDB
    -mysqlclient
    
    -历史:原来py2上有个操作mysql的模块叫mysqlDB,但到py3,没有支持py3,django默认使用这个模块去连接mysql,默认使用-mysqlDB连接,-mysqlDB不支持py3,运行报错
    -我们使用pymysql,作为连接mysql的数据库模块,但是需要加代码
    	imprort pymysql
        pymysql.install_as_mysqldb()  # 猴子补丁
        
    -django 2.2.2以后,还使用pymysql,需要改djagno源代码
    
    -统一使用mysqlclient来作为操作mysql的底层库
    	-基于py2的mysqldb,在py3上重新了,但是名字改成了mysqlclient
    -使用mysqlclient,只需要安装这个模块,不需要再写任何代码,直接用即可
    
    -但是:mysqlclient 这个模块,不好装
    	-win 一般人品好,人品好,pip install mysqlclient
        -人品不好,装不了,centos部署项目,后面会讲centos上如何装
        
        
# mysqlclient
pip install mysqlclient

###### 配置文件修改,连接mysql,使用路飞用户


# 用户名密码写死在代码中了,保证安全
name = os.environ.get('LUFFY_NAME', 'luffy')
password = os.environ.get('LUFFY_PASSWORD', 'Luffy123?')
# 拓展:有的公司,直接有个配置中心---》服务--》只用来存放配置文件

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'luffy',
        'USER': name,
        'PASSWORD': password,
        'HOST': '127.0.0.1',
        'PORT': 3306
    }
}

软件开发模式

# 瀑布模式:bbs项目就是按照这种模式
	-需求分析---》设计--》创建数据库 所有都创建---》开发(3个月)---》交给测试--》测试通过---》上线
	
# 敏捷开发
	-需求分析---》设计---》只设计一个板块---》开发(2周)---》交给测试---》运维上线(测试环境)
    -设计---》只设计一个板块---》开发(2周)---》交给测试---》运维上线(测试环境)
	
    -一个sprint周期
    -scrum敏捷项目管理

image

User模块用户表

# 你决定使用auth表扩写,项目一定不要先迁移,先建好用户表再迁移
	已经迁移完了,再想用auth的user表
    -删库,删迁移文件所有app
    -删admin和auth的迁移文件
    
    
# 用户表使用auth表扩写  pip install Pillow
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


# 遇到的问题,明明小luffyapi已经加入到环境变量,程序运行没问题,但是表迁移,就报错,找不到模块
	-打印了看一下,确实环境变量有,但是不是个字符串,是个对象
    -程序运行,是没问题
    -迁移有问题:配置文件中转成字符串,就解决了

django的配置文件

# pathlib   # 3.6 以后,处理文件路径的模块,原来是os,



# 面试题,md5是对称加密还是非对称加密
	-对称加密:加密的秘钥和解密的秘钥是同一个
    -非对称加密:加密使用公钥加密,解密使用私钥解密,使用公钥是不能解密的
    -摘要算法:没有解密这一说
    
    
    
# 运行django ,泡在0.0.0.0上,局域网内,所有人都能访问
from pathlib import Path
import os
import sys

BASE_DIR = Path(__file__).resolve().parent.parent  # 小项目的路径
path = os.path.join(BASE_DIR, 'apps')  # 将apps的路径加入小项目的路径中
sys.path.insert(0, path)  # 将apps的路径加入系统环境变量
sys.path.insert(0, str(BASE_DIR))  # 将小羡慕的路径添加系统环境变量

# 秘钥,涉及到加密的django中,都会用它
SECRET_KEY = 'django-insecure-=4$gy3wqi9q3!&_%)ff#6zmelv3+iyjwe8u9vmgnipp@jien9n'
# 项目是以debug模式运行,还是非debug模式运行
# 项目上线,要改成false
# debug=True,代码可以热更新
# 挑食模式下,对开发者更友好,可以列出所有路径,报了错,前端能看到
DEBUG = True
# 它搭配debug=False,它的意思是,允许我的项目部署在哪个ip地址上,* 表示允许部署在所有地址上
# ALLOWED_HOSTS = ['*']

ALLOWED_HOSTS = []

# jango是多个app组成的,里面配置app,默认带的app,django内置的app
# django是一个大而全的框架,有很多内置app
# admin是后台管理
# auth是权限管理
# contenttypes表中存app表的关系
# sessions 里面有session表,django的session相关
# messages 消息框架,flask讲闪现,是一样的东西
# staticfiles:静态文件资源
INSTALLED_APPS = [
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions 里面有session表,django的session相关
    'django.contrib.messages',
    'django.contrib.staticfiles',
    
    'home',
    'user',
    'rest_framework',
]
# 中间件
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    # 安全相关中间件
    'django.contrib.sessions.middleware.SessionMiddleware',
    # session相关中间件
    'django.middleware.common.CommonMiddleware',
    # 路由地址带不带/问题
    'django.middleware.csrf.CsrfViewMiddleware',
    # scrf认证,生成scrf串
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    # 用户认证相关
    'django.contrib.messages.middleware.MessageMiddleware',
    # 消息框架相关
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
# 根路由
ROOT_URLCONF = 'djangoProject14.urls'

# 模板文件,一般前后端混合使用
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [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',
            ],
        },
    },
]

# 项目运行的配置---》项目上线运行,使用uwsgi运行,执行application()
WSGI_APPLICATION = 'djangoProject14.wsgi.application'

# 数据库用户名密码卸载在代码中,保证安全
name = os.environ.get('LUFFY_NAME', 'luffy')
password = os.environ.get('LUFFY_PASSWORD', 'Luffy123?')
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'luffy',
        'USER': name,
        'PASSWORD': password,
        'HOST': '127.0.0.1',
        'PORT': 3306
    }
}


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',
    },
]

# 国际化
LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# 静态资源
STATIC_URL = '/static/'



DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

# 日志配置
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': 'INFO',
            'filters': ['require_debug_true'],
            'class': 'logging.StreamHandler',
            'formatter': 'simple'
        },
        'file': {
            # 实际开发建议使用ERROR
            'level': 'WARNING',
            '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,  # 是否让日志信息继续冒泡给其他的日志处理系统
        },
    }
}
# 全局异常
REST_FRAMEWORK = {
    'EXCEPTION_HANDLER': 'utils.common_exceptions.exception_handler',
}
# 自定义auth表
AUTH_USER_MODEL = 'user.User'

开启media访问

# 配置文件加入
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

# 总路由中设置
# re_path('^media/(?P<path>.*)', serve, {'document_root': settings.MEDIA_ROOT})
path('media/<path:path>', serve, {'document_root': settings.MEDIA_ROOT})
# 访问
http://127.0.0.1:8000/media/icon/default.png
        
        
# 以后使用djagno的配置文件都用这个
from django.conf import settings

扩展

# 期终架构相关
	-前端---》看人家开源的前端项目,看不懂
    -第一种情况,vue+java====》分析有哪些接口,drf复写出来
	-第二种情况: 你新建前端项目,你看到它哪个页面好看,copy你里面去只要template和style  
    	-js东西自己写


# https://zhuanlan.zhihu.com/p/370167569


# windows安装 mysql 5.7
https://zhuanlan.zhihu.com/p/571585588

老刘项目演示

# 登录
# 系统管理
	-用户管理
    -角色管理
    -菜单管理
    -部门管理
    -岗位管理

# 最核心
	-创建了用户,授予了角色,因为角色有权限,这个用户就有权限
    -如果这个用户有权限,进入到系统,就能看到相关的操作,如果没有权限,就不能操作

路飞前台全局css,全局配置文件

整理项目

App.vue

<template>
  <div id="app">
    <router-view/>
  </div>
</template>

router/index.js

const routes = [
  {
    path: '/',
    name: 'home',
    component: HomeView
  },
]

HomeView.vue

<template>
  <div class="home">
    <h1>首页</h1>
  </div>
</template>

<script>

export default {
  name: 'HomeView',
}
</script>

全局css

正常写前端项目,需要去掉所有标签的默认样式,css

第一步:在assets文件下新建一个css文件---新建global.css
 
/* 声明全局样式和项目的初始化样式 */
body, h1, h2, h3, h4, h5, h6, p, table, tr, td, ul, li, a, form, input, select, option, textarea {
    margin: 0;
    padding: 0;
    font-size: 15px;
}

a {
    text-decoration: none;
    color: #333;
}

ul {
    list-style: none;
}

table {
    border-collapse: collapse; /* 合并边框 */
}

# 第二步:全局生效 main.js中配置
// 使用全局css样式,只需要导入就会生效
import '@/assets/css/global.css'

全局js

想后端发送请求,请求地址测试阶段 127.0.0.1::8000 ---》后期上线,地址要变,如果在组件中把地址写死,以后要改每个都要改
        
写一个全局js,js中有个url地址,以后所有组件中发送请求时,都是用这个url地址

# 导入导出

使用步骤:
    1.新建:在assets文件下新建js文件---》新建setthings.js
    	export default {
        BASE_URL:'http://127.0.0.1:8000/api/v1'
    }
    2.在main.js中引入
    	//引入settings.js 把setting对象放入到vue的原型中
       import settings from "@/assets/js/settings";
    	Vue.prototype.$settings = settings
       //以后在任意组件中只需要  this.$settings.BASE_URL
    3.在任意组件中使用
    	this.$settings.BASE_URL
    this.$axios.get(this.$settings.BASE_URL+'/users').then(res=>{     
    })

安装axios

跟后端交互

# 使用步骤:
	1.安装:cnpm install axios -S
 	2.把axios放到vue原型中,main.js中
      import axios from "axios";
		Vue.prototype.$axios=axios
    3.在任意组件中使用
    	this.$ajax.get()

安装vue-cookies

后期登录成功,token存在cookie中

使用步骤:
    1.安装:cnpm install vue-cookies -S
    第二步:把vue-cookies放到vue原型中,main.js中
    	import cookies from "vue-cookies";
		Vue.prototype.$cookies=cookies
    第三步:在任意组件中使用
        this.$cookies.set()
        this.$cookies.set()

安装elementui

# 样式,使用elementui
# 使用步骤:
	第一步:安装 cnpm install element-ui -S
    第二步:main.js配置
    import ElementUI from 'element-ui';
	import 'element-ui/lib/theme-chalk/index.css';
    Vue.use(ElementUI);
    第三步:复制,粘贴

后台主页模块表设计

# 分析完原型图,首先要写接口

    -轮播图接口
    -推荐课程接口(暂时没写)
    -推荐老师接口(无)
    -学员评论(无)
 
创建首页app,home
    -来到apps文件夹下执行
    -python ../../manage.py startapp home
    -创建表model,轮播图表Banner
    
    
创建表步骤;
	1.因为有些字段是多个表都要写字段,所以我们将这些字段统一写在一个父类中,在utils下创建common_model.py
    from django.db import models
        class BaseModel(models.Model):
            created_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
            updated_time = models.DateTimeField(auto_now=True, verbose_name='最后更新时间')
            is_delete = models.BooleanField(default=False, verbose_name='是否删除')
            is_show = models.BooleanField(default=True, verbose_name='是否上架')
            orders = models.IntegerField(verbose_name='优先级')

            class Meta:
                abstract = True  # 只用来继承,不用来在数据库创建
     2.在home的app的model.py写模型类
    	class Banner(BaseModel):
        # 哪些字段:真正图片地址,标题,跳转链接,图片介绍       是否删除(软删除),是否显示,优先级,创建时间,更新事件:公共字段
            title = models.CharField(max_length=16, unique=True, verbose_name='名称')
            image = models.ImageField(upload_to='banner', verbose_name='图片')
            link = models.CharField(max_length=64, verbose_name='跳转链接')
            info = models.TextField(verbose_name='详情')

            class Meta:
                db_table = 'luffy_banner'
                verbose_name_plural = '轮播图表'

            def __str__(self):
                return self.title
            
	-3.迁移
    	python manage.py makemigrations
		python manage.py migrate

后台主页模块轮播图接口

轮播图接口,给首页用

视图层

from rest_framework.viewsets import GenericViewSet
from rest_framework.mixins import ListModelMixin
from .models import Banner
from .serializer import BannerSerializer
from utils.common_response import APIResponse


class BannerView(GenericViewSet, ListModelMixin):
    queryset = Banner.objects.filter(is_delete=False, is_show=True).order_by('orders')
    serializer_class = BannerSerializer

    def list(self, request, *args, **kwargs):
        res = super().list(request, *args, **kwargs)
        return APIResponse(data=res.data)  # {code:100,msg:成功,data=[{},{}]}

序列化类

from rest_framework import serializers
from .models import Banner


# Form类和ModelForm的区别

class BannerSerializer(serializers.ModelSerializer):
    class Meta:
        model = Banner
        fields = ['id', 'image', 'title', 'link']

路由

from rest_framework.routers import SimpleRouter
from . import views

router = SimpleRouter()
# 访问 http://127.0.0.1:8000/api/v1/home/banner   ---->get 请求就可以查询所有轮播图
router.register('banner', views.BannerView, 'banner')

urlpatterns = [

]
urlpatterns += router.urls

录入数据

# 主站前后分离

# 后台管理使用django的admin做的---》simpleui

# 使用步骤;
    	 1.安装simplenui:pip install django-simpleui
        2.注册app:'corsheaders',
        3.在home文件下admin.py中注册Banner表
        	from django.contrib import admin

            from .models import Banner
            admin.site.register(Banner)
         4.录入数据:http://127.0.0.1:8000/admin

跨域问题详解

前端发送ajax请求,到后端,会有跨域的拦截
出现的原因
同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现
	-请求的url地址,必须跟浏览器上的url地址处于同域上,也就是域名,端口,协议相同
	-发送ajax请求的地址,必须跟浏览器上的url地址处于同域上,域[域名,地址,端口,协议]
 	-请求成功,数据库返回,但是浏览器拦截
 
补充:浏览器中输入域名:没有加端口
        -www.baidu.com---->dns--->解析成地址  192.168.2.3----》没有加端口,默认是80
        -dns解析,先找本地的host文件
        -可以修改本地的host做映射
  
cors:scc.scrf
	-跨域资源共享:后端计数,就是在响应头中加入固定的头,就会运行前端访问了
        
CORS基本流程
浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。
浏览器发出CORS简单请求,只需要在头信息之中增加一个Origin字段。
浏览器发出CORS非简单请求,会在正式通信之前,增加一次HTTP查询请求,称为”预检”请求(preflight)。浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错


# 什么是简单请求,什么是非简单请求?
# 符合如下条件,就是简单请求
	(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,如果运行,再发真正的
 

自己解决跨域问题---》中间件
from django.utils.deprecation import MiddlewareMixin
class CorsMiddleWare(MiddlewareMixin):
    def process_response(self,request,response):
        if request.method=="OPTIONS":  # 解决非简单请求的请求头
            #可以加*
            response["Access-Control-Allow-Headers"]="*"

        # 允许前端的地址,所有请求头允许
        response["Access-Control-Allow-Origin"] = "*"
        return response

第三方模块解决跨域问题

1.安装:
    pip install django-cors-headers
2.配置APP
	INSTALLED_APPS = [
        'corsheaders'
    ]
3.配置中间件
	MIDDLEWARE = [
        'corsheaders.middleware.CorsMiddleware',
    ]
4.在配置文件配置
# 允许所有域
CORS_ORIGIN_ALLOW_ALL = True
# 允许的请求方式
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',
	'token',
)

补充

# 以后在公司里,
	后端一个项目
    前端多个项目:主站一个,后台管理一个,app一个,小程序一个
    
    
 	前端一个项目
    后端多个项目
posted @ 2023-02-24 17:09  雪语  阅读(36)  评论(0编辑  收藏  举报