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

此時,再次執行命令就不報錯了,大功告成!

相關文章
相關標籤/搜索