路飞项目前置准备

软件开发流程

真正的企业里软件从立项到交付整个过程

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

-持续维护项目

作为后端开发,公司里开发的流程

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

-如果是老项目
    	-老大在项目管理平台(禅道)分配任务给我
        -进入到管理平台就能看到任务,相关功能的原型图
            -需求,原型图,实现的效果
        -开发---有不明白的需求,找产品对接----》自测
        -提交到版本仓库(git,svn)

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

路飞项目需求

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

路飞项目开始

准备工作

1,pip永久换源

打开我的电脑地址栏 输入 %APPDATA% 回车
进入:C:\Users\李啊鸡\AppData\Roaming 目录中

新建pip文件夹并在文件夹中新建pip.ini 配置文件

复制下列内容到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

以后直接pip install 就不用切换源了

2.虚拟环境

两个django项目基于不同的django版本同时开发,每个项目都用自己的独立环境,装的模块互不影响。就要使用虚拟环境。

两种解决方案:
Virtualenv
pipenv

Virtualenv 方案创建虚拟环境

需要安装两个模块

pip install virtualenv    # 虚拟环境是它
pip install virtualenvwrapper-win # 对虚拟环境的加强,以后只需要简单的命令就可以使用和创建虚拟环境

配置虚拟环境变量

我的电脑右键属性-高级设置-环境变量

在环境变量中新建:WORKON_HOME: D:\Virtualenvs
去D盘目录下创建文件夹,以Virtualenvs命名
以后新建的虚拟环境都会在这个文件下
python3 的安装目录下的Scripts文件夹
有一个名为  virtualenvwrapper.bat 的批处理文件
双击运行
创建虚拟环境

cmd执行

mkvirtualenv -p python38 luffy(luffy是虚拟环境的名字)

创建完成后会放在D:\Virtualenvs目录下,并进入虚拟环境

观察cmd命令行前面 会有显示
eg:
    (luffy) C:\Users\李啊鸡>
有则表示在虚拟环境中,以后安装的所有模块,都是给虚拟环境安装的

退出虚拟环境

deactivate
使用虚拟环境

退出虚拟环境后下次进入虚拟环境可以使用

workon # 查看有哪些虚拟环境
workon luffy(环境名)  # 进入虚拟环境

删除虚拟环境

rmvirtualenv 虚拟环境名称

pycharm创建虚拟环境

image

已有项目使用虚拟环境,切换虚拟环境的解释器

image

3,使用pycharm创建虚拟环境路飞项目

image

注意如果下侧有黄色提示说明该虚拟环境中缺少django模块,需要自己去下载在创建如果直接创建就会下载最新版的django

4,创建路飞前端项目

vue create luffy_city

5.包的导入问题

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

6.后端项目调整目录

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

7,开发阶段

调整完目录后运行项目会报错,报错问题处理

python manage.py runserver  # 运行项目

原因是我们把settings文件改成dev了,django运行的时候就会去找settings文件

修改manage.py 的settings.py 目录

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'luffy_api.settings')
修改成
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'luffy_api.settings.dev')

image

DJANGO_SETTINGS_MODULE=luffyapi.settings.dev

解决问题。

8,上线阶段

修改wsgi.py与asgi.py 文件中的路径

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'luffy_api.settings.prod')

9,创建app

我们可以选择在根路径创建app后拖入apps文件夹内,也可以通过cd切换到apps文件夹路径内进行创建app。

cd luffy_api
cd apps
python ../../manage.py startapp home  # 因manage.py 文件在根目录所以需要../.. 

创建好app后我们在dev文件内注册app 发现报错。原因是apps的路径不在环境变量中

 'luffy_api.apps.home',  # 可以这样导,但是太长,有简写
'luffy_api.apps.user'

可以直接写成这样,只需要把apps路径加入到环境变量

'home',
'user'
注意:
 app目录下的apps.py 文件内也得修改 name改成 name & name 改成home

# 加入环境变量----配置文件中的开始(最上面)dev.py
from pathlib import Path
import sys,os
BASE_DIR = Path(__file__).resolve().parent.parent  # dev的父目录settings的父目录小路飞的路径
sys.path.insert(0,os.path.join(BASE_DIR,'apps'))
# 把小路飞也加入到环境变量中
"""方便使用 form home import views   
但是不加也可以使用 form luffy_api.apps.home import views"""
sys.path.insert(0,os.path.join(BASE_DIR))
print(sys.path)

但是我们在导入apps下的app时pycharm解释器会给我们爆红,但是其本身是没有问题的。

解决爆红问题

image

后台日志封装

项目肯定要打印日志,日志可以打印到控制台,也可以写到文件中,或者保存到库里。

所有项目日志都可以统一管理 使用sentry

sentry:django写的服务,收集日志的,可以展示 开源的

我们这里不用这个但是有空需要看一下

操作步骤

1,配置文件中加入配置
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,  # 是否让日志信息继续冒泡给其他的日志处理系统
        },
    }
}
2.utils下新建 common_logger.py 得到日志对象
import logging
logger = logging.getLogger('django')
3.导入后再视图方法内使用
logger.info('info级别的日志')
logger.error('error级别的日志')

全局捕捉异常

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

drf的三大认证,视图类的方法中只要出了异常,就会执行一个函数,但是这个函数只能处理drf的异常

我们需要自己写个函数既能处理drf异常,又能处理django异常

使用步骤

记得配路由哦

1.在utils中新建 common_exceptions.py 写个函数
from rest_framework.views import exception_handler as drf_exception_handler
from rest_framework.response import Response
from utils.common_logger import logger


