1. 程式人生 > >SQLAlchemy (1) -- Python的SQLAlchemy和ORM

SQLAlchemy (1) -- Python的SQLAlchemy和ORM

utf 之間 can env pre highlight als lis mys

Python的SQLAlchemy和ORM(object-relational mapping:對象關系映射)

web編程中有一項常規任務就是創建一個有效的後臺數據庫。以前,程序員是通過寫sql語句,發送到數據庫引擎,解析並返回一個記錄的數組。現在,程序員可以寫ORM程序來取代之前那種不靈活、難以維護的冗長、易出錯的sql語句。

ORM是面向對象編程語言中用來在不兼容的類型系統(incompatible type systems)之間轉換數據的一種編程技術。通常在OO語言中的類型系統,比如python包含的類型是非標量的,也就是說這些類型不能使用原始的類型比如(integer、string)來表達。比如,一個person對象可能含有一個address對象的列表,和一個phonenumber對象的列表。同理,一個address對象可能包含一個postcode對象,一個streetname對象和一個streetnumber對象。盡管簡單對象比如postcode、streetname可以用字符串來表示,但是更復雜的對象比如address、person就不能僅僅用字符串、整形數字來表示了。此外,這些復雜的對象還會具有實例或類方法,這些就更不能簡單用字符串或整形數字來表示了。

為了處理這些復雜的對象管理問題,人們設計了ORM。上面我們的示例可以用一個ORM系統表示出來:設計一個person類、address類、phonenumber類,每個類映射到數據庫中的一張表。這樣就不再需要編寫各種冗長的數據接口程序,而可以更加專註於系統的邏輯設計。

python中寫數據庫的代碼(舊的方式)

使用pymysql創建兩張表:

技術分享

編寫python腳本pymysql_ex.py並執行:

$ python pymysql_ex.py

#!/usr/bin/env python
# _*_ coding:utf-8 _*_

import pymysql

#創建鏈接
conn = pymysql.connect(host=‘127.0.0.1‘, port=3306, user=‘abce‘, passwd=‘abce‘, db=‘abce‘, charset=‘utf8‘)

#創建遊標
c = conn.cursor()

#執行sql建表,插入內容
c.execute(‘‘‘
          create table person
          (id integer primary key, name varchar(250) not null)
          ‘‘‘)
c.execute(‘‘‘
          create table address
          (id integer primary key, street_name varchar(250), street_number varchar(250),
           post_code varchar(250) not null, person_id integer not null,
           foreign key(person_id) references person(id))
          ‘‘‘)
 
c.execute(‘‘‘
          insert into person values(1, ‘pythoncentral‘)
          ‘‘‘)
c.execute(‘‘‘
          insert into address values(1, ‘python road‘, ‘1‘, ‘00000‘, 1)
          ‘‘‘)

#提交
conn.commit()

#關閉遊標
c.close()

#關閉連接
conn.close()

編寫腳本pymysql_q.py查看數據庫表的內容:

#!/usr/bin/env python
# _*_ coding:utf-8 _*_

import pymysql

#創建連接
conn = pymysql.connect(host=‘127.0.0.1‘, port=3306, user=‘abce‘, passwd=‘abce‘, db=‘abce‘, charset=‘utf8‘)

#創建遊標
c = conn.cursor()

#執行sql查看表內容
c.execute(‘select * from person‘)
print(c.fetchall())
c.execute(‘select * from address‘)
print(c.fetchall())

#關閉遊標
c.close()

#關閉連接
conn.close()
$ python pymysql_q.py 
((1, u‘pythoncentral‘),)
((1, u‘python road‘, u‘1‘, u‘00000‘, 1),)

例子中我們使pymysql連接提交對數據庫的修改,並使用pymysql的遊標來執行各種sql語句。盡管這些sql語句完成了相關的工作,但是維護sql語句的本身也不是件容易的事。下面,我們來看看sqlalchemy在Python得類和表之間是如何映射的。

  

Python‘s SQLAlchemy and Declarative

寫SQLAlchemy代碼有三個重要組件:
--數據庫中的表
--mapper:將python的類映射到數據庫中的表
--類對象,定義如何將數據庫的記錄映射到一個python對象

不需要在不同的地方寫表、mapper、class的代碼,SQLAlchemy的declarative支持將表、mapper和類對象定義到一個類中。

下面創建一個declarative (sqlalchemy_declarative.py)

