flask項目結構(四)使用sqlalchemy和alembic

簡介

其實我不是啥正經人,錯了,不是啥正經程序員,所能想到的估計也就碼農一級吧,高級程序員,搞什麼算法,什麼人工智能,大數據計算…………離我還太遙遠。python

可是這並不妨礙我繼續學習,繼續寫垃圾小程序。mysql

反正我作的小程序,也就是把人從重複的勞動中解脫出來。用電腦代替人腦記憶那些枯燥的繁瑣的數據。用電腦來查詢記憶的數據。人腦的神經網絡是比計算機查找的快。隨便吧,還搞不到那個層次。先用電腦記錄查詢吧。linux

雖然python學習中已經學習了讀寫文件,在文件中查找,不過那都面向少許數據,更別提什麼大數據了。幾萬行數據,你試試,搞起來累死了。新武器,數據庫。nginx

數據庫:

抄吧
本詞條由「科普中國」百科科學詞條編寫與應用工做項目 審覈 。
數據庫(Database)是按照數據結構來組織、存儲和管理數據的倉庫,它產生於距今六十多年前,隨着信息技術和市場的發展,特別是二十世紀九十年代之後,數據管理再也不僅僅是存儲和管理數據,而轉變成用戶所須要的各類數據管理的方式。數據庫有不少種類型,從最簡單的存儲有各類數據的表格到可以進行海量數據存儲的大型數據庫系統都在各個方面獲得了普遍的應用。
在信息化社會,充分有效地管理和利用各種信息資源,是進行科學研究和決策管理的前提條件。數據庫技術是管理信息系統、辦公自動化系統、決策支持系統等各種信息系統的核心部分,是進行科學研究和決策管理的重要技術手段。git

就是存數據,查數據,改數據…………的工具集合。程序員

ORM:

繼續抄算法

