天天看點

[Django] Django 連接配接 MySQL資料庫 以及 makemigrations&migrate 過程詳解總結安裝MySQL資料庫安裝mysqlclient包配置settings.py檔案生成遷移檔案生成資料庫的表

Django 連接配接 MySQL資料庫過程

  • 安裝MySQL資料庫
  • 安裝mysqlclient包
  • 配置settings.py檔案
  • 生成遷移檔案
    • ORM
    • 遷移檔案
    • 具體操作
  • 生成資料庫的表

安裝MySQL資料庫

Django自帶的是SQLite資料庫的, 如果要使用MySQL資料庫, 則需要重新安裝, 安裝教程參考

Centos7安裝MySQL8過程詳解筆記 (附相關錯誤解決辦法)

安裝mysqlclient包

  • python通路mysql資料庫 需要第三方包, Django推薦使用mysqlclient.
  • 安裝指令

    pip3 install mysqlclient

    (blog) [[email protected] testBlog]# yum install mysqlclient
    Loaded plugins: fastestmirror, langpacks
    Loading mirror speeds from cached hostfile
     * base: mirrors.aliyun.com
     * epel: mirrors.aliyun.com
     * extras: mirrors.aliyun.com
     * updates: mirrors.aliyun.com
    No package mysqlclient available.
    Error: Nothing to do
    (blog) [[email protected] testBlog]# pip3 install mysqlclient
    Collecting mysqlclient
      Using cached mysqlclient-1.4.6.tar.gz (85 kB)
        ERROR: Command errored out with exit status 1:
         command: /root/env/blog/bin/python -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-yl6cmbzb/mysqlclient/setup.py'"'"'; __file__='"'"'/tmp/pip-install-yl6cmbzb/mysqlclient/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info --egg-base /tmp/pip-install-yl6cmbzb/mysqlclient/pip-egg-info
             cwd: /tmp/pip-install-yl6cmbzb/mysqlclient/
        Complete output (12 lines):
        /bin/sh: mysql_config: command not found
        /bin/sh: mariadb_config: command not found
        /bin/sh: mysql_config: command not found
        Traceback (most recent call last):
          File "<string>", line 1, in <module>
          File "/tmp/pip-install-yl6cmbzb/mysqlclient/setup.py", line 16, in <module>
            metadata, options = get_config()
          File "/tmp/pip-install-yl6cmbzb/mysqlclient/setup_posix.py", line 61, in get_config
            libs = mysql_config("libs")
          File "/tmp/pip-install-yl6cmbzb/mysqlclient/setup_posix.py", line 29, in mysql_config
            raise EnvironmentError("%s not found" % (_mysql_config_path,))
        OSError: mysql_config not found
        ----------------------------------------
    ERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.
               
  • 上述報錯顯示mysql_config變量未找到, 需要安裝mysql相關依賴

    yum install mysql-devel

    安裝成功後, 繼續執行

    pip3 install mysqlclient

    (blog) [[email protected] bin]# pip3 install mysqlclient
    Collecting mysqlclient
      Using cached mysqlclient-1.4.6.tar.gz (85 kB)
    Building wheels for collected packages: mysqlclient
      Building wheel for mysqlclient (setup.py) ... error
      ERROR: Command errored out with exit status 1:
       command: /root/env/blog/bin/python -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-rqkddtxm/mysqlclient/setup.py'"'"'; __file__='"'"'/tmp/pip-install-rqkddtxm/mysqlclient/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' bdist_wheel -d /tmp/pip-wheel-eexcuz_5
           cwd: /tmp/pip-install-rqkddtxm/mysqlclient/
      Complete output (31 lines):
      running bdist_wheel
      running build
      running build_py
      creating build
      creating build/lib.linux-x86_64-3.6
      creating build/lib.linux-x86_64-3.6/MySQLdb
      copying MySQLdb/__init__.py -> build/lib.linux-x86_64-3.6/MySQLdb
      copying MySQLdb/_exceptions.py -> build/lib.linux-x86_64-3.6/MySQLdb
      copying MySQLdb/compat.py -> build/lib.linux-x86_64-3.6/MySQLdb
      copying MySQLdb/connections.py -> build/lib.linux-x86_64-3.6/MySQLdb
      copying MySQLdb/converters.py -> build/lib.linux-x86_64-3.6/MySQLdb
      copying MySQLdb/cursors.py -> build/lib.linux-x86_64-3.6/MySQLdb
      copying MySQLdb/release.py -> build/lib.linux-x86_64-3.6/MySQLdb
      copying MySQLdb/times.py -> build/lib.linux-x86_64-3.6/MySQLdb
      creating build/lib.linux-x86_64-3.6/MySQLdb/constants
      copying MySQLdb/constants/__init__.py -> build/lib.linux-x86_64-3.6/MySQLdb/constants
      copying MySQLdb/constants/CLIENT.py -> build/lib.linux-x86_64-3.6/MySQLdb/constants
      copying MySQLdb/constants/CR.py -> build/lib.linux-x86_64-3.6/MySQLdb/constants
      copying MySQLdb/constants/ER.py -> build/lib.linux-x86_64-3.6/MySQLdb/constants
      copying MySQLdb/constants/FIELD_TYPE.py -> build/lib.linux-x86_64-3.6/MySQLdb/constants
      copying MySQLdb/constants/FLAG.py -> build/lib.linux-x86_64-3.6/MySQLdb/constants
      running build_ext
      building 'MySQLdb._mysql' extension
      creating build/temp.linux-x86_64-3.6
      creating build/temp.linux-x86_64-3.6/MySQLdb
      gcc -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -D_GNU_SOURCE -fPIC -fwrapv -fPIC -Dversion_info=(1,4,6,'final',0) -D__version__=1.4.6 -I/usr/include/mysql -I/root/env/blog/include -I/usr/include/python3.6m -c MySQLdb/_mysql.c -o build/temp.linux-x86_64-3.6/MySQLdb/_mysql.o -m64
      MySQLdb/_mysql.c:38:20: fatal error: Python.h: No such file or directory
       #include "Python.h"
                          ^
      compilation terminated.
      error: command 'gcc' failed with exit status 1
      ----------------------------------------
      ERROR: Failed building wheel for mysqlclient
      Running setup.py clean for mysqlclient
    Failed to build mysqlclient
    Installing collected packages: mysqlclient
        Running setup.py install for mysqlclient ... error
        ERROR: Command errored out with exit status 1:
         command: /root/env/blog/bin/python -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-rqkddtxm/mysqlclient/setup.py'"'"'; __file__='"'"'/tmp/pip-install-rqkddtxm/mysqlclient/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' install --record /tmp/pip-record-83ml8lxb/install-record.txt --single-version-externally-managed --compile --install-headers /root/env/blog/include/site/python3.6/mysqlclient
             cwd: /tmp/pip-install-rqkddtxm/mysqlclient/
        Complete output (31 lines):
        running install
        running build
        running build_py
        creating build
        creating build/lib.linux-x86_64-3.6
        creating build/lib.linux-x86_64-3.6/MySQLdb
        copying MySQLdb/__init__.py -> build/lib.linux-x86_64-3.6/MySQLdb
        copying MySQLdb/_exceptions.py -> build/lib.linux-x86_64-3.6/MySQLdb
        copying MySQLdb/compat.py -> build/lib.linux-x86_64-3.6/MySQLdb
        copying MySQLdb/connections.py -> build/lib.linux-x86_64-3.6/MySQLdb
        copying MySQLdb/converters.py -> build/lib.linux-x86_64-3.6/MySQLdb
        copying MySQLdb/cursors.py -> build/lib.linux-x86_64-3.6/MySQLdb
        copying MySQLdb/release.py -> build/lib.linux-x86_64-3.6/MySQLdb
        copying MySQLdb/times.py -> build/lib.linux-x86_64-3.6/MySQLdb
        creating build/lib.linux-x86_64-3.6/MySQLdb/constants
        copying MySQLdb/constants/__init__.py -> build/lib.linux-x86_64-3.6/MySQLdb/constants
        copying MySQLdb/constants/CLIENT.py -> build/lib.linux-x86_64-3.6/MySQLdb/constants
        copying MySQLdb/constants/CR.py -> build/lib.linux-x86_64-3.6/MySQLdb/constants
        copying MySQLdb/constants/ER.py -> build/lib.linux-x86_64-3.6/MySQLdb/constants
        copying MySQLdb/constants/FIELD_TYPE.py -> build/lib.linux-x86_64-3.6/MySQLdb/constants
        copying MySQLdb/constants/FLAG.py -> build/lib.linux-x86_64-3.6/MySQLdb/constants
        running build_ext
        building 'MySQLdb._mysql' extension
        creating build/temp.linux-x86_64-3.6
        creating build/temp.linux-x86_64-3.6/MySQLdb
        gcc -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -D_GNU_SOURCE -fPIC -fwrapv -fPIC -Dversion_info=(1,4,6,'final',0) -D__version__=1.4.6 -I/usr/include/mysql -I/root/env/blog/include -I/usr/include/python3.6m -c MySQLdb/_mysql.c -o build/temp.linux-x86_64-3.6/MySQLdb/_mysql.o -m64
        MySQLdb/_mysql.c:38:20: fatal error: Python.h: No such file or directory
         #include "Python.h"
                            ^
        compilation terminated.
        error: command 'gcc' failed with exit status 1
        ----------------------------------------
    ERROR: Command errored out with exit status 1: /root/env/blog/bin/python -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-rqkddtxm/mysqlclient/setup.py'"'"'; __file__='"'"'/tmp/pip-install-rqkddtxm/mysqlclient/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' install --record /tmp/pip-record-83ml8lxb/install-record.txt --single-version-externally-managed --compile --install-headers /root/env/blog/include/site/python3.6/mysqlclient Check the logs for full command output.
               
  • 上述報錯顯示mysql_config變量未找到, 需要安裝mysql相關依賴

    yum install python3-devel

    yum install gcc gcc-devel

    這次安裝成功後, 繼續執行

    pip3 install mysqlclient

    , 成功安裝mysqlclient

