Django之模型(操做)以及可能遇到的问题

在使用Django框架开发web应用的过程当中,不可避免的会涉及到数据的管理(增、删、改、查),而一旦谈到数据的管路操做,就须要使用数据管理的软件。例如:mysql, oracle等python

通常的对数据进行操做时候,以往都是经过原生的SQL语句,而后使用pymysql模块远程操做mysql。mysql

可是这样的操做会存在两方面的问题,git

一、sql语句的执行效率:应用开发程序员须要耗费一大部分经历去优化SQL语句程序员

二、一旦涉及到迁库,针对mysql开发的sql语句没法直接应用到oracle数据库上web

为了解决上述问题,Django引入了ORM(object  relational Mapping)即对象关系映射,是在pymysql之上又进行了一层封装,对于数据库的操做,不须要在编写原生的sql,取而代之的是基于面相对象的思想去编写类、对象、调用相应的方法等,sql

ORM会将其转换/映射成原生SQL而后交给pymysql执行 如图:数据库

具体步骤以下:django

一、建立Django 项目 新建名app01,在app01的models.py中建立模型bootstrap

 1 from django.db import models  2 
 3 
 4 # Create your models here.
 5 
 6 class Employee(models.Model):  7     name = models.CharField(max_length=20)  8     gender = models.BooleanField(default=1)  9     birth = models.DateField() 10     department = models.CharField(max_length=30) 11     salary = models.DecimalField(max_digits=10, decimal_places=1)

django的orm支持多种数据库,若是想将上述的模型转为mysql数据库中的表,须要在settings中进行设置python3.x

 1 # DATABASES = {
 2 # 'default': {
 3 # 'ENGINE': 'django.db.backends.sqlite3',
 4 # 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
 5 # }
 6 # }
 7 
 8 #须要将原有的(上面)DATABASES注释掉改为本身的(下面)
 9 DATABASES = { 10     'default': { 11         'ENGINE': 'django.db.backends.mysql',#使用Mysql数据库
12         'NAME': 'tb',#须要链接的数据库
13         'USER': 'root', #链接的数据库用户名
14         'PASSWORD': 'sipg09827', #链接的数据库密码
15         'HOST': '',  #mysql服务监听的ip
16         'PORT': '3306', #mysql服务监听的端口(通常默认为3306)
17         'ATOMIC_REQUEST': True, 18  } 19 }

三、其实python解释器在运行django程序时,django的orm底层操做数据库的python模块默认是mysqldb而非pymysql,而后对于解释器而言,Python2.X解释器支持的操做数据库的模块是mysqldb,而Python3.X解释器支持的操做数据库模块是Pymysql,

若是使用python3.x,须要修改django的orm默认操做数据库的模块为pymysql,具体作法以下:

 

 四、若是想打印orm转换过程当中的原生sql,须要在settings中进行配置日志

 1 LOGGING={  2     'version': 1,  3     'disable_existing_loggers': False,  4     'handle': {  5         'level': 'DEBUG',  6         'class': 'logging.StreamHandler'
 7  },  8     'loggers': {  9         'django.db.backends' :{ 10             'handlers':['console'], 11             'propagate':True, 12             'level':'DEBUG'
13  } 14  } 15 }

最后在命令行中执行两条数据库迁移命令,既可在指定的数据库中建立表:

>>>python manage.py makemigrations

>>>python manage.py migrate

#注意:
#一、makemigations 只是生成一个数据库迁移记录的文件,而migrate才是将更改真正提交到数据库执行
#二、数据库迁移记录的文件存放于app01下的migrations文件里

 注意 在命令行执行 python manage.py migrate 进行数据迁移时报以下错误:

......

  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/importlib/__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/django/db/backends/mysql/base.py", line 36, in <module>
    raise ImproperlyConfigured('mysqlclient 1.3.13 or newer is required; you have %s.' % Database.__version__)
django.core.exceptions.ImproperlyConfigured: mysqlclient 1.3.13 or newer is required; you have 0.9.3.

 根据最后两行的提示,mysqlclient 版本不够新,可是我已经都安装的最新版本了呀    

问题缘由

执行命令时,仔细看下报错的倒数第三行,已经告诉你是在 base.py (能够按住Ctrl而后点击鼠标连接进去)第 36 行报的错,根据你的提示路径打开 base.py,把 3五、36 行前面加 # 注释掉就行了,就像下面这样:

34 version = Database.version_info 35 #if version < (1, 3, 13):
 36 # raise ImproperlyConfigured('mysqlclient 1.3.13 or newer is required; you have %s.' % Database.__version__)
 37

如今再次执行命令,上面的报错已经没有了,可是又有了新的错误,看下面怎么解决

AttributeError: 'str' object has no attribute 'decode'

解决了上面的问题后,又遇到下面这个错误:

File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/django/db/backends/mysql/operations.py", line 146, in last_executed_query query = query.decode(errors='replace') AttributeError: 'str' object has no attribute 'decode'

提示属性错误:“str”对象没有属性“decode”。

问题的缘由是,在 Python3 里:

  • str 经过 encode() 转换成 bytes
  • bytes 经过 decode() 转换成 str
  • 也就是说:str 只有 encode() 方法,bytes 只有 decode() 方法

这个估计是 django 的 bug 了。

解决方法:

  • 根据提示打开报错的文件 operations.py
  • 找到 146 行,把 decode 改为 encode 便可,相似下面这样:
1 140     def last_executed_query(self, cursor, sql, params): 2 141         # With MySQLdb, cursor objects have an (undocumented) "_executed"
3 142         # attribute where the exact query sent to the database is saved.
4 143         # See MySQLdb/cursors.py in the source distribution.
5 144         query = getattr(cursor, '_executed', None) 6 145         if query is not None: 7 146             query = query.encode(errors='replace')    # 这里把 decode 改成 encode
8 147         return query

此时,再次执行命令就不报错了,大功告成!

相关文章
相关标签/搜索