對象關係映射(英語:(Object Relational Mapping,簡稱ORM,或O/RM,或O/R mapping),是一種程序技術,用於實現面向對象編程語言裏不一樣類型系統的數據之間的轉換。sql

也就是不用你管數據庫怎麼樣操做,怎麼處理了,把數據庫變成了你程序當中的對象,你就像操做對象同樣來操做數據庫。下降了程序員的學習成本,你不須要額外再去學數據庫了。簡單學習一下數據庫對象的操做就可使用數據庫了。docker

sqlalchemy:

還得抄shell

SQLAlchemy是Python編程語言下的一款開源軟件。提供了SQL工具包及對象關係映射(ORM)工具,使用MIT許可證發行。
SQLAlchemy「採用簡單的Python語言,爲高效和高性能的數據庫訪問設計,實現了完整的企業級持久模型」。SQLAlchemy的理念是,SQL數據庫的量級和性能重要於對象集合;而對象集合的抽象又重要於表和行。所以,SQLAlchmey採用了相似於Java裏Hibernate的數據映射模型,而不是其餘ORM框架採用的Active Record模型。不過,Elixir和declarative等可選插件可讓用戶使用聲明語法。

python中最出名的,最好用的,最…………反正python中,涉及數據庫的,我都用它了。

alembic:

不抄我怎麼解釋

一般咱們會將咱們的代碼放入到某個VCS(版本控制系統)中,進行可追溯的版本管理。一個項目除了代碼,一般還會有一個數據庫,這個數據庫可能會隨着項目的演進發生變化,甚至須要能夠回滾到過去的某個狀態,因而一些工具將數據庫的版本化也歸入了管理。

Alembic 是 Sqlalchemy 的做者實現的一個數據庫版本化管理工具,它能夠對基於Sqlalchemy的Model與數據庫之間的歷史關係進行版本化的維護。

隨着軟件的開發,功能的增長,方向的調整,數據庫的結構也會跟着變化,那麼數據庫結構怎麼管理呢?手動管理,實在不是程序員的辦法,alembic就是爲了自動化處理數據庫結構的工具。會隨着程序中對數據庫對象的定義,半自動的修改你的數據庫結構。

一:安裝依賴

在python項目的虛擬環境中安裝sqlalchemy  alembic 和 MySQL-connector-python

二:建立數據庫鏈接

在項目根目錄增長文件config.py,項目配置文件。

本例只寫入了數據庫配置。之後cookie,session,加密的鹽,都寫這裏吧。

config.py

from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy.ext.declarative import declarative_base

engine = create_engine('mysql+mysqlconnector://plan:plan@mysql/plan', convert_unicode=True)
db_session = scoped_session(sessionmaker(autocommit=False,
                                         autoflush=False,
                                         bind=engine))
Base = declarative_base()
Base.query = db_session.query_property()

這個配置文件使用了MySQL-connector-python庫鏈接第一篇文章寫的mariadb數據庫。

鏈接參數是'mysql+mysqlconnector://plan:plan@mysql/plan'

三:建立models

在項目根目錄建立目錄models,並在其中建立models.py文件。

models目錄是模型主目錄,公共部分模型,都放這裏。

models.py就是模型了。

在app/app01目錄下建立app01_models.py,app01的私有models,就定義在這裏了。

結構以下:

.
├── app
│   ├── alembic.ini
│   ├── app
│   │   ├── app01
│   │   │   ├── app01_models.py #新加,app01的私有models
│   │   │   └── views.py
│   │   ├── app02
│   │   │   └── views.py
│   │   └── main
│   │       └── views.py
│   ├── build_requirements.py
│   ├── config.py
│   ├── main.py
│   ├── migrate
│   │   ├── env.py
│   │   ├── README
│   │   ├── script.py.mako
│   │   └── versions
│   ├── models #新加目錄 │   │   └── models.py #公共models
│   └── requirements.txt
├── dockerfile
├── list.txt
└── rebuild.sh

/models/models.py

from config import Base
from sqlalchemy import Column, Integer, String


class User(Base):
    __tablename__ = 'public'
    id = Column(Integer, primary_key=True)
    public_name = Column(String(50))
    public_email = Column(String(120))
    
    def __init__(self, name=None, email=None):
        self.public_name = name
        self.public_email = email
    
    def __repr__(self):
        return '<User %r>' % (self.public_name)

/app/app01/app01_models.py

from config import Base
from sqlalchemy import Column, Integer, String


class app01(Base):
    __tablename__ = 'private'
    id = Column(Integer, primary_key=True)
    private_name = Column(String(50))
    private_email = Column(String(120))
    
    def __init__(self, name=None, email=None):
        self.private_name = name
        self.private_email = email
    
    def __repr__(self):
        return '<User %r>' % (self.private_name)

四:建立alembic擴展工具

在pycharm中用擴展工具來構建alembic的3條命令。

alembic init migrate                           建立alembic目錄結構

alembic revision --autogenerate       生成alembic升級腳本

alembic upgrade head                     升級數據庫結構到最新版

 

Program:$PyInterpreterDirectory$\alembic.exe這行比較長,抓圖看不清

五:建立alembic目錄結構

用剛纔配置的擴展工具執行 init也能夠。

直接執行命令  alembic init migrate 也能夠。

會在項目目錄下生成一個目錄  migrage  一個配置文件 alembic.ini

生成結果以下:

.
├── app
│   ├── alembic.ini #自動增長文件,需配置
│   ├── app
│   │   ├── app01
│   │   │   ├── app01_models.py
│   │   │   └── views.py
│   │   ├── app02
│   │   │   └── views.py
│   │   └── main
│   │       └── views.py
│   ├── build_requirements.py
│   ├── config.py
│   ├── main.py
│   ├── migrate #自動增長目錄 │   │   ├── env.py #需修改
│   │   ├── README
│   │   ├── script.py.mako
│   │   └── versions
│   └── requirements.txt
├── dockerfile
├── list.txt
└── rebuild.sh

六:配置alembic

上一節已經標明瞭,須要修改配置的有兩個文件。

alembic.ini,其中配置數據庫鏈接參數。

修改這行:

sqlalchemy.url = driver://user:pass@localhost/dbname

改成咱們的數據鏈接參數:

sqlalchemy.url = mysql+mysqlconnector://plan:plan@mysql/plan

env.py,其中配置models。

修改這行:

target_metadata = None

改成:

import os
import sys
sys.path.append(os.path.dirname(os.path.abspath(__file__)) + "/../")
from models import models
target_metadata = models.Base.metadata

其實我也不是很明白,大概就是引入路徑的問題,因此加了sys.path.append

七:生成升級腳本並升級數據庫

alembic revision --autogenerate       生成alembic升級腳本

alembic upgrade head                     升級數據庫結構到最新版

執行這兩個命令,或用擴展工具的圖形菜單。

八:檢查數據庫結構

跟隨第一張最後一節的測試。

點開數據庫,就能看到有表了。

以下:

哈哈,兩個對象結構,怎麼只有一個public,private不見了。

專門留下來,沒建立。

alembic_version,是alembic自動建立,用來控制版本的,不要動就行了。

九:數據庫版本控制

來,改一下alembic配置models的地方。

import os
import sys
sys.path.append(os.path.dirname(os.path.abspath(__file__)) + "/../")
from models import models
from app.app01 import app01_models  #此行增長
target_metadata = models.Base.metadata

因爲對象public和private都是由Base派生的,因此,只要target_metadata = models.Base.metadata,一遍就能夠了。

部分教程中寫的是target_metadata = [models.Base.metadata,app01_models.Base.metadata],不知道怎麼用。

多是鏈接多數據庫時候用的。之後須要分庫的時候再說吧。看不懂的請忽略。

再來一遍生成版本控制腳本和升級數據庫結構。

private也出來了。

這就是自動化的數據庫結構版本控制。

十:結合docker

看這個鏡像做者的使用說明:

Custom /app/prestart.sh

If you need to run anything before starting the app, you can add a file prestart.sh to the directory /app. The image will automatically detect and run it before starting everything.

For example, if you want to add Alembic SQL migrations (with SQLALchemy), you could create a ./app/prestart.sh file in your code directory (that will be copied by your Dockerfile) with:

#! /usr/bin/env bash # Let the DB start sleep 10; # Run migrations alembic upgrade head

and it would wait 10 seconds to give the database some time to start and then run that alembic command.

If you need to run a Python script before starting the app, you could make the /app/prestart.sh file run your Python script, with something like:

#! /usr/bin/env bash # Run custom Python script before starting python /app/my_custom_prestart_script.y

Note: The image uses source to run the script, so for example, environment variables would persist. If you don't understand the previous sentence, you probably don't need it.

你能夠在app啓動前,執行一些命令,那麼正好,咱們能夠執行數據庫版本升級。

在app目錄下,建立prestart.sh

#! /usr/bin/env bash
# Let the DB start
sleep 10;
# Run migrations
alembic upgrade head

好了,隨便改改你的數據庫結構。只生成一下升級腳本,不用執行到服務器。

重建鏡像,它在啓動的時候就會自動幫你升級數據庫版本到最新版本了。

我使用這個是由於,我服務器5點自動重啓,而後就連不上數據庫了。重啓Flask這個鏡像,一切正常,手動重啓服務器,竟然也都沒事。

這個升級數據庫腳本,正好在啓動APP前sleep 10秒。誰知道是否是由於啓動容器的順序的關係呢?這裏sleep 10秒,也能夠避免這個問題。

該文件請在linux下建立。

或者我寫進dockerfile。

FROM tiangolo/uwsgi-nginx-flask:python3.6-alpine3.7
MAINTAINER jackadam<jackadam@sina.com>
#變動源
# 安裝包源切到中科大, 國內訪問加速
RUN { \
        echo 'http://mirrors.ustc.edu.cn/alpine/v3.7/main'; \
        echo 'http://mirrors.ustc.edu.cn/alpine/v3.7/community'; \
        echo 'http://mirrors.ustc.edu.cn/alpine/edge/main'; \
        echo 'http://mirrors.ustc.edu.cn/alpine/edge/community'; \
        echo 'http://mirrors.ustc.edu.cn/alpine/edge/testing'; \
    } > /etc/apk/repositories && \

# 設置默認時區爲亞洲/上海 (沒有北京可選)
        apk add --no-cache --upgrade apk-tools  && \
    apk add --no-cache tzdata && \
    cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
    echo "Asia/Shanghai" > /etc/timezone && \
    apk del tzdata

#升級pip
RUN  pip3 install --upgrade pip

#複製依賴包列表
COPY ./app/requirements.txt /app/requirements.txt

#安裝依賴包
RUN  pip3 install  -i https://pypi.doubanio.com/simple -r /app/requirements.txt 

#建立prestart.sh
RUN { \
        echo '#! /usr/bin/env bash'; \
        echo '# Let the DB start'; \
        echo 'sleep 10;'; \
        echo '# Run migrations'; \
        echo 'alembic upgrade head'; \
    } > /app/prestart.sh

#複製flask源碼
COPY ./app /app

 

 

結語

到此,咱們已經建立了數據庫,新建flask項目,配置同步到服務器,服務器自動更新docker鏡像,用sqlalchemy鏈接數據庫,用alembic控制數據庫版本。

那麼程序的版本怎麼控制?用git啊。寫不寫git呢?

相關文章
相關標籤/搜索