不写一句mysql操作数据库才是Python的风格!!3个ORM模型库示范

用Python可以不用记住任何一句mysql,通过Python使用的ORM模型,简单来说就是一个库是一个对象,这个库里面的字段是这个对象的属性。

ORM解释:对象关系映射(英语:(Object Relational Mapping,简称ORM,或O/RM,或O/R mapping),是一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换 。从效果上说,它其实是创建了一个可在编程语言里使用的--“虚拟对象数据库”。简单来说就是:一个库是一个对象,这个库里面的字段是这个对象的属性。

所有mysql语句封装在了这个对象的方法之中,直接使用相关方法。

介绍三款ORM模型:Peewee、Sqlalchemy、mongoengine以及其中遇到过的莫名问题

其中Peewee、Sqlalchemy是操作mysql和sqlite的,mongoengine是操作mongodb的,这三个库均可在Python3环境下使用

示例简介使用ORM模型实现数据库的增删改查,以及根据ORM模型映射创建数据库

1.Peewee

```

from peewee import *

from playhouse.db_url import connect

from playhouse.pool import PooledMySQLDatabase, PooledDatabase

from playhouse.shortcuts import model_to_dict, dict_to_model

import datetime

"""peewee提供了一个数据库的封装模型,playhouse.db_url为其连接的一种方式通过数据库的指定格式url连接

连接后创建完以后需要模型生成表使用db.connect(),db.create_tables([Person, Pet])"""

blog = PooledMySQLDatabase(

    'peewee_test',

    max_connections=8,

    stale_timeout=300,

    user='admin',

    host='118.24.52.111',

    password='123456!@#,.',

    port=3306)

""""

http://docs.peewee-orm.com/en/latest/peewee/playhouse.html#PooledDatabase.manual_close

"""

# MYSQL_URL = \

#     'mysql://admin:6666666!@111.1111.111.111:3306/peewee_test?charset=utf8'

# blog = connect(MYSQL_URL)   # 连接方式一

# 连接方式二

# blog = MySQLDatabase('test', user='root', host='localhost', port=3306)

classBaseModel(Model):

    """基类"""

    classMeta:

        database = blog

classTest(BaseModel):

    """参数解释    CharField:字符串类型    IntegerField:整型    DateTimeField:时间类型    ForeignKeyField:外键关联    unique:是否唯一    max_lenth:最大长度    verbose_name:表头名    null:是都为空    default:默认值"""

    name = CharField(unique=True, max_length=50, verbose_name='用户名', null=False, default='你哈')

    number = IntegerField(default=0, verbose_name='数字')

    update_date = DateTimeField(verbose_name='更新时间', default=datetime.datetime.now)

    defclose(self):

        blog.close()

classTests(BaseModel):

    title = CharField(verbose_name='标题', max_length=64)

    site = CharField(verbose_name='前缀', max_length=32, unique=True)

    article_type = ForeignKeyField(Test)

defcreate_tables():

    """生成数据表,在数据库中生成模型映射的表"""

    blog.connect()

    blog.create_tables([Tests, Test])

    blog.close()

defdrop_tables():

    """删除数据表"""

    blog.connect()

    blog.drop_tables([Tests, Test])

    blog.close()

definsert(value):

    """插入数据,或者将属性作为参数传入Test(name='name',number=2222)"""

    obj = Test()

    obj.name = value

    obj.number = 99

    obj.save()

defupdata():

    """"更新数据"""

    obj = Test.get(Test.name == '更新')

    obj.name = '更新完毕'

    obj.number = 100

    obj.save()

defselect_all():

    """查询所有数据"""

    ret = Test.select()

    for obj in ret:

        print(obj.name)

defselect_test():

    """查询条件数据"""

    Test.select().where((Test.name.contains('测试'))) .count()    # 包含指定内容返回集合

    Test.select().where((Test.name == '测试') | (Test.number == 9999)).first()    # 条件或

    Test.select().where((Test.name == '测试'), (Test.number == 9999)).first()    # 条件并

    Test.select().join(Tests).where(Tests.title == 'title').execute()   # 关联查询

    obj = Test.get(Test.name == 'yang')

    if obj:

        print(obj.name)

    else:

        print('none have')

defdelete_a(i):

    """删除数据"""

    obj = Test.get(Test.id == i)

    obj.delete_instance()

defsort():

    """对返回结果列排序"""

    set = Test.select().order_by(Test.name)

defto_dict():

    """把模型数据转为字典对象"""

    user = Test.create(username='jack')

    u = model_to_dict(user)

    return u

defto_model():

    """生成model对象"""

    user_data = {'id': 2, 'username': 'charlie'}

    user = dict_to_model(Test, user_data)

defclose():

    db.close()

```

2.Sqlalchemy

```

from sqlalchemy import Column, create_engine

from sqlalchemy.ext.declarative import declarative_base

from sqlalchemy.orm import sessionmaker

from sqlalchemy.types import CHAR, Integer, String, SMALLINT

"""

__tablename__:指定表名Column:行声明,可指定主键Integer:int类型String:字符串Float:浮点Boolean:布尔DateTime:日期和时间Text:文本LongText:长文本

父类BaseModel会调用所有继承他的子类来生成表结构primary_key:True/False 是否为主键unique:是否唯一nullable:是否为空default:默认值"""

MYSQL_SETTING = "mysql://lkj:123456lkj@localhost:3306/blog?charset=utf8"

engine = create_engine(

    MYSQL_SETTING, pool_size=20, max_overflow=0, pool_recycle=3600)

DBSession = sessionmaker(bind=engine)   # 创建DBSession类型:类似数据库连接

BaseModel = declarative_base()

classTest(BaseModel):

    __tablename__ = 'test_table'

    id = Column(Integer, primary_key=True)

    url = Column(String(128))   # 字符串类型

    update_time = Column(DateTime, default=datetime.datetime.now())

    defto_dict(self):  # 将读取的数据和转化成字典

        return {c.name: getattr(self, c.name, None) for c in self.__table__.columns}

definit_db():

    """生成数据表"""

    BaseModel.metadata.create_all(engine)

defdrop_db():

    """删除数据表"""

    BaseModel.metadata.drop_all(engine)

if __name__ == '__main__':

    init_db()

    """添加数据"""

    session = DBSession()

    new_data = Test(url='', update_time='')

    session.add(new_data)  # 添加

    session.commit()  # 提交

    """查询数据"""

    session = DBSession()

    num = session.query(Test).filter(

        Test.url == 'url', Test.id == '22').count()    # 查询多条件

    session.commit()

    session.close()

    """删除数据"""

    session = DBSession()

    test = session.query(Test).filter(Test.url == "user1").first()

    session.delete(test)

    session.commit()

    session.close()

    """更新数据"""

    session = DBSession()

    test = session.query(Test).filter(Test.url == "user1").first()

    test.url = 'www.test.com'

    session.commit()

    session.close()

```

3.mongoengine

```

from mongoengine import connect, Document, EmbeddedDocument, DynamicDocument, \

    StringField, IntField, FloatField, ListField, EmbeddedDocumentField, DictField

import datetime

connect(db='test',

        host="mongodb://admin:6666666@111.111.111.111:27017/?authSource=admin")

if __name__ == '__main__':

    """

简单使用说明-及其使用案例

Document    #定义基本模式继承该类——适用于储存字典结构变化不定的数据    EmbeddedDocument    #申明内嵌文档    EmbeddedDocumentField   #嵌入文档的方法    DynamicDocument # 动态添加字段方法--适用于储存固定格式字典并要求验证的

StringFiled(regex=None,max_length=None,min_lenght=None) #字符串类型

IntField(min_value=None,max_value=None) #整数类型

FloatField(min_value=None,max_value=None) #字符串类型

BooleanField() #布尔类型

DateTimeField() #时间类型

listField() #可以插入列表的

DictField() #字典类型

ReferenceField() #参照类型

SequenceField() #自动产生一个数列、 递增的

通用参数    default #默认值 也可以是一个函数 可调用类型

required #是否必须赋值 true false

primary_key #插入数据是否重复

null #赋值是否可以为空

choices #列表的范围

unique #当前列只能是唯一的    """

    SEX_CHICES = (

        ('male', '男'),

        ('female', '女')

    )

    classGrade(EmbeddedDocument):

        """成绩"""

        name = StringField(required=True)

        score = FloatField(required=True)

    classStudent(DynamicDocument):

        """学生"""

        name = StringField(max_length=32, required=True)

        age = IntField(required=True)

        sex = StringField(choices=SEX_CHICES, required=True)

        grade = FloatField()

        address = StringField()

        grades = ListField(EmbeddedDocumentField(Grade))

        meta = {

            'collection': 'students',

            # 排序功能,按照分数倒序

            'ordering': ['-grade']

        }

    classTestMongoEngine(object):

        defadd_one(self):

            """添加一条数据到数据库"""

            yuwen = Grade(

                name='语文',

                score=90)

            shuxue = Grade(

                name='数学',

                score=100)

            stu_obj = Student(

                name='张三丰',

                age=15,

                grades=[yuwen, shuxue],

                sex='male'

            )

            # 直接添加remark字段是无法添加成功的,需要引入动态添加字段的方法DynamicDocument

            stu_obj.remark = 'remark'

            stu_obj.save()

            return stu_obj

        defget_one(self):

            """ 获取单条数据 """

            return Student.objects.first()

        defget_more(self):

            """ 获取多条数据 """

            # return Student.objects

            return Student.objects.all()

        defget_one_from_oid(self, oid):

            """ 查询指定id的数据 """

            return Student.objects.filter(id=oid).first()

        defupdate(self):

            """ 修改数据 """

            # 修改一条数据

            # res = Student.objects.filter(sex='male').update_one(inc__age=1)

            # return res

            # 修改多条数据

            res = Student.objects.filter(sex='male').update(inc__age=10)

            return res

        defdelete(self):

            """ 删除数据 """

            # 删除一条数据

            # res = Student.objects.filter(sex='male').first().delete()

            # return res

            # 删除多条数据

            res = Student.objects.filter(gender='male').delete()

    test = TestMongoEngine()

    test.add_one()

```

注意:peewee和sqlalchemy如果使用的是单个连接在多进程使用中会锁表,上面案列连接方式都是连接池的方式,可以避免在多进程中锁表。

------------------------------

ID:Python之战

|作|者|公(zhong)号:python之战 

专注Python,专注于网络爬虫、RPA的学习-践行-总结

喜欢研究和分享技术瓶颈,欢迎关注

独学而无友,则孤陋而寡闻!

---------------------------

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,924评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,902评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,716评论 0 239
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,783评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,166评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,510评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,784评论 2 311
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,476评论 0 196
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,196评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,459评论 2 243
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,978评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,321评论 2 252
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,964评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,046评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,803评论 0 193
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,530评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,420评论 2 265

推荐阅读更多精彩内容