2019独角兽企业重金招聘Python工程师标准>>>

终于来到sora开发准备的最后部分

peewee 管理数据库

1.明确地管理数据库连接(也可以考虑使用连接池)

database = SqliteDatabase('my_app.db')

def before_request_handler():

database.connect()

def after_request_handler():

database.close()

务必明确地处理数据库连接

2.在表类中设置内部类,以使用数据库

class MyModel(Model):

some_field = CharField()

class Meta:

database = database

最佳实践:定义一个基类指定要连接的数据库,其他的子类继承该类定义表格

database = SqliteDatabase('my_app.db')

class BaseModel(Model):

class Meta:

database = database

class User(BaseModel):

username = CharField()

class Tweet(BaseModel):

user = ForeignKeyField(User, related_name='tweets')

message = TextField()

# etc, etc

注意:在建表时不用建BaseModel表,只需处理User和Tweet

3.连接数据库(不同的数据库用不同的类)

mysql:

mysql_db = MySQLDatabase('my_database')

或者:

db = MySQLDatabase('my_db',host='localhost',port=3306,user='root',password='root')

class BaseModel(Model):

"""A base model that will use our MySQL database"""

class Meta:

database = mysql_db

class User(BaseModel):

username = CharField()

# etc, etc

如果使用url的话,需要这样操作:

import os

from peewee import *

from playhouse.db_url import connect

# Connect to the database URL defined in the environment, falling

# back to a local Sqlite database if no database URL is specified.

db = connect(os.environ.get('DATABASE') or 'sqlite:///default.db')

class BaseModel(Model):

class Meta:

database = db

url范例:

mysql://user:passwd@ip:3306/my_db

4.运行时修改数据库配置(根据运行参数修改要连接的数据库)

database = SqliteDatabase(None)  # Un-initialized database.

class SomeModel(Model):

class Meta:

database = database

>>> database.connect()

Exception: Error, database not properly initialized before opening connection

database_name = raw_input('What is the name of the db? ')

database.init(database_name, host='localhost', user='postgres')

使用init修改配置

5.动态修改数据库(使用proxy)

动态地换用不同的数据库(sqlite,mysql,postgreSQL)

database_proxy = Proxy()  # Create a proxy for our db.

class BaseModel(Model):

class Meta:

database = database_proxy  # Use proxy for our DB.

class User(BaseModel):

username = CharField()

# Based on configuration, use a different database.

if app.config['DEBUG']:

database = SqliteDatabase('local.db')

elif app.config['TESTING']:

database = SqliteDatabase(':memory:')

else:

database = PostgresqlDatabase('mega_production_db')

# Configure our proxy to use the db we specified in config.

database_proxy.initialize(database)

如果只是修改运行时的参数而非改变数据库类型,建议使用第四点的方法

6.连接池

连接池支持:

1、超时之后,连接将被回收

2、可以设置连接数的上限

from playhouse.pool import PooledPostgresqlExtDatabase

db = PooledPostgresqlExtDatabase(

'my_database',

max_connections=8,

stale_timeout=300,

user='postgres')

class BaseModel(Model):

class Meta:

database = db

Mysql相关的模块是:PooledMySQLDatabase

7.访问数据副本

使用ReadSlaveModel

from peewee import *

from playhouse.read_slave import ReadSlaveModel

# Declare a master and two read-replicas.

master = PostgresqlDatabase('master')

replica_1 = PostgresqlDatabase('replica', host='192.168.1.2')

replica_2 = PostgresqlDatabase('replica', host='192.168.1.3')

class BaseModel(ReadSlaveModel):

class Meta:

database = master

read_slaves = (replica_1, replica_2)

class User(BaseModel):

username = CharField()

注意:查询会在多个从数据库上以循环的方式执行

8.修改表的schema

通过playhouse的migrator

from playhouse.migrate import *

my_db = SqliteDatabase('my_database.db')

migrator = SqliteMigrator(my_db)

title_field = CharField(default='')

status_field = IntegerField(null=True)