配置settings.py檔案

  • 配置資料庫選項
    DATABASES = {
    		    'default': {
    		        'ENGINE': 'django.db.backends.mysql', # 資料庫引擎
    		        'NAME': 'djangotest', #資料庫名稱
    		        'USER': 'root', # 連結資料庫的使用者名
    		        'PASSWORD': 'root', # 連結資料庫的密碼
    		        'HOST': '127.0.0.1', # mysql伺服器的域名和ip位址
    		        'PORT': '3306', # mysql的一個端口号,預設是3306
    		    }
    		}
               

生成遷移檔案

ORM

  • Django是采用ORM技術來操作資料庫的
    • ORM(object relation mapping): 對象關系映射, 簡單的說這種技術是把資料庫中的表與面向對象程式設計中的類建立映射, 表中的記錄與類的對象建立映射, 記錄中的字段與對象中的屬性建立映射. 然乎使用面向對象程式設計的文法來完成對資料庫的操作
    據庫 面向對象
    對象
    屬性
    • 比如執行一條sql語句:

      select first_name from person where id=10

      ORM可以寫成:

      p=Person.get(10) name = p.first_name

    • ORM封裝了資料庫的底層操作, 給開發者提供了一層接口, 開發者可以使用熟悉的面向對象程式設計的文法與資料對象直接
    • ORM的優點
      • 代碼變的簡單易讀
      • 避免了繁瑣的sql語句
      • 不用操作表, 使用面向對象的思路進行程式設計
    • ORM的缺點
      • 開發者無法了解底層資料庫的操作, 無法自定義一些複雜的sql
      • ORM 庫的文法和相關設定需要重新學習

