路飞项目---day03(后台日志封装,全局异常处理封装,封装Response,luffy数据库创建,用户创建,连接数据库,创User用户表,djagno的配置文件详解,开启media访问)

数据库密码防止忘了
root用户 mysql -uroot -p222

luffy用户 mysql -uluffy -p123 # 改密码看最下面的老刘博客

数据库升级原库里面文件不丢的操作,见之前的mysql专栏介绍
.
.
.

上节回顾

#1 公司里软件开发规范
	-作为后端的开发流程
    -禅道
    
    
# 2 路飞需求分析
	-首页板块
    -用户板块
    -课程列表板块
    -课程详情版块
    -支付板块
    -下单板块
    
    
# 3 pip 换源

# 4 虚拟环境
	-两个模块
    	virtualenv----》virtualenv.exe 用来创建虚拟环境
        virtualenvwrapper-win---》virtualenvwrapper.bat 批处理文件,命令简化
    -命令:创建,查看,进入,退出虚拟环境
    -pycharm中使用虚拟环境
    -环境变量:在cmd窗口中,敲命令,能够执行,在当前路径下有这个命令,环境变量中有
    	-D:\Python38\Scripts  已经被加到环境变量
        -同学问题:
        	-python2
            -python3.8    python3.8   pip3.8
            -python3.9
            -python3.10
            -虚拟环境

            -python3
            -pip3

# 5 创建路飞前后台
	-后台---》pychram 在虚拟环境上先把django 3.2.2装好 ;django-admin创建项目,切换到虚拟环境中
    -前台

# 6 包导入
	- from 或者 import  路径必须从环境变量开始  sys.path
    - 相对导入(相对于执行的脚本文件),绝对导入(根是环境变量)

    -包下都有个 __init__.py ---》
    	-requests----》 import requests---》把init导入了---》requests.能点出来的都是init中的

     -咱们写包,想给外部用的,都在init中注册一下,以后别人用,简单


# 7 调整目录
	- 目录结构调整,做的清晰一些
    	-配置文件路径变了,现在不能运行了---》修改路径
        	-开发阶段  manage.py
            -上线阶段  wsgi.py  asgi.py
   -创建app都在 apps文件夹下,想注册,只写app名字
		-把apps路径加入到环境变量
   -项目根路径(小路飞路径),加入到环境变量

.
.
.
.
.

今日内容

1 后台日志封装

# 以后,项目肯定要记录日志
	-日志都可以打印到控制台
	-日志可以写到日志文件中
	-日志存到某个库中
	-所有项目日志统一管理    sentry:django写的服务,收集日志的,可以展示  开源的

# 以后,在项目中不要出现print了,以后都用日志 logger.info(),以后项目上线,
# 只需要调整日志级别,低级别的日志就不打印了,于是日志输出不用删掉

-----------------------------------------------

# 操作步骤:django中集成日志步骤,django使用的就是python内置的日志模块
	-第一步:在配置文件中加入 日志配置 ---大字典
        详情见项目配置文件

	-第二步:在utils新建 common_logger.py ,得到日志对象
        import logging
        logger = logging.getLogger('django')

	-第三步:在任意想用日志的地方,导入使用即可
        from utils.common_logger import logger
        logger.info('info级别的日志')
        logger.error('error级别的日志')

.
.