with my_db.transaction():

migrate(

migrator.add_column('some_table', 'title', title_field),

migrator.add_column('some_table', 'status', status_field),

migrator.drop_column('some_table', 'old_column'),

)

更多内容要参考Schema Migrations部分的文档

9.从现有数据库生成相应的模块

使用pwiz实现

python -m pwiz -e mysql -H localhost -u root -P root user > md.py

生成的md.py如下

from peewee import *

database = MySQLDatabase('user', **{'host': 'localhost', 'password': 'root', 'user': 'root'})

class UnknownField(object):

pass

class BaseModel(Model):

class Meta:

database = database

class Infos(BaseModel):

name = CharField(null=True)

sex = CharField(null=True)

users = CharField(db_column='users_id', null=True)

class Meta:

db_table = 'infos'

class Usersinfo(BaseModel):

description = TextField(null=True)

user = IntegerField(db_column='user_id', null=True)

user_name = CharField(null=True)

user_password = CharField(null=True)

class Meta:

db_table = 'usersinfo'

该数据库的其中一个表:

mysql> desc infos;

+----------+-------------+------+-----+---------+-------+

| Field    | Type        | Null | Key | Default | Extra |

+----------+-------------+------+-----+---------+-------+

| sex      | varchar(20) | YES  |     | NULL    |       |

| name     | char(20)    | YES  |     | NULL    |       |

| users_id | varchar(40) | YES  |     | NULL    |       |

+----------+-------------+------+-----+---------+-------+

3 rows in set (0.01 sec)

10.model与fields

对应关系:

在peewee中,一个继承model类的类定义为某个数据库的一个表格

类中的feild,为数据库的列(字段)

一个model类实例则是一行

用例:

from peewee import *

db = SqliteDatabase('my_app.db')

class BaseModel(Model):

class Meta:

database = db

class User(BaseModel):

username = CharField(unique=True)

class Tweet(BaseModel):

user = ForeignKeyField(User, related_name='tweets')

message = TextField()

created_date = DateTimeField(default=datetime.datetime.now)

is_published = BooleanField(default=True)

不同的field与数据类型对照:

Field Type  Sqlite  Postgresql  MySQL

CharField   varchar varchar varchar

TextField   text    text    longtext

DateTimeField   datetime    timestamp   datetime

IntegerField    integer integer integer

BooleanField    smallint    boolean bool

FloatField  real    real    real

DoubleField real    double precision    double precision

BigIntegerField integer bigint  bigint

DecimalField    decimal numeric numeric

PrimaryKeyField integer serial  integer

ForeignKeyField integer integer integer

DateField   date    date    date

TimeField   time    time    time

BlobField   blob    bytea   blob

UUIDField   not supported   uuid    not supported

field的初始化参数:

null = False – boolean indicating whether null values are allowed to be stored

index = False – boolean indicating whether to create an index on this column

unique = False – boolean indicating whether to create a unique index on this column. See also adding composite indexes.

verbose_name = None – string representing the “user-friendly” name of this field

help_text = None – string representing any helpful text for this field

db_column = None – string representing the underlying column to use if different, useful for legacy databases

default = None – any value to use as a default for uninitialized models

choices = None – an optional iterable containing 2-tuples of value, display

primary_key = False – whether this field is the primary key for the table

sequence = None – sequence to populate field (if backend supports it)

constraints = None - a list of one or more constraints, e.g. [Check('price > 0')]

schema = None – optional name of the schema to use, if your db supports this.

有关DateTimeField, DateField and TimeField:

DateField有如下特性:

year

month

day

TimeField:

hour

minute

second

而DateTimeField有以上全部特性

简单用例:

# Get the current time.

now = datetime.datetime.now()

# Get days that have events for the current month.

Event.select(Event.event_date.day.alias('day')).where(

(Event.event_date.year == now.year) &

(Event.event_date.month == now.month))

11.创建model tables

首次使用某类时,需要执行创建表格的操作:

# Connect to our database.

