django连接MySQL数据库常见错误解析

连接步骤

首先,如果我们要用django连接数据库,大体上可分为三步:

  1. 在settings中的INSTALLED_APPS里注册我们的项目
	INSTALLED_APPS = [
	...
    'user.apps.UserConfig',
    ...
   ]
  1. 修改settings中的DATABASES进行我们的数据库配置连接
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': "rest_3",
        'PORT':3306,
        'HOST':"127.0.0.1",
        "PASSWORD":"123456",
        "USER":"root",
    }
}

  1. 在项目文件下的init文件里写入如下代码,表示安装pymysql的驱动,因为django的历史遗留问题,本身是支持mysql的。
import pymysql
pymysql.install_as_MySQLdb()

连接错误

这里的问题都是一些比较好解决的,因为一般都是语法错误或者写错,比如说是密码写错了,那么它就会提示为数据库拒绝了我们的连接请求:

django.db.utils.OperationalError: (1045, "Access denied for user 'root'@'localhost' (using password: YES)")

另外就是假如我们没有安装pymysql,那么它就会提示我们需要安装:

django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module: No module named 'MySQLdb'.
Did you install mysqlclient or MySQL-python?

数据库迁移


迁移步骤


关于数据库的迁移,Django中有两种方式。

1.原生迁移
我们需要在终端输入以下两条命令:

  1. python manage.py makemigrations
  2. python manage.py migrate

2.通过任务

在这里插入图片描述

当我们点击红框部分后,会自动弹出终端,然后会像在.py文件中一样,会有自动补齐和提示功能。我们只需要输入:

  1. makemigrations
  2. migrate

迁移错误

前面的一种可以说是makemigrations的迁移问题,生成不了迁移文件,也就是在migrations里没有像0001_initial字样的py文件。这种一般都会有提示,而一旦生成了这类初始化的文件,那么问题就变得有些棘手。这里我将列出我犯过的几类。

No changes detected

这种应该是最麻烦的,因为它不会报错,但就这一句话,表确出不来。

引起原因

  1. 第一可能是操作不当导致的:比如说当makemigrations已经执行了,突然又想到一个新思路,于是跑去另加字段,还有就是迁移过程中出现了暂停,但暂停的时间点掐得不准,已经在创建表了。当然还有其它的,这里就只提这两种了。
  2. 另外就是操作正确,中途没有产生干扰,但还是出不来表,一旦出现这种,那么大概率是表结构有问题,比如说是表中某个字段多了一些比较意外的参数,如managed=False,还有我前篇在restframework(2)中列举的那些常用参数都可能会导致这类问题。

解决方案

1.手动删除initial文件

这种一般是最直接的,当我们把位于migrations文件夹下的文件脚本删除后,然后再次运行上面的两条命令,是有可能成功的,当然,很大概率是因为中途暂停导入没有完整的记录。

2.删除脚本,再删除库中记录

这是大部分问题的症结所在,具有普适性。由于makemigrations执行后生成脚本,但migrate一直迟迟不成功,然后我们就会不断重复的进行迁移迁移再迁移,但即使再多次也是没有用处,initial文件却在呈现几何量级的增长。。所以这里有一个一劳永逸的办法,那就是先在python中删除我们的数据库脚本文件,然后利用python终端或者我们的系统终端进入我们正在操作的数据库,然后输入如下的命令:

select * from django_migrations;

查询数据库迁移指令,然后可以针对数据库记录进行删除迁移记录,之后就能再重新迁移。
在这里插入图片描述

然后我们找到最近一次失败的记录,输入如下命令:

delete from django_migrations where id=11;

删除制定目录下的迁移记录。然后就可以重新makemigrations

3.删除django_migrations表

一般这也是因为修改表结构的时候出现的错误,我们的解决方案是进入数据库输入如下命令:

delete from django_migrations where app='yourappname';

然后再把initial文件以及相应的缓存清一下就行了。命令如下:

$ rm -rf migrations/ __pycache__/

不过我并不推荐这一种,就像第一种一样有很大的偶然性,我也只在初期用过。一般都是推荐第二种方案或者第四种方案。

4.终极方案

删库,这就不多说了。。。

服务器内部错误

这是我最近的一个错误,也是我想总结一下数据库常用错误的初衷,找这个bug找了几个小时,最后找到的时候发现非常简单,因为开始就提示出来了。

起因

最近在写一个用户注册登录的功能,然后表的改动有时候会非常大,我又喜欢在windows和Linux中两边调试,这并不是一个好习惯,以后大概做这类项目就直接Linux了。好了,下面就说说bug原因。

当我填好一切的时候,整个后端逻辑基本没错,前端套用模板然后自己修改了下,但当我点击注册的时候,发现并没有发生页面的跳转,前端的控制台提示我:

{
	"message":"服务器内部错误"
}

从这里的信息还是有点难判断是前端错误还是后端错误,所以我们打开了postman,向注册页面提交了post请求,发现结果和上面的一样。然后我们就去日志里找提示报错信息,报错信息提示为507,发现是我们在异常文件中继承了数据库的异常重写的报错信息,代码为:

from rest_framework.views import exception_handler as drf_exception_handler 
import logging
from django.db import DatabaseError
from redis.exceptions import RedisError
from rest_framework.response import Response
from rest_framework import status

# 获取在配置文件中定义的logger,用来记录日志
logger = logging.getLogger('django')

def exception_handler(exc, context):
    """
    自定义异常处理
    :param exc: 异常
    :param context: 抛出异常的上下文
    :return: Response响应对象
    """
    # 调用drf框架原生的异常处理方法
    response = drf_exception_handler(exc, context)

    if response is None:
        view = context['view']
        if isinstance(exc, DatabaseError) or isinstance(exc, RedisError):
            # 数据库异常
            logger.error('[%s] %s' % (view, exc))
            response = Response({'message': '服务器内部错误'}, status=status.HTTP_507_INSUFFICIENT_STORAGE)

    return response

如果不定义异常信息的话,可能报错翻译为507存储空间不足:服务器无法存储完成请求所需的表示。我们来看一下django.db的源码为:

from django.db.utils import (
    DEFAULT_DB_ALIAS, DJANGO_VERSION_PICKLE_KEY, ConnectionHandler,
    ConnectionRouter, DatabaseError, DataError, Error, IntegrityError,
    InterfaceError, InternalError, NotSupportedError, OperationalError,
    ProgrammingError,
)

__all__ = [
    'connection', 'connections', 'router', 'DatabaseError', 'IntegrityError',
    'InternalError', 'ProgrammingError', 'DataError', 'NotSupportedError',
    'Error', 'InterfaceError', 'OperationalError', 'DEFAULT_DB_ALIAS',
    'DJANGO_VERSION_PICKLE_KEY',
]

每一个错误都在下面有对应的解释,并且每一个错误都是一个定义类,于是很不容易的找到了这个类别。并且我们可以发现这个类别的问题,然后通过和models里的模型类对比。这里需要注意:当我们在做项目的时候,这里有两种方式进入数据库,第一种是通过视图里的工具栏打开database:
在这里插入图片描述

中途还有要输入账号密码,这里就不再多说了,我主要想说的是虽然这种能在不打开终端的情况下连接数据库,但就因为不是终端,可能权限以及自动更新都跟不上节奏,在我排查完redis的问题后,发现保存数据基本正常,而通过这个窗口看mysql的字段发现与models匹配,调了半天,最后尝试第二种方案终于知道原因。


当我们检查数据库时,最好的操作,就是直接去数据库查,而不要通过其它的任何取巧的方式,那样只会加大工作量。经过验证,是我们的user表里的email_active字段缺少,进而影响到了我们注册页面的验证码,而直接导致我们点击注册时,验证码是正确的但一直提示验证码错误,并且可能成功也是不能注册的。

排错时可能会出现的错误

单元测试错误

出错原因

Requested setting DEFAULT_INDEX_TABLESPACE, but settings are not configured. You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing setting

这个错误一般都是我们debug的时候,操作不当出现,下面将列举解决方案。

解决方案

我们可以在我们想要测试的文件最上方加入如下三行代码:

import os,django
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project_name.settings")# project_name 项目名称
django.setup()

如果这个错误是当我们运行整个项目的时候发生,那么很显然我们的项目启动被替换了,这个时候我们可以按如下步骤将文件替换回来。

在这里插入图片描述

脚本出错

出错原因

AttributeError: ‘module’ object has no attribute’xxx’

这个错误我也在本次修改数据库的时候遇到了,原因就是:其实我们的代码逻辑以及语法完全没有错误,但它依然会报错是由于.pyc文件出现了问题,也就是当我们第一次执行成功时,pycharm会在相同文件夹下建立相应的缓存文件,这样可以保证以后再用时可以直接运行.pyc的执行文件。

pyc文件介绍

pyc文件,是python编译后的字节码(bytecode)文件。只要你运行了py文件,python编译器就会自动生成一个对应的pyc字节码文件。这个pyc字节码文件,经过python解释器,会生成机器码运行(这也是为什么pyc文件可以跨平台部署,类似于java的跨平台,java中JVM运行的字节码文件)。下次调用直接调用pyc,而不调用py文件。直到你这个py文件有改变。python解释器会检查pyc文件中的生成时间,对比py文件的修改时间,如果py更新,那么就生成新的pyc。

解决方案

问题解决方法:

  1. 命名py脚本时,不要与python预留字,模块名等相同
  2. 删除该库的.pyc文件(因为py脚本每次运行时均会生成.pyc文件;在已经生成.pyc文件的情况下,若代码不更新,运行时依旧会走pyc,所以要删除.pyc文件),重新运行代码;或者找一个可以运行代码的环境,拷贝替换当前机器的.pyc文件即可

所以这也是上面我提过的django_migrations数据库有时清空还不够,还要清理缓存的原因。

  • 1
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

submarineas

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值