# 日志的配置
# 真实项目上线后,日志的打印与记录级别不能过低,日志的记录属于io操作

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'verbose': {
            'format': '%(levelname)s %(asctime)s %(module)s %(lineno)d %(message)s'
        },
        'simple': {
            'format': '%(levelname)s %(module)s %(lineno)d %(message)s'
        },
    },
    'filters': {
        'require_debug_true': {
            '()': 'django.utils.log.RequireDebugTrue',
        },
    },
    'handlers': {
        'console': {
            # 实际开发建议使用WARNING
            'level': '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 前后端分离的rbac项目演示

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

.
.
.
.
.
.

3 全局异常处理封装

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

-------------------------------------

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

--------------------------------------

# 使用步骤
-第一步:在utils中新建 common_exceptions.py

-第二步:写个函数 见下面项目代码

-第三步:配置配置文件,以后只要出了异常,都会走咱们自己写的异常处理函数
	REST_FRAMEWORK = {
            'EXCEPTION_HANDLER': 'utils.common_exceptions.my_exception_handler', }

-第四步:勇敢大胆写代码,即便报错,程序不会蹦,并且会记录日志,并且处理成统一格式

.
.

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


def my_exception_handler(exc, context):
    # 1 记录日志  报错要记录的详细一点  哪个ip地址,用户id是多少,访问哪个路径,执行哪个视图函数,出了什么错
    view = context.get('view')  # 拿当前出错的视图类的对象
    request = context.get('request')  # 拿请求对象就是那个大字典
    ip = request.META.get('REMOTE_ADDR')  # 拿ip地址
    user_id = request.user.pk  # 拿用户id
    path = request.get_full_path()  # 拿访问的完整路由

    # 2 处理异常
    response = drf_exception_handler(exc, context)
    print(response)

    if response:
        # drf的异常已经处理了
        logger.warning('drf出了异常,异常是:%s' % str(exc))
        res = Response({'code': 999, 'msg': response.data.get('detail', '请联系系统管理员')})

    else:
        # django的异常,我们要处理,给前端不要有详细错误信息展示,日志记详细一点
        logger.error('用户【%s】,ip地址为【%s】,访问地址为【%s】,执行视图函数为【%s】,出错是【%s】' % (user_id, ip, path, str(view), str(exc)))
        res = Response({'code': 888, 'msg': '服务器异常,请联系系统管理员'})

    return res

------------------------------------------
#  drf处理全局异常的时候,传给异常处理函exception_handler的参数exc
#  与context是个啥东西    exc是错误对象 context是一个大字典,详见
#  handle_exception 的源码分析,见excel的视图类总结


#  response.data.get('detail')  这个拿到的是什么?
#  drf_exception_handler函数的返回值被变量response接收
#  如果是drf的异常,就可以通过response.data拿到包裹错误信息的字典或列表
#  再get.('detail')能拿到detail键对应的值

#  data = {'detail': exc.detail}
#  return Response(data, status=exc.status_code, headers=headers)
----------------------------------------
配置文件dev里面配置一下
REST_FRAMEWORK = {
    'EXCEPTION_HANDLER': 'utils.common_exception.my_exception_handler',
}

-----------------------
测试代码
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, 23]
        print(l[9])

        return Response('ok')

.
.
.
.
.
.

3 封装Response

# 本身drf有Response,但是咱们公司规定,前端收到的格式都是固定的
	-{code:100,msg:提示,data:{}/[]}
	-{code:100,msg:提示,token:asdfasd,user:lqz}

# 所以要对DRF的Response进行封装,封装后,code,msg可以不传,不传就用默认的

---------------------------------------------
# 使用步骤
	第一步:在utils下新建common_response.py
    第二步:封装APIRespon
    第三步:导入使用,视图函数的方法,返回时,都使用咱们自己的

.
.

from rest_framework.response import Response

'''

要达到的效果,以后使用APIResponse的情况
    -return APIResponse()----------前端收到-->{code:100,msg:成功}
    -return APIResponse(token=xsdse,username=lqz)----------前端收到-->{code:100,msg:成功,token:xsdse,username:lqz}
    -return APIResponse(data=[{},{},{}])----------前端收到-->{code:100,msg:成功,data:[{},{},{}]}
    -return APIResponse(code=101,msg=失败)----------前端收到-->{code:101,msg:失败}
    -return APIResponse(headers={'xx':'yy'})----------前端收到-->{code:100,msg:成功},但是响应头中有xx=yy
    -return APIResponse(status=201)----------前端收到-->{code:100,msg:成功},但是响应状态码是201


效果就是:传code msg  status headers 都能正常改,不传有默认值,
如果有多余的参数传过来了,都统一放到响应体的字典里面去
实际上需要达到的效果就是:传Response里面有的参数,会替换,传传Response里面没有的参数,
会给APIResponse添加属性!!!

'''

class APIResponse(Response):
    # 除了code msg  status headers 其他的参数都被**kwargs接收了
    def __init__(self, code=100, msg='成功', status=None, headers=None, **kwargs):
        data888 = {'code': code, 'msg': msg}
        if kwargs:
            # 有值,说明,除了code,msg,status,headers以外的,还传了其他的数据
            # 这些数据我们都要返回给前端,放到这个data888中
            data888.update(kwargs)
        # 这个data方法的功能是:用括号里面的字典去更新外面的字典,键相同就更新,
        # 键不相同就把键与值一起加到外面的字典里面去!!!

        super().__init__(data=data888, status=status, headers=headers)
        # 子类调用父类里面的方法,执行Response里面的双下init方法,实现真正的初始化
        # 将数据返给了前端了!!!

-----------------------------------
测试的代码视图类代码
from utils.common_response import APIResponse

class TestAPIResponse(APIView):
    def get(self, request):
        # return APIResponse('ok')   # 这样传前端看到是这样了 {'code':'ok','msg':'成功'}
        # return APIResponse(token='ddsfaffad',username='lqz')

        # return APIResponse(code=101, msg='错误')

        return APIResponse(data=[{'name': 'lqz'}, {'age': 18}])

# 都能统一展示给前端规定的格式!!!

.
.
.
.
.

4 luffy数据库创建

4.1 创建用户创建库

----------------------------------------
# 之前项目操作数据库,都是使用root用户,root用户权限太高了
# 在公司里,一般不会给你root用户权限
# 如果开发人员是root权限,数据安全性就很差

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

# 面试题:utf8  utf8mb4 有什么区别 ?

----------------------------------------

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

1.管理员连接数据库
>: mysql -uroot -p密码

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

3.查看用户
>: select user,host,password from mysql.user;
只有root用户,但是root用户权限太高,所以需要创建luffy用户

# (5.7往后的版本) 查看用户的命令
>: select user,host,authentication_string from mysql.user;
----------------------------------------------------------

localhost意思就是root用户可以用本地连接
image
.
.
.
.
.
.


#创建路飞用户,授予luffy库所有权限
-----------------------------------------------------
设置权限账号密码

# 授权账号命令:
	grant 权限(create, update) on 库.表 to '账号'@'host' identified by '密码'
-------on 后面接库.表 意思就是授予对哪个库哪个表新增数据与更新数据的权限
----------------------------------------------------------

1.配置任意ip都可以连入数据库的账户
	grant all privileges on luffy.* to 'luffy'@'%' identified by '123';
-------grant all privileges 授予所有权限
-------on luffy.*      对于路飞库的所有表
-------to 'luffy'     创哪个用户
-------@'%'      访问地址,可以写'host',也可以写允许访问的ip地址,也可以写个'%'允许任意远程ip地址访问
-------identified by '123'    创的用户的密码
整体的意思是:创建一个luffy用户,可以远程连接到luffy库的所有表,密码是123,对
所有表有所有权限

----------------------------------------------------------

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

3.刷新一下权限
	flush privileges;
# 刷新一下权限的目的是把硬盘上的权限加载到内存里!!!
----------------------------------------------------------

操作完后的效果:
只能操作luffy数据库的账户
账号:luffy
密码:123
----------------------------------------------------------
面试题
mysql 的 localhost连接与 IP地址连接有什么区别?

localhost本地连接没有经过网卡,本地有个socket文件直接连的
IP地址连接,是经过网卡,通过网卡去连接的
----------------------------------------------------------

image
.
本地连接与用ip地址远程连接 两张连接数据库的情况!!!
image
.
.
.
.
.
.
.

4.2 使用项目连接库

# 项目操作mysql,需要安装模块
	-pymysql
	-mysqlDB
	-mysqlclient

	历史:原来py2上有个操作mysql的模块叫mysqlDB,
	但到py3,mysqlDB模块没有支持py3,但django默认使用mysqlDB这个模块去连接mysql,mysqlDB不支持py3,运行就报错
	我们使用pymysql,作为连接mysql的数据库模块,但是需要加代码
		imprort pymysql
		pymysql.install_as_mysqldb()  # 猴子补丁
# 这两行代码一般放在项目目录下的双下init文件里面,如果不能用mysqlclient,
# 只能用pymysql的情况下,或者写在配置文件的最下面也行

	-django 2.2.2以后,还使用pymysql,需要改djagno源代码,就比较烦了!!!

------------------------------------------------------
------------------------------------------------------

# 所以统一使用mysqlclient来作为操作mysql的底层库!!!

	基于py2的mysqldb,在py3上重写了,但是名字改成了mysqlclient
	使用mysqlclient,只需要安装这个模块,不需要再写任何代码,直接用即可!!!

	-但是:mysqlclient 这个模块
		-win 一般人品好,pip install mysqlclient  直接就装上了
		-mac 人品不好,装不了,centos部署项目,后面会讲centos上如何装

# mysqlclient
pip install mysqlclient

-----------------------------------------------------

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

# 用户名密码写死在代码中了,为了保证安全,可以把用户名与密码写到环境变量中

name = os.environ.get('LUFFY_NAME', 'luffy')
password = os.environ.get('LUFFY_PASSWORD', '123')
# os.environ.get() 拿环境变量里面的东西

# 拓展:有的公司,直接有个配置中心---》服务--》只用来存放配置文件


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


image
.
image
.
.
.
.
.
.
.

5 软件开发模式

---------------------------------------------------
# 瀑布模式:bbs项目就是按照这种模式
	-需求分析---》设计--》创建数据库 所有都创建---》开发(3个月)---》交给测试--》测试通过---》上线

----------------------------------------------------
# 敏捷开发
	-需求分析---》设计---》只设计一个板块---》开发(2周)---》交给测试---》运维上线(测试环境)
    -设计---》只设计一个板块---》开发(2周)---》交给测试---》运维上线(测试环境)

    -一个sprint周期   两周
    -scrum敏捷项目管理
----------------------------------------------------

img
.
.
.
.
.
.
.
.
.

6 User用户表

# 你决定使用auth表扩写,项目一定不要先迁移,先建好用户表再迁移
	已经迁移完了,再想用auth的user表
	删库,删所有app里面的migrations下面的所有迁移文件
	删django文件夹里面的contrib文件夹里面的admin和auth文件夹下的migrations下面的所有迁移文件

---------------------------------------------------

# 用户表使用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
------------------------------------------------

# 配置文件里面注册一下
AUTH_USER_MODEL = 'user.User'    # app名字下的表名

-----------------------------------------------

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

用ImageField字段,要先下pillow模块
image
.
.
可以看到环境变量里面有一路径,有问题
image
.
这地方的路径要用str转一下,才能正常数据库迁移
image
image
.
.
.
.
.
.
.

7 djagno的配置文件每个配置的作用

# 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  # 项目根路径, 小路飞luffy_api路径 D:\pythonProject03\luffy_api\luffy_api
# print(BASE_DIR)
# 把 apps 路径加入到环境变量
sys.path.insert(0, os.path.join(BASE_DIR, 'apps'))
# 把BASE_DIR也加入到环境变量,以后直接从小路飞开始导起即可
sys.path.insert(0, str(BASE_DIR))
# print(sys.path)
# 以后从大路飞开始导起,或者小路飞开始导起,或者apps开始导起都可以


# 秘钥,涉及到加密的django中,都会用它
SECRET_KEY = 'django-insecure-!g(8l%fw_#t$pz$x4jdf#e3$b4+c%xzqyq@3zki08vj&i)z4k-'

# 项目是以debug模式运行,还是非debug模式运行

# 项目上线,要改成false
# debug=True 代码可以热更新
# 调试模式下,对开发者更友好:可以列出所有路径.报了错,前端能看到
DEBUG = False
# 它搭配debug=False,它的意思是,允许我的项目部署在哪个ip地址上,* 表示允许部署在所有地址上
ALLOWED_HOSTS = ['*']



# django 是多个app组成的,里面配置app,默认带的app,django内置的app
# django 是一个大而全的框架,有很多内置app:
#   admin后台管理,
#   auth权限管理,
#   contenttypes表中存app也表的关系,
#   sessions session表,django的session相关
#   messages:消息框架,flask讲闪现,是一样的东西
#  staticfiles:静态资源的

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',

    # 'luffy_api.apps.home',   # luffy_api在环境变量,直接从这一层开始导起, 太长了,以后就想 注册  home
    # 'luffy_api.apps.user'
    'home',
    'user'
]