db.connect()         #建议明确地控制连接

# Create the tables.

db.create_tables([User, Tweet])

可以有条件地创建表格:

# Only create the tables if they do not exist.

db.create_tables([User, Tweet], safe=True)

12.Model的options和Metadata

如果想访问某个表格类的meta,应该这样做:

>>> Person.Meta

Traceback (most recent call last):

File "<stdin>", line 1, in <module>

AttributeError: type object 'Preson' has no attribute 'Meta'

>>> Person._meta

<peewee.ModelOptions object at 0x7f51a2f03790>

查看ModelOptions:

>>> Person._meta.fields

{'id': <peewee.PrimaryKeyField object at 0x7f51a2e92750>, 'name': <peewee.CharField object at 0x7f51a2f0a510>}

>>> Person._meta.primary_key

<peewee.PrimaryKeyField object at 0x7f51a2e92750>

>>> Person._meta.database

<peewee.SqliteDatabase object at 0x7f519bff6dd0>

ModelOptions有如下成分:

Option  Meaning Inheritable?

database    database for model  yes

db_table    name of the table to store data no

indexes a list of fields to index   yes

order_by    a list of fields to use for default ordering    yes

primary_key a CompositeKey instance yes

table_alias an alias to use for the table in queries    no

schema  the database schema for the model   yes

validate_backrefs   ensure backrefs do not conflict with other attributes.  yes

简单用例:

>>> db = SqliteDatabase(':memory:')

>>> class ModelOne(Model):

...     class Meta:

...         database = db

...         db_table = 'model_one_tbl'

...

>>> class ModelTwo(ModelOne):

...     pass

...

>>> ModelOne._meta.database is ModelTwo._meta.database

True

>>> ModelOne._meta.db_table == ModelTwo._meta.db_table

False

12.索引和唯一约束

简单用例:

class User(Model):

username = CharField(unique=True)

email = CharField(index=True)

或者通过Meta来设置(第二个布尔型参数决定了是否创建唯一约束):

class Transaction(Model):

from_acct = CharField()

to_acct = CharField()

amount = DecimalField()

date = DateTimeField()

class Meta:

indexes = (

# create a unique on from/to/date

(('from_acct', 'to_acct', 'date'), True),

# create a non-unique on from/to

(('from_acct', 'to_acct'), False),

)

个人测试:

root@workgroup0:~# python

Python 2.7.6 (default, Mar 22 2014, 22:59:56)

[GCC 4.8.2] on linux2

Type "help", "copyright", "credits" or "license" for more information.

>>> from peewee import *

>>> db = MySQLDatabase('vmrecord',host='localhost',port=3306,user='root',password='root')

>>> class Performance(Model):

...   vm_id = IntegerField(unique=True)

...   desc = CharField(index=True)

...   class Meta:

...     database = db

...

>>> db.connect()

>>> db.create_tables([Performance,])

>>> for i in Performance.select():

...   print i.vm_id

...

123

124

>>> try:

...   a.save

... except IntegrityError:

...   print 'error'

...

<bound method Performance.save of <__main__.Performance object at 0x7f047311a750>>

>>> try:

...   a.save()

... except IntegrityError as e:

...   print e

...

(1062, "Duplicate entry '123' for key 'performance_vm_id'")

>>>

可以看到unique constraints已经起了作用

>>> b = Performance(vm_id='125',desc='use 10%')

>>> try:

...   b.save()

... except IntegrityError as error:

...   print error

... else:

...   print 'success'

...

1

success

mysql> select * from performance;

+----+-------+---------+

| id | vm_id | desc    |

+----+-------+---------+

|  1 |   123 | use 40% |

|  2 |   124 | use 40% |

|  5 |   125 | use 10% |

+----+-------+---------+

3 rows in set (0.01 sec)

13.复合主键

设置meta的primary key有多个,简单用例:

class BlogToTag(Model):

"""A simple "through" table for many-to-many relationship."""

blog = ForeignKeyField(Blog)

tag = ForeignKeyField(Tag)

