• luffy配置相关


    目录

    后台配置之封装logger

    在项目中集成日志

    封装全局异常

    二次封装response

    数据库配置

    在项目中配置使用mysql

    User模块User表配置

    开放media访问

    路飞前台项目创建和配置

    elementui

    vue-cookies

    bootstrap、 jquery

    前台全局样式

    全局js配置

    后台主页模块接口

    首页轮播图接口

    轮播图表

    轮播图接口

    路由分发

    后台管理采用simpleui

     第三方模块解决此问题

    自定义配置

    补充:

    断点调试

    绝对导入

    相对导入

    猴子补丁

    utf8 与utf8mb4的区别

    MySQL两条命令的区别

    开发模式


     

    后台配置之封装logger

     每个项目都需要记录日志

    这么做的目的是为了:后期可以通过日志排查问题分析错误,分析用户的行为

    django的logger是基于原生的logging模块封装的

    python-- 日志模块, logging_Yietong309的博客-CSDN博客

    在项目中集成日志

    1. 复制代码到配置文件

    1. # 真实项目上线后,日志文件打印级别不能过低,因为一次日志记录就是一次文件io操作
    2. LOGGING = {
    3. 'version': 1,
    4. 'disable_existing_loggers': False,
    5. 'formatters': {
    6. 'verbose': {
    7. 'format': '%(levelname)s %(asctime)s %(module)s %(lineno)d %(message)s'
    8. },
    9. 'simple': {
    10. 'format': '%(levelname)s %(module)s %(lineno)d %(message)s'
    11. },
    12. },
    13. 'filters': {
    14. 'require_debug_true': {
    15. '()': 'django.utils.log.RequireDebugTrue',
    16. },
    17. },
    18. 'handlers': {
    19. 'console': {
    20. # 实际开发建议使用WARNING
    21. 'level': 'DEBUG',
    22. 'filters': ['require_debug_true'],
    23. 'class': 'logging.StreamHandler',
    24. 'formatter': 'simple'
    25. },
    26. 'file': {
    27. # 实际开发建议使用ERROR
    28. 'level': 'INFO',
    29. 'class': 'logging.handlers.RotatingFileHandler',
    30. # 日志位置,日志文件名,日志保存目录必须手动创建,注:这里的文件路径要注意BASE_DIR代表的是小luffyapi
    31. 'filename': os.path.join(os.path.dirname(BASE_DIR), "logs", "luffy.log"),
    32. # 日志文件的最大值,这里我们设置300M
    33. 'maxBytes': 300 * 1024 * 1024,
    34. # 日志文件的数量,设置最大日志数量为10
    35. 'backupCount': 10,
    36. # 日志格式:详细格式
    37. 'formatter': 'verbose',
    38. # 文件内容编码
    39. 'encoding': 'utf-8'
    40. },
    41. },
    42. # 日志对象
    43. 'loggers': {
    44. 'django': {
    45. 'handlers': ['console', 'file'],
    46. 'propagate': True, # 是否让日志信息继续冒泡给其他的日志处理系统
    47. },
    48. }
    49. }

    2. 在utils中新建common_logger.py

    1. import logging
    2. # 通过配置问中的名字拿到logger对象,以后只需要导入,直接使用对象写日志即可
    3. logger=logging.getLogger('django')

    3. 在需要的地方导入使用即可【注意路径】 直接使用logger.info

     

    封装全局异常

    drf中继承了APIView及其子类的视图类有全局异常处理,只需要写个函数,配置在配置文件中,出了异常这个函数就会执行。 再self.dispatch()方法中

    eb22704ba76e4f02aeb2691895e7f9f0.png

    3fc89d61771d433c9762de3a22b0ca8a.png

    c05e9b10899b476cb97e66c45abf5609.png

    9919f70b780b48028d53d933a1b4302c.png

    上述只是处理了drf的异常, django中的异常还需要自己处理。 使用我们需要写一个全局异常处理的方法, 并将此重写的方法配置在REST_FRAMEWORK配置项中。 

    封装异常函数规定了统一的返回格式,记录了日志,一旦程序处理问题,方便后续排查问题

    exceptions.py

    1. from rest_framework.views import exception_handler as drf_exception_handler
    2. from rest_framework.response import Response
    3. from utils.common_logger import logger
    4. def exception_handler(exc, context):
    5. # 程序出了异常,会走到这,我们都要记录日志
    6. # 请求地址,请求方式,请求时间,请求哪个视图函数,如果登录了,记录一下用户id
    7. request = context.get('request')
    8. try:
    9. user_id = request.user.pk
    10. if not user_id:
    11. user_id = '匿名用户'
    12. except:
    13. user_id = '匿名用户'
    14. view = context.get('view')
    15. logger.error('用户:【%s】,使用:【%s】 请求,请求:【%s】 地址,视图函数是:【%s】,出错了,错误是:【%s】' % (
    16. user_id, request.method, request.get_full_path(), str(view), str(exc)
    17. ))
    18. # 第一步:执行一下原来的异常处理:它只处理drf的异常,django的异常没有处理
    19. # res如果有值是Response的对象,说明是drf的异常
    20. # res如果是None,说明是django的异常
    21. res = drf_exception_handler(exc, context)
    22. # 在这里,可以通过状态码,把异常分的更细一些:比如有数据的异常,除以0的异常,列表越界异常。。。。
    23. if res:
    24. # drf异常
    25. # res=Response(data={'code':999,'msg':'服务器出错,请联系系统管理员'})
    26. res = Response(data={'code': 999, 'msg': res.data.get('detail', '服务器出错,请联系系统管理员')})
    27. else:
    28. # django的异常,状态码是888,错误信息是 exc异常对象转成字符串
    29. res = Response(data={'code': 888, 'msg': str(exc)})
    30. return res

    settings/dev.py 配置文件中配置

    1. # 在配置文件中配置
    2. REST_FRAMEWORK = {
    3. # 以后,只要出异常,就会执行exception_handler
    4. 'EXCEPTION_HANDLER': 'utils.exceptions.exception_handler',
    5. }

     

    二次封装response

    drf提供的Response对象,并不能够很方便的加入code和msg字段,我们自己来封装一个Response类,方便添加使用code 和msg

    utils/response.py

    1. from rest_framework.response import Response
    2. class APIResponse(Response):
    3. def __init__(self, code=100, msg='成功', status=None, headers=None, **kwargs):
    4. data = {'code': code, 'msg': msg}
    5. if kwargs:
    6. data.update(kwargs)
    7. super().__init__(data=data, status=status, headers=headers)

    以后在视图类中导入使用即可

    views.py

    1. class TestView(APIView):
    2. def get(self,request):
    3. # 以后使用APIResponse(result=[{id:1,name:'xiyouji'},{}..]>> 前端收到的样式{code:100,msg:成功,token:awdaexcw}
    4. # return Response('ok')
    5. # return APIResponse(token='qwdd')
    6. return APIResponse(result={'id':1,'name':'alice','price':12})
    7. -----------------------------------
    8. return APIResponse(token='asfdasfd')
    9. return APIResponse(token='asfdasfd',status=201,code=101)

     

    返回给前端的样式

    9fac78c20fbf449890f7519acce14d70.png

     1c549c4c6a584cb38166f02459ded10b.png

     

     

    数据库配置

    luffy项目使用的数据库是mysql. 以前我们使用root用户作为项目的数据库用户, 但是root用户的权限太高了,一般在公司里我们会给项目单独建立一个用户, 此用户只对当前数据库有权限。 

    在MySQL中创建一个用户luffy_api, 给用户授予luffy库的所有权限

    1. 链接mysql,创建一个luffy库 【命令行创建或者navicat客户端创建】

    2. 查看有哪些用户

    select user,host from mysql.user;

    79881acfe2be4fdca6054d50928ef35d.png

     

    3. 创建一个luffy_api用户【之前有个root用户, 权限过高】

    授权账号命令 :

    grant 权限(create, update) on 库.表 to '账号'@'host' identified by '密码'

    把luffy库下所有表的权限都授予luffy_api这个用户, 允许远程连接

      grant all privileges on luffy.* to 'luffy_api'@'localhost' identified by 'Luffy123?';

    把luffy库下所有表的权限都授予luffy_api这个用户,允许本地链接

    grant all privileges on luffy.* to 'luffy_api'@'localhost' identified by 'Luffy123?';

     

    ab8b7f02077f454e8ffd2d18a2df2a1f.png

     e25bd81a49eb47df858f76bd8078d22a.png

    4. 以luffy_api用户登录,查看, 只能看到luffy库

    5865e46e11ed406fa30730f35c7d7727.png

     fbff75c26bf6450ab7f1903e53e2a1b7.png

     

    在项目中配置使用mysql

    1.配置文件中

    1. DATABASES = {
    2. 'default': {
    3. 'ENGINE': 'django.db.backends.mysql',
    4. 'NAME': 'luffy',
    5. 'USER': user,
    6. 'PASSWORD': password,
    7. 'HOST': '127.0.0.1',
    8. 'PORT': 3306
    9. }
    10. }

    目前配置文件中我们直接写死了mysql的用户名和密码

    可能存在的风险: 如果源代码泄露了,数据库用户名和密码就会泄露。

    真正的用户名和密码是环境变量里配的,不是现在写的这个

    1. import os
    2. USER= os.environ.get('USER','luffy_api')
    3. PASSWORD = os.environ.get('PASSWORD','Luffy123?')
    4. DATABASES = {
    5. # 'default': {
    6. # 'ENGINE': 'django.db.backends.sqlite3',
    7. # 'NAME': BASE_DIR / 'db.sqlite3',
    8. # }
    9. 'default': {
    10. 'ENGINE': 'django.db.backends.mysql',
    11. 'NAME': 'luffy',
    12. 'USER': 'USER',
    13. 'PASSWORD': 'PASSWORD',
    14. 'HOST': '127.0.0.1',
    15. 'PORT': 3306
    16. }
    17. }

     

    f98e5078e443458b839cd6866cb5e706.png

     

    2. 运行项目会报错, django默认使用mysqlDB操作mysql, mysqlDB这个模块,在python 2中支持,python3中不支持, 于是使用pymysql替换, 到了django2.0.7以后, 如果使用pymysql天天替换就需要更改django源代码, 后期使用mysqlclient替换pymyaql .   mysqlclient是mysqlDB的python3.x版本

    如果使用pymysql要改源码,需要执行

    1. import pymysql
    2. pymysql.install_as_MySQLdb() # 猴子补丁,把里面所有mysqlDB的对象,都替换成pymysql

      猴子补丁是:在程序运行过程中的动态替换技术

      以后再django中不使用pymysql了,使用mysqlclient,不需要再执行任何补丁了。

    我这里直接提示安装mysqlclient模块 

    7e14f91ccda74c6788f987d96be5a008.png
       
      3.  只需要装 mysqlclient,一切都解决了
        

    User模块User表配置

    配置好mysql了,咱们项目的用户表是,会用Auth的User表,扩写字段

     使用步骤
        -1 创一个用户app:python ../../manage.py startapp user
        -2 user 的app的models.py中扩写用户表

    1. class UserInfo(AbstractUser):
    2. mobile = models.CharField(max_length=11, unique=True)
    3. # 需要pillow包的支持 ImageField继承了 FileField只存储图片
    4. icon = models.ImageField(upload_to='icon', default='icon/default.png')
    5. class Meta:
    6. db_table = 'luffy_user' # 指定表明
    7. verbose_name = '用户表' # 后台管理中显示中文
    8. verbose_name_plural = verbose_name
    9. def __str__(self):
    10. return self.username

     

        -3 配置文件配置,注册app,安装pillow模块
        用户表的配置

      AUTH_USER_MODEL='user.UserInfo'


        -4 两条命令迁移

     

    开放media访问

    1 在配置文件中配置
       

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


        2 新建media文件夹,icon文件夹,放一张图片进去
        3 路由中加入:
     

    1.   path('media/', serve, kwargs={'document_root': settings.MEDIA_ROOT}),

    访问路由查看 

    c7384c9081b741ae9dba7116d94fb3df.png

     

     

    路飞前台项目创建和配置

    创建项目

    71c3126e711c46bfa4590533270d0fb0.png

      

    在pycharm新窗口中打开luffy_city

    删除一些不用的信息, 只保留需要的信息

    1. # -App.vue中只保留
    2. <template>
    3. <div id="app">
    4. <router-view/>
    5. div>
    6. template>
    7. # HomeView.vue
    8. <template>
    9. <div class="home">
    10. <h1>首页h1>
    11. div>
    12. template>
    13. <script>
    14. export default {
    15. name: 'HomeView',
    16. }
    17. script>
    18. # router/index.js
    19. const routes = [
    20. {
    21. path: '/',
    22. name: 'home',
    23. component: HomeView
    24. },
    25. ]
    26. const router = new VueRouter({
    27. mode: 'history',
    28. base: process.env.BASE_URL,
    29. routes
    30. })
    31. export default router

    安装axios

    5a748a63f55b4b80a308069c2ad83a22.png

    配置 main.js

    1. import axios from 'axios'
    2. Vue.prototype.$axios=axios

    测试一下前后端是否打通

    1. <script>
    2. export default {
    3. name: 'HomeView',
    4. data(){
    5. return {}
    6. },
    7. created() {
    8. this.$axios.get('http://127.0.0.1:8000/test/').then(res=>{
    9. console.log(res)
    10. })
    11. }
    12. }
    13. script>

     报错的原因是跨域问题,暂不处理。a98ae92d35244a2ca71049f4b61cacda.png

     以后再任意组件中使用只需要引入即可。

    elementui

    vue2 使用elementiu, vue3使用elementui-plus

    安装element-ui

    982055ebcf3945c3ae9abd64fc558d83.png

     配置main.js

    1. import ElementUI from 'element-ui';
    2. import 'element-ui/lib/theme-chalk/index.css';
    3. Vue.use(ElementUI);

    使用时再任意组件中复制粘贴即可

     

    5f729afa1cc048ba8881de1d6995d239.png

     

    vue-cookies

    安装 

    73e3f0fb620c4217a86247bc6df8e9b6.png

     

    配置main.js

    1. import cookies from 'vue-cookies'
    2. Vue.prototype.$cookies=cookies

     使用:再任意组件中

    this.$cokies.set()
        this.$cookies.set('name','yietong')
      

    536f0a82e0334a59afd866b348f1b5ce.png

     

    bootstrap、 jquery

    方便后期万一需要使用bootstrap的样式, bootstrap基于jQuery, 所以两者都引入

    安装

    f459c598b7634e0a8f1a5004560ee402.png

     配置

    main.js

    1. import 'bootstrap'
    2. import 'bootstrap/dist/css/bootstrap.min.css'

    vue.config.js配置

    1. const webpack = require("webpack");
    2. module.exports = {
    3. configureWebpack: {
    4. plugins: [
    5. new webpack.ProvidePlugin({
    6. $: "jquery",
    7. jQuery: "jquery",
    8. "window.jQuery": "jquery",
    9. "window.$": "jquery",
    10. Popper: ["popper.js", "default"]
    11. })
    12. ]
    13. }
    14. };

     

    测试按钮

    88c56753cee0484a99f6e7c4eb2a41f7.png

     前后端连用测试

    1. //使用jQuery
    2. $.ajax({
    3. url:'http://127.0.0.1:8000/test/',
    4. type:'get',
    5. success:(data)=>{
    6. console.log(data)
    7. }
    8. })

    e734bd88ef9c4396ac02367ab589e2e5.png

     

    前台全局样式

    Body,h1等标签都有默认的样式。 我们要将原有的默认样式去掉, 写一个全局生效的样式

    在assets/css/global.css文件中复制下边的代码  【assets文件夹下存放静态资源,如图片,文件等】

    1. /* 声明全局样式和项目的初始化样式 */
    2. body, h1, h2, h3, h4, h5, h6, p, table, tr, td, ul, li, a, form, input, select, option, textarea {
    3. margin: 0;
    4. padding: 0;
    5. font-size: 15px;
    6. }
    7. a {
    8. text-decoration: none;
    9. color: #333;
    10. }
    11. ul {
    12. list-style: none;
    13. }
    14. table {
    15. border-collapse: collapse; /* 合并边框 */
    16. }

    main.js配置

    1. //5 去掉所有标签默认样式
    2. import '@/assets/css/global.css'

    全局js配置

    由于我们目前访问的都是127.0.0.1:8000端口,需要多次使用该地址, 使用将其抽象成公共的数据信息, 需要的时候导入即可。

    settings.js中配置

    1. export default {
    2. BASE_URL:'http://127.0.0.1:8000/'
    3. }

    main.js中配置

    1. // 6 全局配置
    2. import settings from "@/assets/js/settings";
    3. Vue.prototype.$settings=settings

    后台主页模块接口


    首页轮播图接口


    一张表写一个app, 创建一个app,写轮播图

    基表

    1. from django.db import models
    2.  
    3. # Create your models here.
    4. # 轮播图表
    5. # class Banner(models.Model):
    6. # 将其只作为基表使用
    7. class BaseModel(models.Model):
    8.  
    9.     # 是否删除,展示,创建时间
    10.     create_time = models.DateTimeField(auto_now_add=True,verbose_name='创建时间')
    11.     update_time = models.DateTimeField(auto_now=True,verbose_name='最后更新时间')
    12.     is_delete = models.BooleanField(default=False,verbose_name='是否删除')
    13.     is_display = models.BooleanField(default=True,verbose_name='是否上架展示')
    14.     privilege = models.IntegerField(verbose_name='优先级')
    15.  
    16.     class Meta:
    17.         # 如果表迁移,这个表就会生成, 为了不让表生成苦于加这句话
    18.         abstract = True  # 虚拟表,只用来做继承,不在数据库生成表

    但是上述字段,在别的表中可能也会用到, 于是我们将它抽出来,成为一个基表, 后续有需要使用这些字段的表直接继承它就可以了, 减少代码的编写。 将其放在utils/models.py中【utils文件夹内存放公共的数据和资源】

    轮播图表

    1. from utils.models import BaseModel
    2. from django.db import models
    3.  
    4.  
    5. # 轮播图表
    6. class Banner(BaseModel):
    7.     # 图片地址,名字,图片名字,link地址【前端点击,会跳到图片】
    8.  
    9.     title = models.CharField(max_length=32,unique=True,verbose_name='名字')
    10.     image = models.ImageField(upload_to='banner',verbose_name='图片')
    11.     link = models.CharField(max_length=64,verbose_name='跳转链接')  # course
    12.     desc = models.TextField(verbose_name='详情')  # 也可以用详情表
    13.  
    14.     class Meta:
    15.         db_table = 'luffy_banner'
    16.         verbose_name_plural = '轮播表图'
    17.  
    18.     def __str__(self):
    19.         return self.title
    20.  

    执行迁移命令

    d6b6df7e63784fd3bba11b679df7f334.png

     

    轮播图接口


    路由分发

     urls.py  总路由

    1.  
    2. from django.contrib import admin
    3. from django.urls import path,include
    4. from home import views
    5. from django.views.static import serve
    6. from django.conf import settings
    7. urlpatterns = [
    8.     path('admin/', admin.site.urls),
    9.     # path('test/', views.TestView.as_view()),
    10.  
    11.     # 路由分发
    12.     path('api/v1/home/',include('home.urls')),
    13.     # 开启media访问
    14.     path('media/',serve,kwargs={'document_root':settings.MEDIA_ROOT}),
    15. ]


    home/urls.py app下的路由

    1.  
    2. from home import views
    3.  
    4.  
    5. from rest_framework.routers import SimpleRouter
    6. router = SimpleRouter()
    7. router.register('banner',views.BannerView,'banner')
    8.  
    9. urlpatterns = [
    10.  
    11. ]
    12.  
    13. urlpatterns+=router.urls
    14. views.py
    15. from django.shortcuts import render
    16.  
    17. # Create your views here.
    18. from .models import Banner
    19. from .serializer import BannerSerializer
    20.  
    21. # 自动生成路由
    22. from rest_framework.viewsets import GenericViewSet
    23.  
    24. # 获取所有的
    25. from rest_framework.mixins import ListModelMixin
    26.  
    27. class BannerView(GenericViewSet,ListModelMixin):
    28.     queryset = Banner.objects.all().filter(is_delete=False,is_display=True).order_by('privilege')
    29.     serializer_class = BannerSerializer

     views.py

    1. from django.shortcuts import render
    2. # Create your views here.
    3. from .models import Banner
    4. from .serializer import BannerSerializer
    5. # 自动生成路由
    6. from rest_framework.viewsets import GenericViewSet
    7. # 获取所有的
    8. from rest_framework.mixins import ListModelMixin
    9. class BannerView(GenericViewSet,ListModelMixin):
    10. queryset = Banner.objects.all().filter(is_delete=False,is_display=True).order_by('privilege')
    11. serializer_class = BannerSerializer

    serializer.py

     

    1. from rest_framework import serializers
    2. from .models import Banner
    3.  
    4.  
    5. class BannerSerializer(serializers.ModelSerializer):
    6.     class Meta:
    7.         model = Banner
    8.         fields = ['title','image','link']


    测试访问一下

    37215d9e75d9439abd56f5633533036b.png

     

    重写list方法,获取所有。 返回统一的格式。

      utils/views.py 封装一下获取所有数据方法,方便后续,少写代码。

    1. from rest_framework.mixins import ListModelMixin
    2. from utils.response import APIResponse
    3.  
    4. class CommonListModelMixin(ListModelMixin):
    5.     def list(self, request, *args, **kwargs):
    6.         res = super().list(request,*args,**kwargs)
    7.         return APIResponse(result=res.data)

    home/view.py 

    1. from django.shortcuts import render
    2.  
    3. # Create your views here.
    4. from .models import Banner
    5. from .serializer import BannerSerializer
    6.  
    7. # 自动生成路由
    8. from rest_framework.viewsets import GenericViewSet
    9.  
    10. # 获取所有的
    11. from utils.view import CommonListModelMixin
    12.  
    13. class BannerView(GenericViewSet,CommonListModelMixin):
    14.     queryset = Banner.objects.all().filter(is_delete=False,is_display=True).order_by('privilege')
    15.     serializer_class = BannerSerializer

     

    再次访问就可以看到已经统一了数据返回格式

    db7432c38a8742debc3bea4fd7a74838.png

     

    接下来去后台填充数据

    先做汉化处理

    1. LANGUAGE_CODE = 'zh-hans'
    2.  
    3. TIME_ZONE = 'Asia/Shanghai'
    4.  
    5. USE_I18N = True
    6.  
    7. USE_L10N = True
    8.  
    9. USE_TZ = False


    创建超级用户  [密码不展示】

    python manage.py createsuperuser


    admin里注册

    1.  
    2. from .models import Banner
    3.  
    4. admin.site.register(Banner)


    后台管理采用simpleui


    下载安装

    app中注册

    1. INSTALLED_APPS = [
    2.     'simpleui',]


    添加数据

    5338facef493489c962383099c452873.png

    ea4e846fad09426b9948b6a10bdd4ce6.png

     

     后端完成后我们来接通前端
     

    settings.js    以后访问的路径都是api/v1/...

    1. export default {
    2. BASE_URL:'http://127.0.0.1:8000/api/v1/'
    3. }

    HomeVue.vue

    1. export default {
    2. name: 'HomeView',
    3. data(){
    4. return {}
    5. },
    6. created() {
    7. // 联通前后端, 注意斜杠得添加, 前端不会追加斜杠
    8. this.$axios.get(this.$settings.BASE_URL+'/home/banner/').then(res=>{
    9. console.log(res)
    10. })
    11. }
    12. }

    然后我们发现前后端交互的时候出现了跨域问题

     

    5ff3bcbc807943589f8ad4daa6b0a37a.png

    具体成因及解决方案参考此篇博文 

    django中的跨域问题以及解决策略_Yietong309的博客-CSDN博客

     

    做一个小测验可能浏览器发送的是什么请求

    urls/py

    1. from home.views import test
    2. urlpatterns = [
    3. path('test/',test)]

    views.py

    1. ####测试跨域问题
    2. from django.shortcuts import render,HttpResponse
    3. def test(request):
    4. print(request.method)
    5. return HttpResponse('ok')

    a974e5d245e54c9b90ffd511fec432e5.png

     前端测试。 后端也打印出来请求方式

    1. created{
    2. // 测试跨域问题, get请求,简单,之发送一次
    3. // this.$axios.get('http://127.0.0.1:8000/test/').then(res=> {
    4. // console.log(res)
    5. // })}

    fabaee8cc52c486596c1ef3e5a0f0ed3.png

     因为GET是个简单请求, 所以之发送一次

    换成post请求,并且在请求头中加参数

    1. created{
    2. this.$axios.post('http://127.0.0.1:8000/test/', {}, {
    3. headers: {'token': 'asdfasdf'}
    4. }).then(res => {
    5. console.log(res)
    6. })}

    后端出现OPTIONS请求【非简单请求,所以先发送了Options请求,请求通过后才会在发送别的请求】

    57aa6a1725d54a4db7533b82734ac364.png

     

     解决跨域问题,使用CORS技术,在响应中写东西, 如果自己写需要写个中间件,每个请求都会走, 在process_response中写入以下代码

    1. def test(request):
    2. print(request.method)
    3. # 如果自己写,需要写个中间件,每个请求都会走,在process_response中写入下面的代码即可
    4. # 解决简单请求
    5. res=HttpResponse('ok')
    6. res['Access-Control-Allow-Origin']='*'
    7. # 解决非简单请求
    8. if request.method=='OPTIONS':
    9. res['Access-Control-Allow-Headers'] = 'Content-Type'
    10. return res

     第三方模块解决此问题

    1. 安装django-cors-headers

    2. 注册app

    1. INSTALLED_APPS = [
    2. 'simpleui',
    3. 'home',
    4. # 'home' # 找不到路径会直接报错 导报要从环境变量开始导
    5. # 'luff_api.apps.home' # 太长了,导入不方便
    6. 'rest_framework',
    7. 'corsheaders',
    8. ]

    3. 中间件中加入

    1. MIDDLEWARE = [
    2. 'corsheaders.middleware.CorsMiddleware',
    3. ]

    4. 配置文件中配置

    1. # 允许所有域
    2. CORS_ORIGIN_ALLOW_ALL = True
    3. # 允许的请求方式
    4. CORS_ALLOW_METHODS = (
    5. 'DELETE',
    6. 'GET',
    7. 'OPTIONS',
    8. 'PATCH',
    9. 'POST',
    10. 'PUT',
    11. 'VIEW',
    12. )
    13. # 允许请求头带
    14. CORS_ALLOW_HEADERS = (
    15. 'accept-encoding',
    16. 'authorization',
    17. 'content-type',
    18. 'origin',
    19. 'user-agent',
    20. 'x-csrftoken',
    21. 'token'
    22. )

     

    自定义配置

    将一些公共的配置信息单独放在一个配置文件中

    新建一个common_settings.py

    比如:轮播图展示条数

    BANNER_COUNT = 3

    在dev.py中导入

    from settings.common_settings import *

    在查询所有轮播图接口中修改

        queryset = Banner.objects.all().filter(is_delete=False,is_display=True).order_by('privilege')[:settings.common_settings.BANNER_COUNT]

     

    前后端管理模板

    vue_admin: 基于Vue的后台管理模板

     

     

    补充:

    断点调试

    6fcfd6aaea2f40abb854c044355958ac.png

     

    绝对导入

    绝对指的是 环境变量 sys.path 里面的路径,项目跟路径在pycharm自动加入环境变量

    用法
    绝对导入可以使用 import <> 或 from <> import <> 这两种语法,比如在 moduleA 模块里面,使用下面的绝对导入语句是有效的。

    1. import package.subpackage1.moduleX as moduleX
    2. from package.subpackage1 import moduleY
    3. from subpackage2 import moduleZ

    相对导入

    一个py文件中如果使用相对导入,这个文件不能以脚本运行
    相对导入解决了绝对导入的一些问题:

    同一个包下的模块可以很方便的相互引用,使用像 from . import xxx 的语句就行。
    顶层包的报名改了,包下的模块的相对导入的语句基本不用改

    1. from .moduleY import spam
    2. from .moduleY import spam as ham
    3. from . import moduleY
    4. from ..subpackage1 import moduleY
    5. from ..subpackage2.moduleZ import eggs
    6. from ..moduleA import foo

    猴子补丁

     猴子补丁是:在程序运行过程中得动态替换技术:

    1-Python中的GIL | Justin-刘清政的博客

    utf8 与utf8mb4的区别

    1. utf8 是针对Unicode的一种可变长度字符编码。

    2. utf8是utf8mb4的子集,除了将编码改为utf8mb4外不需要做其他转换。

    MySQL在5.5.3之后增加了这个utf8mb4的编码,mb4就是most bytes 4的意思,专门用来兼容四字节的unicode。好在utf8mb4是utf8的超集,除了将编码改为utf8mb4外不需要做其他转换。当然,为了节省空间,一般情况下使用utf8也就够了。

    3. utf8mb4比utf8多了emoji编码支持

    如评论要支持emoji可以用到. 建议普通表使用utf8 如果这个表需要支持emoji就使用utf8mb4

    4. 排序规则

    排序规则选择常用的有utf8_general_ci , utf8_unicode_ci

    utf8_unicode_ci   是基于标准的Unicode来排序和比较,能够在各种语言之间精确排序 , 为了能够处理特殊字符的情况,实现了略微复杂的排序算法。

    所以  utf8_unicode_ci   的准确性比较好 , 但是性能相对比较低。

    utf8_general_ci  没有实现Unicode排序规则,在遇到某些特殊语言或字符是,排序结果可能不是所期望的。
    5. UTF-8 编码是一种变长的编码机制,可以用1~4个字节存储字符。

    推荐新项目中使用utf8mb4的编码

     

    MySQL两条命令的区别

    mysql -u root -p  通过文件链接, 速度快

    mysql -h 192.168.1.11 -P 3306 -uroot -p 通过网卡链接,速度慢

     

     

    开发模式

    瀑布模式:例如BBS项目。  设计数据库,全部设计完了之后开始写项目

    敏捷开发: luffy项目,管理软件。  写一块设计一块数据库。

    8b7e95e5c47c4cf890676d9cb9197142.png

     

    sprint 开发周期一般为5-7天

     

     

  • 相关阅读:
    【9. 子矩阵和】
    14:00面试,14:06就出来了,问的问题有点变态。。。
    使用设计模式基于easypoi优雅的设计通用excel导入功能
    Set和Map的用法
    6.Android应用架构指南:界面层界面事件
    流媒体集群应用与配置:如何在一台服务器部署多个EasyCVR?
    现在学RPA,还有前途吗,会不会太卷?
    mysql之GROUP_CONCAT
    使用Java连接Hadoop进行编程
    整数转罗马数字
  • 原文地址:https://blog.csdn.net/weixin_67531112/article/details/127694183