# 中间件
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',  # 安全相关中间件
    'django.contrib.sessions.middleware.SessionMiddleware', # session相关中间件
    'django.middleware.common.CommonMiddleware',            # 带不带 / 问题
    'django.middleware.csrf.CsrfViewMiddleware',            # csrf 认证,生成csrf串
    'django.contrib.auth.middleware.AuthenticationMiddleware', # 用户认证
    'django.contrib.messages.middleware.MessageMiddleware',  #消息框架相关
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]


# 根路由
ROOT_URLCONF = 'luffy_api.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 = 'luffy_api.wsgi.application'

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


# 数据库配置,mysql 主从搭建完,读写分离
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 = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_L10N = True
USE_TZ = False



# 静态资源
STATIC_URL = '/static/'   # 访问静态文件资源的接口前缀(通行证)

STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static88')   # 存储静态文件资源的目录名称!!
]
# 存储静态文件资源的目录名称-------是我们自己创在项目根目录下的文件夹


# 原来id字段是IntegerField
# 后来做成了BigAutoField ,为了防止存的数据量过大超了,才有的配置
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

.
.
.
.
.
.

8 开启media访问

# 配置文件加入,开启msdia访问
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media88')
#  访问 ip:端口/media/ 路径后   去media88目录下去找
#  所以到项目小目录里面,创一个media88目录