class Meta:

primary_key = CompositeKey('blog', 'tag')

14.手动指定主键

你可以设置Meta中(用class._meta访问)的auto_increment为false(一次性),用例

data = load_user_csv() # load up a bunch of data

User._meta.auto_increment = False # turn off auto incrementing IDs

with db.transaction():

for row in data:

u = User(id=row[0], username=row[1])

u.save(force_insert=True) # <-- force peewee to insert row

User._meta.auto_increment = True

如果你想彻底控制主键,可以指定id这个field(可以使用integerFiled取代PrimaryKeyField):

class User(BaseModel):

id = IntegerField(primary_key=True)

username = CharField()

>>> u = User.create(id=999, username='somebody')

>>> u.id

999

>>> User.get(User.username == 'somebody').id

999

#此例中id字段不是自增的

注:如果不用PrimaryKeyField,创建表格时也会自动生成一个自增的id字段

个人测试:

>>> db.connect()

>>> db.create_tables([network,])

>>> class test1(Model):

...   username = CharField()

...   class Meta:

...     database = db

...

>>> class test2(Model):

...    id = IntegerField(primary_key=True)

...    username = CharField()

...    class Meta:

...     database = db

...

>>> db.create_tables([test1,test2])

>>>

mysql> desc test1;

+----------+--------------+------+-----+---------+----------------+

| Field    | Type         | Null | Key | Default | Extra          |

+----------+--------------+------+-----+---------+----------------+

| id       | int(11)      | NO   | PRI | NULL    | auto_increment |

| username | varchar(255) | NO   |     | NULL    |                |

+----------+--------------+------+-----+---------+----------------+

2 rows in set (0.00 sec)

mysql> desc test2;

+----------+--------------+------+-----+---------+-------+

| Field    | Type         | Null | Key | Default | Extra |

+----------+--------------+------+-----+---------+-------+

| id       | int(11)      | NO   | PRI | NULL    |       |

| username | varchar(255) | NO   |     | NULL    |       |

+----------+--------------+------+-----+---------+-------+

2 rows in set (0.00 sec)

15.Circular foreign key dependencies(我猜是两个表之间建立联系)

例子:

class User(Model):

username = CharField()

favorite_tweet = ForeignKeyField(Tweet, null=True)  # NameError!!

class Tweet(Model):

message = TextField()

user = ForeignKeyField(User, related_name='tweets')

因为在定义User时,Tweet还没定义,会导致NameError

可以用这个简单地处理id:

class User(Model):

username = CharField()

favorite_tweet_id = IntegerField(null=True)

或者通过proxy绕过这个问题:

# Create a proxy object to stand in for our as-yet-undefined Tweet model.

TweetProxy = Proxy()

class User(Model):

username = CharField()

# Tweet has not been defined yet so use the proxy.

favorite_tweet = ForeignKeyField(TweetProxy, null=True)

class Tweet(Model):

message = TextField()

user = ForeignKeyField(User, related_name='tweets')

# Now that Tweet is defined, we can initialize the proxy object.

TweetProxy.initialize(Tweet)

但是建表时还要做出一些处理:

# Foreign key constraint from User -> Tweet will NOT be created because the

# Tweet table does not exist yet. `favorite_tweet` will just be a regular

# integer field:

User.create_table()

# Foreign key constraint from Tweet -> User will be created normally.

Tweet.create_table()

# Now that both tables exist, we can create the foreign key from User -> Tweet:

db.create_foreign_key(User, User.favorite_tweet)

转载于:https://my.oschina.net/hochikong/blog/471675

