摘要:本文學(xué)習(xí)使用連接數(shù)據(jù)庫,創(chuàng)建一個博客應(yīng)用所需要的數(shù)據(jù)表,并介紹了使用進(jìn)行簡單了操作及使用生成測試數(shù)據(jù)。多對多關(guān)系一篇博客通常有一個分類,好幾個標(biāo)簽。
1.簡述
最近在學(xué)習(xí)tornado,發(fā)現(xiàn)沒有Orm模型。其自帶的torndb模塊不支持python3,學(xué)習(xí)一下SQLAlchemy供以后工作中使用。
本文學(xué)習(xí)使用 SQLAlchemy 連接 MySQL 數(shù)據(jù)庫,創(chuàng)建一個博客應(yīng)用所需要的數(shù)據(jù)表,并介紹了使用 SQLAlchemy 進(jìn)行簡單了 CURD 操作及使用 Faker 生成測試數(shù)據(jù)。
1.1 知識要點(diǎn)學(xué)會用 SQLALchemy 連接數(shù)據(jù)庫(MySQL, SQLite, PostgreSQL), 創(chuàng)建數(shù)據(jù)表;
掌握表數(shù)據(jù)之間一對一,一對多及多對多的關(guān)系并能轉(zhuǎn)化為對應(yīng) SQLAlchemy 描述;
掌握使用 SQLAlchemy 進(jìn)行 CURD 操作;
學(xué)會使用 Faker 生成測試數(shù)據(jù)
2. ORM 與 SQLAlchemy 簡單介紹ORM 全稱 Object Relational Mapping, 翻譯過來叫對象關(guān)系映射。簡單的說,ORM 將數(shù)據(jù)庫中的表與面向?qū)ο笳Z言中的類建立了一種對應(yīng)關(guān)系。這樣,我們要操作數(shù)據(jù)庫,數(shù)據(jù)庫中的表或者表中的一條記錄就可以直接通過操作類或者類實(shí)例來完成。
SQLAlchemy 是Python 社區(qū)最知名的 ORM 工具之一,為高效和高性能的數(shù)據(jù)庫訪問設(shè)計(jì),實(shí)現(xiàn)了完整的企業(yè)級持久模型。
接下來我們將使用 SQLAlchemy 和 MySQL 構(gòu)建一個博客應(yīng)用的實(shí)驗(yàn)庫。
3. 連接與創(chuàng)建安裝SQLAlchemy
pip install sqlalchemy
數(shù)據(jù)庫我們采用Mysql,安裝過程這里省略。可參考我的lnmp安裝步驟
http://www.jianshu.com/p/1e51985b46dd
啟動mysql服務(wù)
systemctl start mysqld
進(jìn)入數(shù)據(jù)庫命令行
mysql
更改數(shù)據(jù)庫授權(quán),遠(yuǎn)程主機(jī)可訪問
update mysql.user set Host="%" where HOST="localhost" and User="root";
接下來我們使用圖形化數(shù)據(jù)庫操作工具(Navicat Premium)來操作數(shù)據(jù)庫
創(chuàng)建一個blog的數(shù)據(jù)庫
安裝數(shù)據(jù)庫驅(qū)動
pip install pymysql3.1 連接數(shù)據(jù)庫
新建一個db.py的文件,寫入下面的內(nèi)容:
#!/usr/bin/env python # _*_ coding:utf-8 _*_ __author__ = "junxi" from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base engine = create_engine("mysql+pymysql://blog:123456@localhost:3306/blog?charset=utf8") Base = declarative_base() print(engine)
運(yùn)行:
Engine(mysql+pymysql://blog:***@localhost:3306/blog?charset=utf8)3.2 描述表結(jié)構(gòu)
要使用 ORM, 我們需要將數(shù)據(jù)表的結(jié)構(gòu)用 ORM 的語言描述出來。SQLAlchmey 提供了一套 Declarative 系統(tǒng)來完成這個任務(wù)。我們以創(chuàng)建一個 users 表為例,看看它是怎么用 SQLAlchemy 的語言來描述的:
編輯db.py:
#!/usr/bin/env python # _*_ coding:utf-8 _*_ __author__ = "junxi" from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, String, Integer, Text, Boolean, DateTime, ForeignKey, Table from sqlalchemy.orm import relationship, sessionmaker engine = create_engine("mysql+pymysql://blog:123456@localhost:3306/blog?charset=utf8") Base = declarative_base() class User(Base): __tablename__ = "users" id = Column(Integer, primary_key=True) username = Column(String(64), nullable=False, index=True) password = Column(String(64), nullable=False) email = Column(String(64), nullable=False, index=True) def __repr__(self): return "%s(%r)" % (self.__class__.__name__, self.username) if __name__ == "__main__": Base.metadata.create_all(engine)
我們看到,在 User 類中,用 __tablename__ 指定在 MySQL 中表的名字。我們創(chuàng)建了三個基本字段,類中的每一個 Column 代表數(shù)據(jù)庫中的一列,在 Colunm中,指定該列的一些配置。第一個字段代表類的數(shù)據(jù)類型,上面我們使用 String, Integer 倆個最常用的類型,其他常用的包括:
Text
Boolean
SmallInteger
DateTime
ForeignKey
nullable=False 代表這一列不可以為空,index=True 表示在該列創(chuàng)建索引。
另外定義 __repr__ 是為了方便調(diào)試,你可以不定義,也可以定義的更詳細(xì)一些。
運(yùn)行 db.py
運(yùn)行程序,我們在Mysql命令行中看看表是如何創(chuàng)建的:
C:Windowssystem32>mysql -ublog -p123456 mysql> use blog; Database changed mysql> show create table usersG; *************************** 1. row *************************** Table: users Create Table: CREATE TABLE `users` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(64) NOT NULL, `password` varchar(64) NOT NULL, `email` varchar(64) NOT NULL, PRIMARY KEY (`id`), KEY `ix_users_username` (`username`), KEY `ix_users_email` (`email`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 1 row in set (0.00 sec)4. 關(guān)系定義 4.1 一對多關(guān)系
一個普通的博客應(yīng)用,用戶和文章顯然是一個一對多的關(guān)系,一篇文章屬于一個用戶,一個用戶可以寫很多篇文章,那么他們之間的關(guān)系可以這樣定義:
class User(Base): __tablename__ = "users" id = Column(Integer, primary_key=True) username = Column(String(64), nullable=False, index=True) password = Column(String(64), nullable=False) email = Column(String(64), nullable=False, index=True) articles = relationship("Article") def __repr__(self): return "%s(%r)" % (self.__class__.__name__, self.username) class Article(Base): __tablename__ = "articles" id = Column(Integer, primary_key=True) title = Column(String(255), nullable=False, index=True, name="標(biāo)題") content = Column(Text) user_id = Column(Integer, ForeignKey("users.id")) author = relationship("User") def __repr__(self): return "%s(%r)" % (self.__class__.__name__, self.title)
每篇文章有一個外鍵指向 users 表中的主鍵 id, 而在 User 中使用 SQLAlchemy 提供的 relationship 描述 關(guān)系。而用戶與文章的之間的這個關(guān)系是雙向的,所以我們看到上面的兩張表中都定義了 relationship。
SQLAlchemy 提供了 backref 讓我們可以只需要定義一個關(guān)系:
articles = relationship("Article", backref="author")
添加了這個就可以不用再在 Article 中定義 relationship 了!
在 User 中我們只定義了幾個必須的字段, 但通常用戶還有很多其他信息,但這些信息可能不是必須填寫的,我們可以把它們放到另一張 UserInfo 表中,這樣User 和 UserInfo 就形成了一對一的關(guān)系。你可能會奇怪一對一關(guān)系為什么不在一對多關(guān)系前面?那是因?yàn)橐粚σ魂P(guān)系是基于一對多定義的:
class User(Base): __tablename__ = "users" id = Column(Integer, primary_key=True) username = Column(String(64), nullable=False, index=True) password = Column(String(64), nullable=False) email = Column(String(64), nullable=False, index=True) articles = relationship("Article") userinfo = relationship("UserInfo", backref="user", uselist=False) def __repr__(self): return "%s(%r)" % (self.__class__.__name__, self.username) class UserInfo(Base): __tablename__ = "userinfos" id = Column(Integer, primary_key=True) name = Column(String(64)) qq = Column(String(11)) phone = Column(String(11)) link = Column(String(64)) user_id = Column(Integer, ForeignKey("users.id"))
定義方法和一對多相同,只是需要添加 userlist=False 。
4.3 多對多關(guān)系一篇博客通常有一個分類,好幾個標(biāo)簽。標(biāo)簽與博客之間就是一個多對多的關(guān)系。多對多關(guān)系不能直接定義,需要分解成倆個一對多的關(guān)系,為此,需要一張額外的表來協(xié)助完成:
""" # 這是創(chuàng)建表的另一種寫法 article_tag = Table( "article_tag", Base.metadata, Column("article_id", Integer, ForeignKey("articles.id")), Column("tag_id", Integer, ForeignKey("tags.id")) ) """ class ArticleTag(Base): __tablename__ = "article_tag" id = Column(Integer, primary_key=True) article_id = Column(Integer, ForeignKey("articles.id")) tag_id = Column(Integer, ForeignKey("tags.id")) class Tag(Base): __tablename__ = "tags" id = Column(Integer, primary_key=True) name = Column(String(64), nullable=False, index=True) def __repr__(self): return "%s(%r)" % (self.__class__.__name__, self.name)4.4 映射到數(shù)據(jù)庫
#!/usr/bin/env python # _*_ coding:utf-8 _*_ __author__ = "junxi" """ mysql://username:password@hostname/database postgresql://username:password@hostname/database sqlite:////absolute/path/to/database sqlite:///c:/absolute/path/to/database """ from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, String, Integer, Text, Boolean, DateTime, ForeignKey, Table from sqlalchemy.orm import relationship, sessionmaker engine = create_engine("mysql+pymysql://blog:123456@localhost:3306/blog?charset=utf8") Base = declarative_base() # print(engine) class User(Base): __tablename__ = "users" id = Column(Integer, primary_key=True) username = Column(String(64), nullable=False, index=True) password = Column(String(64), nullable=False) email = Column(String(64), nullable=False, index=True) articles = relationship("Article") userinfo = relationship("UserInfo", backref="user", uselist=False) def __repr__(self): return "%s(%r)" % (self.__class__.__name__, self.username) class UserInfo(Base): __tablename__ = "userinfos" id = Column(Integer, primary_key=True) name = Column(String(64)) qq = Column(String(11)) phone = Column(String(11)) link = Column(String(64)) user_id = Column(Integer, ForeignKey("users.id")) class Article(Base): __tablename__ = "articles" id = Column(Integer, primary_key=True) title = Column(String(255), nullable=False, index=True) content = Column(Text) user_id = Column(Integer, ForeignKey("users.id")) author = relationship("User") def __repr__(self): return "%s(%r)" % (self.__class__.__name__, self.title) """ # 這是創(chuàng)建表的另一種寫法 article_tag = Table( "article_tag", Base.metadata, Column("article_id", Integer, ForeignKey("articles.id")), Column("tag_id", Integer, ForeignKey("tags.id")) ) """ class ArticleTag(Base): __tablename__ = "article_tag" id = Column(Integer, primary_key=True) article_id = Column(Integer, ForeignKey("articles.id")) tag_id = Column(Integer, ForeignKey("tags.id")) class Tag(Base): __tablename__ = "tags" id = Column(Integer, primary_key=True) name = Column(String(64), nullable=False, index=True) def __repr__(self): return "%s(%r)" % (self.__class__.__name__, self.name) if __name__ == "__main__": Base.metadata.create_all(engine)
進(jìn)入MySQL查看:
mysql> use blog; Database changed mysql> show tables; +----------------+ | Tables_in_blog | +----------------+ | article_tag | | articles | | tags | | userinfos | | users | +----------------+ 5 rows in set (0.00 sec)
所有的表都已經(jīng)創(chuàng)建好了!
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/41632.html
摘要:另外,項(xiàng)目在單元測試中使用的是的內(nèi)存數(shù)據(jù)庫,這樣開發(fā)者運(yùn)行單元測試的時候不需要安裝和配置復(fù)雜的數(shù)據(jù)庫,只要安裝好就可以了。而且,數(shù)據(jù)庫是保存在內(nèi)存中的,會提高單元測試的速度。是實(shí)現(xiàn)層的基礎(chǔ)。項(xiàng)目一般會使用數(shù)據(jù)庫來運(yùn)行單元測試。 OpenStack中的關(guān)系型數(shù)據(jù)庫應(yīng)用 OpenStack中的數(shù)據(jù)庫應(yīng)用主要是關(guān)系型數(shù)據(jù)庫,主要使用的是MySQL數(shù)據(jù)庫。當(dāng)然也有一些NoSQL的應(yīng)用,比如Ce...
摘要:數(shù)據(jù)庫關(guān)系數(shù)據(jù)庫將數(shù)據(jù)保存在表中來模擬應(yīng)用程序中不同的實(shí)體。這些行之間的連接稱作關(guān)系,也是關(guān)系數(shù)據(jù)庫模型的基礎(chǔ)。就像這個示例中看到的那樣,關(guān)系數(shù)據(jù)庫存儲數(shù)據(jù)高效且避免重復(fù)。最好的例子就是,支持一組關(guān)系數(shù)據(jù)庫引擎,包括流行的和。 數(shù)據(jù)庫就是有組織的存儲應(yīng)用程序數(shù)據(jù),然后查詢檢索指定需要的那部分。大部分web應(yīng)用程序都采用基于關(guān)系模型的數(shù)據(jù)庫,也稱作結(jié)構(gòu)化查詢語言(SQL)數(shù)據(jù)庫。但是最近...
摘要:查詢記錄在調(diào)試或測試模式自動啟用。可以用于顯式禁用原生支持。當(dāng)使用不合適的指定無編碼的數(shù)據(jù)庫默認(rèn)值時,這對于一些數(shù)據(jù)庫適配器是必須的比如上某些版本的。這對是必要的,它默認(rèn)移除閑置多于小時的連接。注意如果使用了,自動設(shè)定這個值為小時。 flask-sqlalchemy是flask的一個ORM擴(kuò)展框架,這個擴(kuò)展在sqlalchemy的進(jìn)行的擴(kuò)展,更方便的結(jié)合Flask.什么是ORM?其是O...
摘要:數(shù)據(jù)庫關(guān)系數(shù)據(jù)庫將數(shù)據(jù)保存在表中來模擬應(yīng)用程序中不同的實(shí)體。這些行之間的連接稱作關(guān)系,也是關(guān)系數(shù)據(jù)庫模型的基礎(chǔ)。就像這個示例中看到的那樣,關(guān)系數(shù)據(jù)庫存儲數(shù)據(jù)高效且避免重復(fù)。最好的例子就是,支持一組關(guān)系數(shù)據(jù)庫引擎,包括流行的和。 數(shù)據(jù)庫就是有組織的存儲應(yīng)用程序數(shù)據(jù),然后查詢檢索指定需要的那部分。大部分web應(yīng)用程序都采用基于關(guān)系模型的數(shù)據(jù)庫,也稱作結(jié)構(gòu)化查詢語言(SQL)數(shù)據(jù)庫。但是最近...
閱讀 964·2023-04-26 02:56
閱讀 9438·2021-11-23 09:51
閱讀 1850·2021-09-26 10:14
閱讀 2980·2019-08-29 13:09
閱讀 2154·2019-08-26 13:29
閱讀 571·2019-08-26 12:02
閱讀 3562·2019-08-26 10:42
閱讀 3000·2019-08-23 18:18