#Sora#peewee管理数据库——笔记
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管理数据库——笔记相关推荐
- 数据库笔记05:创建与管理数据库
/**************************** 第五单元:创建与管理数据库 *****************************/ /* 任务:创建数据库friend,包含两个数据 ...
- Windows内存管理学习笔记(二)—— 物理内存的管理
Windows内存管理学习笔记(二)-- 物理内存的管理 物理内存 实验一:理解MmNumberOfPhysicalPages MmPfnDatabase _MMPFN 物理页状态 六个链表 实验二: ...
- sqlserver 2012实施与管理学习笔记(一):选型和部署之单机部署、故障转移群集与日志传送
sqlserver 2012实施与管理学习笔记(一):选型和部署之单机部署.故障转移群集与日志传送 数据库的选型和部署 sqlserver的安装和升级 选择高可用性和灾难恢复技术 故障转移群集 日志传 ...
- DB2 UDB V8.1 管理 学习笔记
DB2 UDB V8.1 管理 学习笔记 DB2 学习笔记 - AIview.com Last updated on Wednesday, August 24, 2005 Skip to naviga ...
- 数据库笔记整理--基于《数据库系统概论》第五版王珊一书|第八章--数据库编程知识整理和课后习题答案
该系列的博客都是基于<数据库系统概论>第五版王珊一书 前提: 因为最近要升学的原因,再加上重温数据库部分内容,所以整理一份比较详细且重点的笔记.适合有考研升学需求的人收藏 -------- ...
- 【数据库笔记】Spark 小点汇总
Reference:https://www.cnblogs.com/yanshw/category/1605447.html?page=2 大数据-Spark(29)栏目 0 大数据基本架构 可参见: ...
- Oracle数据库•笔记
Oracle数据库•笔记 第一章 数据库概述 第二章 表管理.表数据库修改 oracle注释:单行注释(–),如: –这是单行注释 多行注释(/**/),如: /* 这是多行注释 这是多行注释 这是多 ...
- iPhone开发进阶(9)--- 用SQLite管理数据库
博主:易飞扬 原文链接 : http://www.yifeiyang.net/iphone-developer-advanced-9-management-database-using-sqlite/ ...
- Spring Boot 2.x基础教程:使用Flyway管理数据库版本
之前已经介绍了很多在Spring Boot中使用MySQL的案例,包含了Spring Boot最原始的 JdbcTemplate(https://blog.didispace.com/spring-b ...
最新文章
- 用命令行工具创建 NuGet 程序包
- IBM X3650 M2 BR10i卡的阵列配置方法
- 第十七课:js数据缓存系统的原理
- 对软件工程与计算机科学之间区别的看法
- Hibernate的批量查询
- 深度学习(06)-- Network in Network(NIN)
- android svg指纹录取动画_你知道几种前端动画的实现方式?
- 依赖注入有点_一文读懂Java控制反转(IOC)与依赖注入(DI)
- Ext.js4 的Store携带参数加载中文,后台出现乱码解决办法
- 【基础处理】基于matlab语音信号预处理【含Matlab源码 364期】
- 磁盘串口和并口的区别
- redis下载安装教程
- Greenplum集群扩容总结
- 挖矿木马分析之肉鸡竟是我自己
- Gradient Normalization在多任务学习中的优化实践
- Vue.js实战——内置指令(二)
- 视频教程-Oracle12数据库管理/DBA/数据库工程师培训-Oracle
- 最短路径算法正确性和操作性闲杂谈-DijkstraFloyd算法
- GMT格式的时间处理 Thu Jan 01 00:00:00 +0000 2009成时间戳
- 玉帝传美猴王上天,大闹天宫之Java设计模式:命令模式