首先,如果我们要用django连接数据库,大体上可分为三步:
INSTALLED_APPS = [
...
'user.apps.UserConfig',
...
]
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': "rest_3",
'PORT':3306,
'HOST':"127.0.0.1",
"PASSWORD":"123456",
"USER":"root",
}
}
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.原生迁移
我们需要在终端输入以下两条命令:
2.通过任务
当我们点击红框部分后,会自动弹出终端,然后会像在.py文件中一样,会有自动补齐和提示功能。我们只需要输入:
前面的一种可以说是makemigrations的迁移问题,生成不了迁移文件,也就是在migrations里没有像0001_initial字样的py文件。这种一般都会有提示,而一旦生成了这类初始化的文件,那么问题就变得有些棘手。这里我将列出我犯过的几类。
No changes detected
这种应该是最麻烦的,因为它不会报错,但就这一句话,表确出不来。
引起原因
这种一般是最直接的,当我们把位于migrations文件夹下的文件脚本删除后,然后再次运行上面的两条命令,是有可能成功的,当然,很大概率是因为中途暂停导入没有完整的记录。
这是大部分问题的症结所在,具有普适性。由于makemigrations执行后生成脚本,但migrate一直迟迟不成功,然后我们就会不断重复的进行迁移迁移再迁移,但即使再多次也是没有用处,initial文件却在呈现几何量级的增长。。所以这里有一个一劳永逸的办法,那就是先在python中删除我们的数据库脚本文件,然后利用python终端或者我们的系统终端进入我们正在操作的数据库,然后输入如下的命令:
select * from django_migrations;
查询数据库迁移指令,然后可以针对数据库记录进行删除迁移记录,之后就能再重新迁移。
然后我们找到最近一次失败的记录,输入如下命令:
delete from django_migrations where id=11;
删除制定目录下的迁移记录。然后就可以重新makemigrations
一般这也是因为修改表结构的时候出现的错误,我们的解决方案是进入数据库输入如下命令:
delete from django_migrations where app='yourappname';
然后再把initial文件以及相应的缓存清一下就行了。命令如下:
$ rm -rf migrations/ __pycache__/
不过我并不推荐这一种,就像第一种一样有很大的偶然性,我也只在初期用过。一般都是推荐第二种方案或者第四种方案。
删库,这就不多说了。。。
这是我最近的一个错误,也是我想总结一下数据库常用错误的初衷,找这个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。
问题解决方法:
所以这也是上面我提过的django_migrations数据库有时清空还不够,还要清理缓存的原因。