#Sora#peewee管理数据库——笔记相关推荐

  1. 数据库笔记05:创建与管理数据库

    /****************************  第五单元:创建与管理数据库 *****************************/ /* 任务:创建数据库friend,包含两个数据 ...

  2. Windows内存管理学习笔记(二)—— 物理内存的管理

    Windows内存管理学习笔记(二)-- 物理内存的管理 物理内存 实验一:理解MmNumberOfPhysicalPages MmPfnDatabase _MMPFN 物理页状态 六个链表 实验二: ...

  3. sqlserver 2012实施与管理学习笔记(一):选型和部署之单机部署、故障转移群集与日志传送

    sqlserver 2012实施与管理学习笔记(一):选型和部署之单机部署.故障转移群集与日志传送 数据库的选型和部署 sqlserver的安装和升级 选择高可用性和灾难恢复技术 故障转移群集 日志传 ...

  4. DB2 UDB V8.1 管理 学习笔记

    DB2 UDB V8.1 管理 学习笔记 DB2 学习笔记 - AIview.com Last updated on Wednesday, August 24, 2005 Skip to naviga ...

  5. 数据库笔记整理--基于《数据库系统概论》第五版王珊一书|第八章--数据库编程知识整理和课后习题答案

    该系列的博客都是基于<数据库系统概论>第五版王珊一书 前提: 因为最近要升学的原因,再加上重温数据库部分内容,所以整理一份比较详细且重点的笔记.适合有考研升学需求的人收藏 -------- ...

  6. 【数据库笔记】Spark 小点汇总

    Reference:https://www.cnblogs.com/yanshw/category/1605447.html?page=2 大数据-Spark(29)栏目 0 大数据基本架构 可参见: ...

  7. Oracle数据库•笔记

    Oracle数据库•笔记 第一章 数据库概述 第二章 表管理.表数据库修改 oracle注释:单行注释(–),如: –这是单行注释 多行注释(/**/),如: /* 这是多行注释 这是多行注释 这是多 ...

  8. iPhone开发进阶(9)--- 用SQLite管理数据库

    博主:易飞扬 原文链接 : http://www.yifeiyang.net/iphone-developer-advanced-9-management-database-using-sqlite/ ...

  9. Spring Boot 2.x基础教程:使用Flyway管理数据库版本

    之前已经介绍了很多在Spring Boot中使用MySQL的案例,包含了Spring Boot最原始的 JdbcTemplate(https://blog.didispace.com/spring-b ...

最新文章

  1. 用命令行工具创建 NuGet 程序包
  2. IBM X3650 M2 BR10i卡的阵列配置方法
  3. 第十七课:js数据缓存系统的原理
  4. 对软件工程与计算机科学之间区别的看法
  5. Hibernate的批量查询
  6. 深度学习(06)-- Network in Network(NIN)
  7. android svg指纹录取动画_你知道几种前端动画的实现方式?
  8. 依赖注入有点_一文读懂Java控制反转(IOC)与依赖注入(DI)
  9. Ext.js4 的Store携带参数加载中文,后台出现乱码解决办法
  10. 【基础处理】基于matlab语音信号预处理【含Matlab源码 364期】
  11. 磁盘串口和并口的区别
  12. redis下载安装教程
  13. Greenplum集群扩容总结
  14. 挖矿木马分析之肉鸡竟是我自己
  15. Gradient Normalization在多任务学习中的优化实践
  16. Vue.js实战——内置指令(二)
  17. 视频教程-Oracle12数据库管理/DBA/数据库工程师培训-Oracle
  18. 最短路径算法正确性和操作性闲杂谈-DijkstraFloyd算法
  19. GMT格式的时间处理 Thu Jan 01 00:00:00 +0000 2009成时间戳
  20. 玉帝传美猴王上天,大闹天宫之Java设计模式:命令模式

热门文章

  1. 第五模块:WEB开发基础-第8章 Jquery开发BootStrap
  2. 线索化二叉树的学习记录
  3. 基于WEB的数据挖掘综述
  4. 你还在用Excel? 用这工具,5步完爆Excel表格
  5. MTK DTS 文件配置
  6. 软件开发基于JavaScript实现快速转换文本语言
  7. EMI+ EMC基础知识
  8. 新概念2 课文和单词(8)
  9. 培训机构炒出来的Unity就业没问题吗
  10. 看百度搜索的变易之道:AI引领的新搜索时代丨Xtecher 观察