-----------------------------------------------------

# 总路由中设置
from django.urls import path,re_path
from django.views.static import serve
# 导入配置文件
from django.conf import settings  # 这样做有个好处,如果你配了用你了,如果没配用内置的
# from settings import dev  不要这么导入配置文件

from user import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('test_logger/', views.test_logger),
    path('test_exception/', views.TestException.as_view()),
    path('test_response/', views.TestAPIResponse.as_view()),
    # re_path('^media/(?P<path>.*)', serve, {'document_root': settings.MEDIA_ROOT})

    path('media/<path:path>', serve, {'document_root': settings.MEDIA_ROOT})
]

# 第一个path是转换器  后面的path是有名分组的名字,
# 后一个path作用是,将media/后面接收到的路径,用path=接收到的路径的形式,
# 传到serve函数里面去,serve函数的作用就是帮我们开路径用的
# document_root 是serve函数里面的一个参数,
# settings.MEDIA_ROOT就是我们配置文件里面写的目录名,也就是说,根据分组分出来的路径去
# 我们写在项目里面的media88目录里面找
# 整体和static差不多,都是先看路由对不对,对了,把路由后面的部分拿出来,
# 到指定的文件夹下找,找到就展示给前端

----------------------------------------

# 先在项目的media88目录下的icon里面添加一个default.png图片
# 访问路径就能看到图片了
http://127.0.0.1:8000/media/icon/default.png


# 以后使用djagno的配置文件都用这个
from django.conf import settings

image
.
.
.
.
.
.

扩展

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

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

.
.
.
.
.
.
.

作业

1 路飞封装日志并测试
2 封装异常处理记录日志并测试
3 封装Resposne并测试
4 创建路飞用户,路飞库
5 创建用户表,迁移成功


---------扩展------
6 搜索:utf8和utf8mb4的区别
7 搜索:mysql本地连接和用ip连接的区别
8 学习python位运算
9 重装mysql 5.7
posted @   tengyifan  阅读(34)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
点击右上角即可分享
微信分享提示