#!/usr/bin/env python
# _*_ coding:utf-8 _*_
import pymysql
import os
import sys
from sqlalchemy import Column, ForeignKey, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship
from sqlalchemy import create_engine
 
Base = declarative_base()
 
class Person(Base):
    __tablename__ = ‘person‘
    # Here we define columns for the table person
    # Notice that each column is also a normal Python instance attribute.
    id = Column(Integer, primary_key=True)
    name = Column(String(250), nullable=False)
 
class Address(Base):
    __tablename__ = ‘address‘
    # Here we define columns for the table address.
    # Notice that each column is also a normal Python instance attribute.
    id = Column(Integer, primary_key=True)
    street_name = Column(String(250))
    street_number = Column(String(250))
    post_code = Column(String(250), nullable=False)
    person_id = Column(Integer, ForeignKey(‘person.id‘))
    person = relationship(Person)
 
# 連接數據庫采用pymysq模塊做映射,後面參數是最大連接數5
engine = create_engine(‘mysql+pymysql://abce:[email protected]:3306/abce?charset=utf8‘, max_overflow=5)
 
# Create all tables in the engine. This is equivalent to "Create Table"
# statements in raw SQL.
Base.metadata.create_all(engine)

執行腳本,就會創建了相應的數據庫表

$ python sqlalchemy_declarative.py

  

接下來,我們插入一些數據(sqlalchemy_insert.py)

#!/usr/bin/env python
# _*_ coding:utf-8 _*_
import pymysql
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
 
from sqlalchemy_declarative import Address, Base, Person
 
engine = create_engine(‘mysql+pymysql://abce:[email protected]:3306/abce?charset=utf8‘)
# Bind the engine to the metadata of the Base class so that the
# declaratives can be accessed through a DBSession instance
Base.metadata.bind = engine
 
DBSession = sessionmaker(bind=engine)
# A DBSession() instance establishes all conversations with the database
# and represents a "staging zone" for all the objects loaded into the
# database session object. Any change made against the objects in the
# session won‘t be persisted into the database until you call
# session.commit(). If you‘re not happy about the changes, you can
# revert all of them back to the last commit by calling
# session.rollback()
session = DBSession()
 
# Insert a Person in the person table
new_person = Person(name=‘new person‘)
session.add(new_person)
session.commit()
 
# Insert an Address in the address table
new_address = Address(post_code=‘00000‘, person=new_person)
session.add(new_address)
session.commit()

從數據庫後臺可以直接看到數據:

mysql> select * from person;
+----+------------+
| id | name       |
+----+------------+
|  1 | new person |
+----+------------+
1 row in set (0.00 sec)

mysql> select * from address;
+----+-------------+---------------+-----------+-----------+
| id | street_name | street_number | post_code | person_id |
+----+-------------+---------------+-----------+-----------+
|  1 | NULL        | NULL          | 00000     |         1 |
+----+-------------+---------------+-----------+-----------+
1 row in set (0.00 sec)

mysql>

  

當然我們得重點是從python中查看插入的數據:

>>> from sqlalchemy_declarative import Person, Base, Address
>>> from sqlalchemy import create_engine
>>> engine = create_engine(‘mysql+pymysql://abce:[email protected]:3306/abce?charset=utf8‘)
>>> Base.metadata.bind = engine
>>> from sqlalchemy.orm import sessionmaker
>>> DBSession = sessionmaker()
>>> DBSession.bind = engine
>>> session = DBSession()
>>> # Make a query to find all Persons in the database
>>> session.query(Person).all()
[<sqlalchemy_declarative.Person object at 0x21c7390>]
>>>
>>> # Return the first Person from all Persons in the database
>>> person = session.query(Person).first()
>>> person.name
u‘new person‘
>>>
>>> # Find all Address whose person field is pointing to the person object
>>> session.query(Address).filter(Address.person == person).all()
[<sqlalchemy_declarative.Address object at 0x22b08d0>]
>>>
>>> # Retrieve one Address whose person field is point to the person object
>>> session.query(Address).filter(Address.person == person).one()
<sqlalchemy_declarative.Address object at 0x22b08d0>
>>> address = session.query(Address).filter(Address.person == person).one()
>>> address.post_code
u‘00000‘

  

總結
以上就是如何使用sqlalchemy的declaratives來編寫數據庫代碼。和傳統的sql語句相比,顯得更面向對象、更易於理解和維護。

參考原文地址:http://pythoncentral.io/introductory-tutorial-python-sqlalchemy/

SQLAlchemy (1) -- Python的SQLAlchemy和ORM