遷移檔案

  • Django中資料模型的代碼采用面向對象的思想在app下的models.py中編寫, 擁有自己特定的文法格式
  • Django并不是把models.py中的資料模型直接轉換成資料庫中的表, 而是先把資料模型檔案轉換成遷移檔案, 再由遷移檔案生成資料庫中的表

    資料模型 ----> 遷移檔案 ----> 資料庫中的表

  • 遷移檔案充當了對象到關系映射的中間使者
  • 遷移檔案存放在app下的migrations目錄下,

具體操作

  • 将所有app的資料模型轉換成遷移檔案 (注意: 生成遷移檔案的階段資料庫中還沒有表)

    python3 manage.py makemigrations

  • 隻把特定的app下的資料模型轉換成遷移檔案

    python3 manage.py makemigrations app_name

  • 檢視特定app下特定遷移檔案将會生成的sql操作(Django就是根據這些sql操作在資料庫中建立表)

    python3 manage.py sqlmigrate app_name 000N

    (所有生成的遷移檔案的檔案名都有一個000N的編号)
    [Django] Django 連接配接 MySQL資料庫 以及 makemigrations&amp;migrate 過程詳解總結安裝MySQL資料庫安裝mysqlclient包配置settings.py檔案生成遷移檔案生成資料庫的表
    (blog) [[email protected] migrations]# cat 0001_initial.py 
    # Generated by Django 3.0.5 on 2020-04-09 17:23
    
    from django.db import migrations, models
    
    
    class Migration(migrations.Migration):
    
        initial = True
    
        dependencies = [
        ]
    
        operations = [
            migrations.CreateModel(
                name='Account',
                fields=[
                    ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                    ('user', models.CharField(max_length=40)),
                    ('gender', models.IntegerField()),
                    ('birthday', models.DateField()),
                ],
            ),
        ]```
    
               
  • 顯示遷移檔案狀态: []代表還未遷移, [X]表示已經遷移完畢, 資料庫中生成了相應的表

    python3 manage.py showmigrations

    [Django] Django 連接配接 MySQL資料庫 以及 makemigrations&amp;migrate 過程詳解總結安裝MySQL資料庫安裝mysqlclient包配置settings.py檔案生成遷移檔案生成資料庫的表
  • 每執行一次makemigrations操作, django就會把目前的資料模型和migrations檔案夾下最新一次的遷移檔案中的資料模型進行對比
    • 如果相同, 則會提示: no changes, 不産生新檔案.
    • 如果不同, 則會将這部分不同 涉及的對資料庫的更改操作重新生成一個.py檔案存放在migrations檔案夾下.
    • 除了第一次migrations會有大規模建表的create語句外, 後續的都隻是在一些已有表上進行修改的操作, 并不會把資料模型整個重構
      [Django] Django 連接配接 MySQL資料庫 以及 makemigrations&amp;migrate 過程詳解總結安裝MySQL資料庫安裝mysqlclient包配置settings.py檔案生成遷移檔案生成資料庫的表
      [Django] Django 連接配接 MySQL資料庫 以及 makemigrations&amp;migrate 過程詳解總結安裝MySQL資料庫安裝mysqlclient包配置settings.py檔案生成遷移檔案生成資料庫的表
      (blog) [[email protected] migrations]# cat 0002_auto_20200409_1914.py 
      # Generated by Django 3.0.5 on 2020-04-09 19:14
      
      from django.db import migrations
      
      
      class Migration(migrations.Migration):
      
          dependencies = [
              ('app1', '0001_initial'),
          ]
      
          operations = [
              migrations.RenameField(
                  model_name='account',
                  old_name='birthday',
                  new_name='school',
              ),
          ]
                 

生成資料庫的表

  • 将所有app的遷移檔案都映射到資料庫, 全局映射隻會映射還沒有映射的檔案

    python3 manage.py migrate

  • 指定特定項目的所有遷移檔案映射到資料庫

    python3 manage.py migrate app_name

  • 指定特定項目下的特定遷移檔案映射到資料庫

    python3 manage.py migrate app_name 000N

  • 資料庫中的表隻會和最新一次遷移(migrate)的内容保持一緻, 是以如果遷移檔案的編号已經到了0007, 并且全部遷移檔案都已經遷移過一次. 此時如果再次遷移0005, 那麼0006和0007的遷移檔案産生的更改會全部被取消, 也就是unapplying
    [Django] Django 連接配接 MySQL資料庫 以及 makemigrations&amp;migrate 過程詳解總結安裝MySQL資料庫安裝mysqlclient包配置settings.py檔案生成遷移檔案生成資料庫的表
    (遷移第二個檔案)
    [Django] Django 連接配接 MySQL資料庫 以及 makemigrations&amp;migrate 過程詳解總結安裝MySQL資料庫安裝mysqlclient包配置settings.py檔案生成遷移檔案生成資料庫的表
    (遷移三個檔案)
    [Django] Django 連接配接 MySQL資料庫 以及 makemigrations&amp;migrate 過程詳解總結安裝MySQL資料庫安裝mysqlclient包配置settings.py檔案生成遷移檔案生成資料庫的表
    (所有檔案都以遷移完畢)
    [Django] Django 連接配接 MySQL資料庫 以及 makemigrations&amp;migrate 過程詳解總結安裝MySQL資料庫安裝mysqlclient包配置settings.py檔案生成遷移檔案生成資料庫的表
    再次遷移第一個檔案
    [Django] Django 連接配接 MySQL資料庫 以及 makemigrations&amp;migrate 過程詳解總結安裝MySQL資料庫安裝mysqlclient包配置settings.py檔案生成遷移檔案生成資料庫的表
    (第二第三産生的更改全部取)
  • 如果最新一次的遷移再次被執行, Django顯示沒有需要遷移的檔案
    Running migrations:
      No migrations to apply.
      Your models have changes that are not yet reflected in a migration, and so won't be applied.
      Run 'manage.py makemigrations' to make new migrations, and then re-run 'manage.py migrate' to apply them.
               

參考

  1. 第五章:Django連接配接mysql資料庫
  2. 了解Django的makemigrations和migrate
  3. 資料庫遷移(migrate)應該知道的一些事