# 只要知道这个函数一定出错了,就要记录日志
def exception_handler(exc, context):
    # 1.记录日志 记录详细
    # context 里有request和view
    request = context.get('request')
    view = context.get('view')
    ip = request.META.get('REMOTE_ADDR')
    user_id = request.user.id
    if not user_id:
        user_id = '匿名用户'
    path = request.get_full_path()
    response = drf_exception_handler(exc, context)
    if response:
        # drf 的异常 已经处理过
        logger.warning(f'drf出了异常,问题是:{str(exc)}')
        # drf的异常已经被drf三大认证处理了,response.data里的detail里有错误信息,直接取可能会有问题 碰到在解决
        res = Response({'code': 999, 'msg': response.data.get('detail', '服务器异常,请联系管理员')})

    else:
        # django的异常需要我们自己处理详细一点
        logger.error(f'用户:{user_id},ip地址为:{ip},访问地址为:{path},执行视图函数为:{str(view)},出错问题是:{str(exc)}')
        # django的异常我们自己处理,后续报错我们可以根据时间去日志里查找详细信息
        res = Response({'code': 888, 'msg': '服务器异常,请联系系统管理员'})
    return res
2.导入使用

视图函数的方法报错返回时的数据格式,都使用咱们自己的

# 测试全局异常处理
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.exceptions import APIException


class TestException(APIView):
    def get(self, request):
        # # drf报错
        # raise APIException('drf出了异常')
        # 未知错误
        # l = [1,2]
        # print(l[3])
        # django的错误
        raise Exception('django抛异常')
        return Response('ok')

封装APIResponse

本身drf就有Response 但是根据公司规定前端收到的格式必须是固定格式

eg:

{'code':100,'msg':'错误提示',data:{}}
{'code':100,'msg':'错误提示','token':dasd213asd123f,data:{}}

封装后code,msg就不需要传了,使用默认的

开始封装

在utils中新建common_response.py复制下列代码放入

记得配路由哦

# 继承drf的Response 在其基础之上继续封装
from rest_framework.response import Response

"""
使用APIResponse()返回数据前端收到{'code':100,'msg':'成功'}
APIResponse(token=token,username='lxj'),----》前端收到{'code':100,'msg':'成功','token':dasda231314,'username':lxj}
"""
class APIResponse(Response):
    def __init__(self,code=100,msg='成功',status=None,headers=None,**kwargs):
        # 如果不传 data就等于默认的,传了就用新传的
        data = {'code':code,'msg':msg}
        # 判断kwargs里有传入数据没,有则传入了非code,msg,status,headers,之外的数据都要返回给前端
        if kwargs:
            # data里有一样的就替换,不一样的往data添加进去
            data.update(kwargs)
        # "子类调用父类的方法"完成初始化
        super().__init__(data=data,status=status,headers=headers)
导入使用
# 测试APIResonse
from rest_framework.views import APIView
from utils.common_response import APIResponse
class TestAPIResponse(APIView):
    def get(self,request):

        # return APIResponse(token='213da',username='lxj')
        """
        {
    "code": 100,
    "msg": "成功",
    "token": "213da",
    "username": "lxj"
        }
"""
        # return APIResponse(code=101,msg='错误')
        """
        {
    "code": 101,
    "msg": "错误"
}
        """
        return APIResponse(data=[{'name':'lxj','age':18}])
    """
    {
    "code": 100,
    "msg": "成功",
    "data": [
        {
            "name": "lxj",
            "age": 18
        }
    ]
}
    """

luffy数据库创建

在实际情况中root权限太大,在公司里一般不会给到你。

创建一个luffy库,创建luffy用户,luffy用户只对luffy库有操作权限


1.管理员连接数据库
>: mysql -uroot -proot

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

3.查看用户
>: select user,host,password from mysql.user; 
只有root用户,要创建luffy用户
%      代表所有ip远程方式都能连
localhost 代表只能本地连

# 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.* = luffy库所有表
to 'luffy'@'%' = @ 访问地址   %允许远程访问
identified by 'Luffy123?'; 密码
            """
>: 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 -uluffy -p  本地连
mysql -uluffy -h 127.0.0.1 -p 远程联

一个是直接连,一个是通过网卡连

项目连接mysql

# 项目操作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

安装mysqlclient

pip install mysqlclient

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

import os
# 为了数据的安全一般从环境变量中配置好用户名与密码,然后取出来,后面可以随便写 是前面娶不到就用后面的,为了安全不能填写真实的
环境变量添加:
"""LUFFY_NAME = name
LUFFY_PASSWORD = password"""
name = os.environ.get('LUFFY_NAME', 'luffy')
password = os.environ.get('LUFFY_PASSWORD', 'Luffy123?')  # 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周)-->交给测试-->运维上线(测试环境)

image

sprint周期就是敏捷开发周期

User模块用户表

用户表使用auth表扩写

from django.db import models
from django.contrib.auth.models import AbstractUser
# Create your models here.
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

"""
记得迁移前:在配置文件中替换
AUTH_USER_MODEL = 'user.user'"""
# 大家遇到的问题,明明小luffyapi已经加入到环境变量,程序运行没问题,但是表迁移,就报错,找不到模块
    -迁移有问题:配置文件中把小路飞的path环境变量转成字符串添加到sys.path中,就解决了
    
    我没报错哦

开启媒体目录media访问

配置文件添加以下代码

MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

路由设置

from django.urls import path,re_path
from django.views.static import serve
from django.conf import settings
# 第一种方法
re_path('^media/(?P<path>.*)', serve, {'document_root': settings.MEDIA_ROOT})
# 第二种方法
path('media/<path:path>', serve, {'document_root': settings.MEDIA_ROOT})
posted @ 2023-02-24 20:02  李阿鸡  阅读(34)  评论(0)    收藏  举报
Title