欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

python輕量級(jí)orm框架 peewee常用功能速查詳情

 更新時(shí)間:2021年09月13日 17:50:14   作者:金色旭光  
Peewee是一種簡單而小的ORM。它有很少的(但富有表現(xiàn)力的)概念,使它易于學(xué)習(xí)和直觀的使用,感興趣的朋友可以參考下面文章的具體內(nèi)容

一、常見orm數(shù)據(jù)庫框架

Django ORM
peewee
SQLAlchemy

Django ORM

優(yōu)點(diǎn) :

易用,學(xué)習(xí)曲線短

Django緊密集合,用Django時(shí)使用約定俗成的方法去操作數(shù)據(jù)庫

缺點(diǎn) :

QuerySet速度不給力,會(huì)逼我用Mysqldb來操作原生sql語句。

Peewee

優(yōu)點(diǎn) :

Django式的API,使其易用

輕量實(shí)現(xiàn),很容易和任意web框架集成

缺點(diǎn) :

不支持自動(dòng)化 schema 遷移

不能像Django那樣,使線上的mysql表結(jié)構(gòu)生成結(jié)構(gòu)化的模型。

SQLAlchemy

優(yōu)點(diǎn) :

巨牛逼的API,使得代碼有健壯性和適應(yīng)性

靈活的設(shè)計(jì),使得能輕松寫復(fù)雜查詢

缺點(diǎn) :

工作單元概念不常見

重量級(jí) API,導(dǎo)致長學(xué)習(xí)曲線

1、peewee 簡單demo

import datetime
from peewee import *

db = MySQLDatabase(
    "test", host="127.0.0.1", port=3306, user="root", passwd="123456"
)
db.connect()


class BaseModel(Model):
    class Meta:
        database = db

class Person(BaseModel):
    name = CharField()
    age = IntegerField()
    height = IntegerField()
    sex = BooleanField(default='male')

if __name__ == "__main__":
    Person.create_table()

    # 創(chuàng)建
    Person.create(name='tom', age=30, height=177)
    
    # 查詢
    res = Person.select().where(Person.name=='tom')
    print(res)
    print(res[0])
    print(res[0].name)
    print(res[0].age)
    print(res[0].height)
    print(res[0].sex)
>>>>
SELECT `t1`.`id`, `t1`.`name`, `t1`.`age`, `t1`.`High`, `t1`.`sex` FROM `person` AS `t1` WHERE (`t1`.`name` = 'ljk')
1
tom
30
177
True

二、Model 和 Field 關(guān)系

在ORM對(duì)象關(guān)系數(shù)據(jù)庫中 Model是一個(gè)類,映射到數(shù)據(jù)庫表中就是一個(gè)表。Filed是字段,映射到表中就是字段。model實(shí)例就是數(shù)據(jù)庫中的一條記錄。在peewee中Model和Field的關(guān)系如下:

Thing 對(duì)應(yīng)關(guān)系
Model 類
Field 實(shí)例 表中字段
Model 實(shí)例 表中數(shù)據(jù)

數(shù)據(jù)庫連接和model類定義的 典型使用

import datetime
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, backref='tweets')
    message = TextField()
    created_date = DateTimeField(default=datetime.datetime.now)
    is_published = BooleanField(default=True)


創(chuàng)建一個(gè)數(shù)據(jù)庫實(shí)例

db = SqliteDatabase('my_app.db')


創(chuàng)建一個(gè)基礎(chǔ)model類

class BaseModel(Model):
    class Meta:
        database = db


定義一個(gè)用于建立數(shù)據(jù)庫連接的基模類是一種推薦的做法,因?yàn)閷⒉槐貫楹罄m(xù)表指定數(shù)據(jù)庫。

定義一個(gè)普通 model 類

class User(BaseModel):
    username = CharField(unique=True)


模型定義使用的是其他流行的orm(如SQLAlchemyDjango)中看到的聲明式風(fēng)格。因?yàn)閁ser繼承了BaseModel 類,所以User類可以繼承數(shù)據(jù)庫連接。

User已經(jīng)明確定義了一個(gè)具有唯一約束的用戶名列。因?yàn)槲覀儧]有指定主鍵,peewee 會(huì)自動(dòng)添加一個(gè)自增整數(shù)主鍵字段,名為 id。沒有指定主鍵的表peewee會(huì)自動(dòng)創(chuàng)建一個(gè)名字為id的自增主鍵。

三、Model 模型

為了不污染model的命名空間,model的配置放在特殊的元屬性類中。這是從Django的框架中借鑒過來的。

contacts_db = SqliteDatabase('contacts.db')

class Person(Model):
    name = CharField()

    class Meta:
        database = contacts_db

在簡單model示例中,你會(huì)注意到,我們創(chuàng)建了一個(gè)定義數(shù)據(jù)庫的BaseModel,然后擴(kuò)展了它。這是定義數(shù)據(jù)庫和創(chuàng)建模型的首選方法。

你可以通過 ModelClass._meta 來使用:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: type object 'Person' has no attribute 'Meta'

>>> Person._meta
<peewee.modeloptions object="" at="" 0x7f51a2f03790="">

ModelOptions 實(shí)現(xiàn)了幾個(gè)查看model metadata的方法:

{'id': <peewee.autofield object="" at="" 0x7f51a2e92750="">,
 'name': <peewee.charfield object="" at="" 0x7f51a2f0a510="">}

>>> Person._meta.primary_key
<peewee.autofield object="" at="" 0x7f51a2e92750="">

>>> Person._meta.database
<peewee.sqlitedatabase object="" at="" 0x7f519bff6dd0="">

Model 在ORM數(shù)據(jù)中就是一張表,那么表的屬性可以有如下選項(xiàng)。它們是被定義在Meta中元數(shù)據(jù)。

Option Meaning 是否可繼承?
database 指定表創(chuàng)建依附的數(shù)據(jù)庫 yes
table_name 表名 no
table_function 生成表名的函數(shù) yes
indexes 多行索引 yes
primary_key 主鍵 yes
constraints 表約束的列表 yes
schema 模型的數(shù)據(jù)庫架構(gòu) yes
only_save_dirty 調(diào)用model.save()時(shí),僅保存臟字段,指定字段? yes
options 創(chuàng)建表擴(kuò)展的選項(xiàng)字典 yes
table_settings 在右括號(hào)后設(shè)置字符串的列表 yes
temporary 指示臨時(shí)表 yes
legacy_table_names 使用舊表名生成(默認(rèn)情況下啟用) yes
depends_on 指示此表依賴于另一個(gè)表進(jìn)行創(chuàng)建 no
without_rowid 指示表不應(yīng)具有rowid(僅限SQLite) no
strict_tables 指示嚴(yán)格的數(shù)據(jù)類型(僅限SQLite,3.37+) yes

四、Filed 字段

Field類是用來將Model屬性映射到數(shù)據(jù)庫列。每個(gè)字段類型都有一個(gè)相應(yīng)的SQL存儲(chǔ)類,將python數(shù)據(jù)類型轉(zhuǎn)化為基本的存儲(chǔ)類型。

當(dāng)創(chuàng)建Model類時(shí),fields被定義成類的屬性。它看起來和django的數(shù)據(jù)庫框架很類似。

class User(Model):
    username = CharField()
    join_date = DateTimeField()
    about_me = TextField()


在上面的例子中,因?yàn)闆]有field有主鍵屬性primary_key=True,所以會(huì)創(chuàng)建一個(gè)名字是id的自增主鍵。

peewee中可用的字段包括:

字段類型 Sqlite Postgresql MySQL
AutoField integer serial integer
BigAutoField integer bigserial bigint
IntegerField integer integer integer
BigIntegerField integer bigint bigint
SmallIntegerField integer smallint smallint
IdentityField not supported int identity not supported
FloatField real real real
DoubleField real double precision double precision
DecimalField decimal numeric numeric
CharField varchar varchar varchar
FixedCharField char char char
TextField text text text
BlobField blob bytea blob
BitField integer bigint bigint
BigBitField blob bytea blob
UUIDField text uuid varchar(40)
BinaryUUIDField blob bytea varbinary(16)
DateTimeField datetime timestamp datetime
DateField date date date
TimeField time time time
TimestampField integer integer integer
IPField integer bigint bigint
BooleanField integer boolean bool
BareField untyped not supported not supported
ForeignKeyField integer integer integer

1、字段初始化參數(shù)

所有字段類型接受的參數(shù)及其默認(rèn)值

  • null = False 允許空值
  • index = False 創(chuàng)建索引
  • unique = False 創(chuàng)建唯一索引
  • column_name = None 顯式指定數(shù)據(jù)庫中的列名
  • default = None 默認(rèn)值,可以使任意值或可調(diào)用對(duì)象
  • primary_key = False 指明主鍵
  • constraints = None 約束條件
  • sequence = None 序列名字(如果數(shù)據(jù)庫支持)
  • collation = None 排序字段
  • unindexed = False 虛表上的字段不應(yīng)該被索引
  • choices = None 兩種可選項(xiàng):value display
  • help_text = None 幫助說明字段。表示此字段的任何有用文本的字符串
  • verbose_name = None 表示此字段的用戶友好名稱的字符串
  • index_type = None 索引類型

2、字段特有參數(shù)

在一些字段中有些自己特有的參數(shù),如下:

字段類型 特有參數(shù)
CharField max_length
FixedCharField max_length
DateTimeField formats
DateField formats
TimeField formats
TimestampField resolution, utc
DecimalField max_digits, decimal_places, auto_round, rounding
ForeignKeyField model, field, backref, on_delete, on_update, deferrable lazy_load
BareField adapt

3、字段默認(rèn)參數(shù)

peewee可以為每一個(gè)字段提供默認(rèn)值,比如給intergerField 默認(rèn)值0而不是NULL。你可以申明字段時(shí)指定默認(rèn)值:

class Message(Model):
    context = TextField()
    read_count = IntegerField(default=0)


在某些情況下,默認(rèn)值是動(dòng)態(tài)的會(huì)更有意義。一個(gè)可能的場景就是當(dāng)前時(shí)間。Peewee 允許您在這些情況下指定一個(gè)函數(shù),該函數(shù)的返回值將在創(chuàng)建對(duì)象時(shí)使用。注意,使用時(shí)只提供了函數(shù),并不需要實(shí)際調(diào)用它。

class Message(Model):
    context = TextField()
    timestamp = DateTimeField(default=datetime.datetime.now)


如果你正在使用一個(gè)接受可變類型(list, dict等)的字段,并想提供一個(gè)默認(rèn)值。將默認(rèn)值包裝在一個(gè)簡單的函數(shù)中是個(gè)好主意,這樣,多個(gè)模型實(shí)例就不會(huì)共享對(duì)同一底層對(duì)象的引用。

def house_defaults():
    return {'beds': 0, 'baths': 0}

class House(Model):
    number = TextField()
    street = TextField()
    attributes = JSONField(default=house_defaults)

4、索引

peewee可以通過單列索引和多列索引??蛇x地包括UNIQUE約束。Peewee還支持對(duì)模型和字段的用戶定義約束。

單列索引

單列索引使用字段初始化參數(shù)定義。下面的示例在用戶名字段上添加一個(gè)惟一索引,在電子郵件字段上添加一個(gè)普通索引

class User(Model):
    username = CharField(unique=True)
    email = CharField(index=True)


在列上添加用戶定義的約束。你可以使用constraints參數(shù)。例如,您可能希望指定一個(gè)默認(rèn)值,或者添加一個(gè)CHECK約束

class Product(Model):
    name = CharField(unique=True)
    price = DecimalField(constraints=[Check('price < 10000')])
    created = DateTimeField(
        constraints=[SQL("DEFAULT (datetime('now'))")])


多列索引

可以使用嵌套元組將多列索引定義為元屬性。每個(gè)表的索引是一個(gè)2元組,第一部分是索引字段名稱的元組,可以有多個(gè)字段,第二部分是一個(gè)布爾值,指示索引是否應(yīng)該唯一。

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),
        )

記住,如果索引元組只包含一項(xiàng),則添加末尾逗號(hào)

五、基本操作 增刪改查

peewee中關(guān)于增刪改查的基本操作方法如下:

增 :

  • create():最常用創(chuàng)建,返回創(chuàng)建實(shí)例
  • save():第一次執(zhí)行的save是插入,第二次是修改
  • insert: 插入數(shù)據(jù),不創(chuàng)建數(shù)據(jù)庫實(shí)例。返回id
  • insert_many: 批量插入
  • bulk_create:批量插入,類似于insert_many。可指定單次插入的數(shù)量
  • batch_commit: 自動(dòng)添加了一個(gè)事務(wù),然后一條條的插入
  • insert_from: 從另一個(gè)表中查詢的數(shù)據(jù)作為插入的數(shù)據(jù)

刪除 :

  • delete().where().execute()
  • delete_instance() 直接執(zhí)行刪除了,不用調(diào)用execute() 方法

修改 :

  • save(): 第一次執(zhí)行的save是插入,第二次是修改
  • update() 用于多字段更新

查詢 :

  • Model.get(): 檢索與給定查詢匹配的單個(gè)實(shí)例。報(bào) Model.DoesNotExist 異常。如果有多條記錄滿足條件,則返回第一條
  • get_or_none() :與get使用方法相同。區(qū)別是找不到結(jié)果時(shí)不會(huì)報(bào)錯(cuò)
  • get_by_id() :通過主鍵查找,是一種快捷方式
  • Model['id_num']: 和上面的get_by_id一樣是通過主鍵查找。
  • get_or_create(): 首先查詢,如果查不到將創(chuàng)建一個(gè)新的記錄
  • select() 查詢多條數(shù)據(jù)

1、創(chuàng)建

單條插入

你可以用 Model.create() 創(chuàng)建一個(gè)新的實(shí)例。這個(gè)方法接收關(guān)鍵字參數(shù),參數(shù)要和表定義的字段一致。返回值是新的實(shí)例

>>> User.create(username='Charlie')
<__main__.User object at 0x2529350>

批量插入

有幾種方法可以快速加載大量數(shù)據(jù),缺乏經(jīng)驗(yàn)的做法是在循環(huán)中調(diào)用Model.create來創(chuàng)建

data_source = [
    {'field1': 'val1-1', 'field2': 'val1-2'},
    {'field1': 'val2-1', 'field2': 'val2-2'},
    # ...
]

for data_dict in data_source:
    MyModel.create(**data_dict)

上面的方法比較慢的原因有幾個(gè):

  1. 如果沒有在事務(wù)中裝飾循環(huán),那么每個(gè)對(duì)create()的調(diào)用都發(fā)生在它自己的事務(wù)中。這將會(huì)非常緩慢
  2. 必須生成每個(gè)InsertQuery并將其解析為SQL
  3. 需要原生SQL語句傳入到數(shù)據(jù)庫中解析
  4. 檢索最后一個(gè)insert id,這在某些情況下會(huì)導(dǎo)致執(zhí)行額外的查詢

可以通過一個(gè)簡單的裝飾: atomic 來大幅度提高速度

# This is much faster.
with db.atomic():
    for data_dict in data_source:
        MyModel.create(**data_dict)


上面的代碼仍然沒有解決2、3、4這三點(diǎn)。我們可以通過 insert_many 帶來一個(gè)大的速度提升。這個(gè)方法接收多列元組或字典,然后在一次SQL語句中插入多行數(shù)據(jù)。

data_source = [
    {'field1': 'val1-1', 'field2': 'val1-2'},
    {'field1': 'val2-1', 'field2': 'val2-2'},
    # ...
]

# Fastest way to INSERT multiple rows.
MyModel.insert_many(data_source).execute()

insert_many() 方法還接收多行元組,同時(shí)需要提供一個(gè)對(duì)應(yīng)的字段。

# We can INSERT tuples as well...
data = [('val1-1', 'val1-2'),
        ('val2-1', 'val2-2'),
        ('val3-1', 'val3-2')]

# But we need to indicate which fields the values correspond to.
MyModel.insert_many(data, fields=[MyModel.field1, MyModel.field2]).execute()

在裝飾中批量插入是一個(gè)好的方法。

# You can, of course, wrap this in a transaction as well:
with db.atomic():
    MyModel.insert_many(data, fields=fields).execute()


插入大量數(shù)據(jù)

在大量數(shù)據(jù)的插入場景下,根據(jù)數(shù)據(jù)源中的行數(shù),您可能需要將其分解為多個(gè)塊。SQLite通常有99932766的限制

您可以編寫一個(gè)循環(huán)來將數(shù)據(jù)批處理成塊(在這種情況下,強(qiáng)烈建議您使用事務(wù))

# Insert rows 100 at a time.
with db.atomic():
    for idx in range(0, len(data_source), 100):
        MyModel.insert_many(data_source[idx:idx+100]).execute()


peewwee提供了一個(gè)chunked函數(shù)幫助你高效的將普通可迭代對(duì)象拆分成為可批處理對(duì)象。

from peewee import chunked

# Insert rows 100 at a time.
with db.atomic():
    for batch in chunked(data_source, 100):
        MyModel.insert_many(batch).execute()


Model.bulk_create() 的行為有點(diǎn)像insert_many(),但是可以用來插入沒有保存的數(shù)據(jù)庫實(shí)例,并且可以指定每次插入的數(shù)量。如一共插入345,如果指定了一次插入100條記錄,那么就是4次插入,3 * 100 + 1 * 45

什么叫沒有保存的數(shù)據(jù)庫實(shí)例呢?就是類似于 User(username='kk') ,創(chuàng)建的數(shù)據(jù)庫實(shí)例。

# Read list of usernames from a file, for example.
with open('user_list.txt') as fh:
    # Create a list of unsaved User instances.
    users = [User(username=line.strip()) for line in fh.readlines()]

# Wrap the operation in a transaction and batch INSERT the users
# 100 at a time.
with db.atomic():
    User.bulk_create(users, batch_size=100)

bulk_update() bulk_create 類似,可以用來插入沒有保存的數(shù)據(jù)庫實(shí)例,自動(dòng)添加了一個(gè)事務(wù),然后一條條的插入

# List of row data to insert.
row_data = [{'username': 'u1'}, {'username': 'u2'}, ...]

# Assume there are 789 items in row_data. The following code will result in
# 8 total transactions (7x100 rows + 1x89 rows).
for row in db.batch_commit(row_data, 100):
    User.create(**row)

從另一個(gè)表批量裝載

Model.insert_from() 如果要批量插入的數(shù)據(jù)存儲(chǔ)在另一個(gè)表中,還可以創(chuàng)建源為SELECT查詢的INSERT查詢。

res = (TweetArchive
       .insert_from(
           Tweet.select(Tweet.user, Tweet.message),
           fields=[TweetArchive.user, TweetArchive.message])
       .execute())

2、刪除

要?jiǎng)h除單個(gè)模型實(shí)例,可以使用model.delete_instance()快捷方式。delete_instance()將刪除給定的模型實(shí)例,并且可以選擇遞歸地刪除任何依賴對(duì)象(通過指定recursive=True)。

刪除一個(gè)記錄:Model.delete_instance()

刪除任意記錄:Model.delete()

3、更新

save() :單個(gè)更新

一旦模型實(shí)例有了主鍵,隨后對(duì)save()的任何調(diào)用都將導(dǎo)致一個(gè)UPDATE而不是另一個(gè)INSERT。模型的主鍵不會(huì)改變

>>> user.save()  # save() returns the number of rows modified.
1
>>> user.id
1
>>> user.save()
>>> user.id
1
>>> huey.save()
1
>>> huey.id
2


update :批量更新

接受關(guān)鍵字參數(shù),其中鍵對(duì)應(yīng)于模型的字段名稱

>>> today = datetime.today()
>>> query = Tweet.update(is_published=True).where(Tweet.creation_date < today)
>>> query.execute()  # Returns the number of rows that were updated.
4

4、查詢

單條記錄查詢

你可以通過Model.get()方法查詢到給條件的數(shù)據(jù)。如果是通過主鍵查找,也可以用一個(gè)快捷方法 Model.get_by_id()。

此方法是使用給定查詢調(diào)用Model.select()的快捷方式,但將結(jié)果集限制為一行。需要注意的是使用get()方法,如果沒有找到匹配的數(shù)據(jù)會(huì)拋出錯(cuò)誤:DoesNotExist

get

>>> User.get(User.id == 1)
<__main__.User object at 0x25294d0>

>>> User.get_by_id(1)  # Same as above.
<__main__.User object at 0x252df10>

>>> User[1]  # Also same as above.
<__main__.User object at 0x252dd10>

>>> User.get(User.id == 1).username
u'Charlie'

>>> User.get(User.username == 'Charlie')
<__main__.User object at 0x2529410>

>>> User.get(User.username == 'nobody')
UserDoesNotExist: instance matching query does not exist:
SQL: SELECT t1."id", t1."username" FROM "user" AS t1 WHERE t1."username" = ?
PARAMS: ['nobody']

單條記錄查詢方法:

  • Model.get()
  • Model.get_by_id()
  • Model.get_or_none() - if no matching row is found, return None.
  • Model.select()
  • SelectBase.get()
  • SelectBase.first() - return first record of result-set or None.

查詢或創(chuàng)建:

Model.get_or_create() 它首先嘗試檢索匹配的行。如果失敗,將創(chuàng)建一個(gè)新行。

通常,可以依賴唯一約束或主鍵來防止創(chuàng)建重復(fù)對(duì)象。例如,假設(shè)我們希望使用示例用戶模型實(shí)現(xiàn)注冊新用戶帳戶。用戶模型對(duì)用戶名字段有唯一的約束,因此我們將依賴數(shù)據(jù)庫的完整性保證,以確保不會(huì)出現(xiàn)重復(fù)的用戶名:

try:
    with db.atomic():
        return User.create(username=username)
except peewee.IntegrityError:
    # `username` is a unique column, so this username already exists,
    # making it safe to call .get().
    return User.get(User.username == username)


上面的例子首先嘗試創(chuàng)建,然后回退到查詢,依靠數(shù)據(jù)庫來強(qiáng)制執(zhí)行唯一約束。

如果您希望首先嘗試檢索記錄,可以使用get_or_create()。該函數(shù)返回一個(gè)2元組,其中包含實(shí)例和一個(gè)布爾值,該值指示對(duì)象是否被創(chuàng)建。

user, created = User.get_or_create(username=username)
person, created = Person.get_or_create(
    first_name=first_name,
    last_name=last_name,
    defaults={'dob': dob, 'favorite_color': 'green'})

查詢多行記錄:

可以通過Model.select()獲取多行數(shù)據(jù)。peewee允許你迭代這些數(shù)據(jù),同時(shí)也可以索引和切片。

>>> query = User.select()
>>> [user.username for user in query]
['Charlie', 'Huey', 'Peewee']

>>> query[1]
<__main__.User at 0x7f83e80f5550>

>>> query[1].username
'Huey'

>>> query[:2]
[<__main__.User at 0x7f83e80f53a8>, <__main__.User at 0x7f83e80f5550>]

select()是很智能的,在查詢一次的前提下可以多次迭代,切片,下標(biāo)取值等。

在緩存結(jié)果時(shí),同一查詢的后續(xù)迭代不會(huì)命中數(shù)據(jù)庫。要禁用此行為(以減少內(nèi)存使用),請?jiān)诘鷷r(shí)調(diào)用Select.iterator()。

除了返回模型實(shí)例外,Select查詢還可以返回字典、元組和命名元組。根據(jù)您的用例,您可能會(huì)發(fā)現(xiàn)將行作為字典使用更容易

>>> query = User.select().dicts()
>>> for row in query:
...     print(row)

{'id': 1, 'username': 'Charlie'}
{'id': 2, 'username': 'Huey'}
{'id': 3, 'username': 'Peewee'}

iterator() :不緩存查詢結(jié)果

默認(rèn)情況下,peewee將緩存迭代Select查詢時(shí)返回的行。這是一種優(yōu)化,允許多次迭代以及索引和切片,而不會(huì)導(dǎo)致額外的查詢。但是,當(dāng)您計(jì)劃在大量行上進(jìn)行迭代時(shí),這種緩存可能會(huì)有問題。

為了減少內(nèi)存的消耗,使用iterator()方法。這個(gè)方法允許返回結(jié)果不緩存數(shù)據(jù)。使用更少的內(nèi)存。

stats = Stat.select()

# Our imaginary serializer class
serializer = CSVSerializer()

# Loop over all the stats and serialize.
for stat in stats.iterator():
    serializer.serialize_object(stat)

對(duì)于簡單的查詢,您可以通過將行作為字典返回來進(jìn)一步提高速度。namedtuples或元組。以下方法可用于任何Select查詢,以更改結(jié)果行類型。

dicts()

namedtuples()

tuples()

objects : 將多個(gè)查詢表放在一個(gè)實(shí)例中

當(dāng)對(duì)包含多個(gè)表中的列的大量行進(jìn)行迭代時(shí),peewee將為返回的每一行構(gòu)建查詢模型。對(duì)于復(fù)雜查詢,此操作可能很慢。例如,如果我們選擇一個(gè)tweet列表以及tweet作者的用戶名和頭像,Peewee必須為每一行創(chuàng)建兩個(gè)對(duì)象(tweet和用戶)。除了上述行類型之外,還有第四個(gè)方法objects(),它將作為模型實(shí)例返回行,但不會(huì)分解模型查詢。

query = (Tweet
         .select(Tweet, User)  # Select tweet and user data.
         .join(User))

# Note that the user columns are stored in a separate User instance
# accessible at tweet.user:
for tweet in query:
    print(tweet.user.username, tweet.content)

# Using ".objects()" will not create the tweet.user object and assigns all
# user attributes to the tweet instance:
for tweet in query.objects():
    print(tweet.username, tweet.content)

為了獲得最佳性能,您可以執(zhí)行查詢,然后使用底層數(shù)據(jù)庫游標(biāo)對(duì)結(jié)果進(jìn)行迭代。

Database.execute()。接受查詢對(duì)象,執(zhí)行查詢,并返回DB-API 2.0游標(biāo)對(duì)象。光標(biāo)將返回原始行元組:

query = Tweet.select(Tweet.content, User.username).join(User)
cursor = database.execute(query)
for (content, username) in cursor:
    print(username, '->', content)

5、事務(wù)

數(shù)據(jù)庫事務(wù) Transaction)是一種機(jī)制,包含了一組數(shù)據(jù)庫操作命令

事務(wù)把所有的命令作為一個(gè)整體一起向系統(tǒng)提交或撤銷操作請求,即這一組數(shù)據(jù)庫命令要么都執(zhí)行,要么都不執(zhí)行,因此事務(wù)是一個(gè)不可分割的工作邏輯單元。

事務(wù)具有 4 個(gè)特性,即原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)和持久性(Durability),這 4 個(gè)特性通常簡稱為 ACID。

peewee事務(wù)

Peewee實(shí)現(xiàn)事務(wù)的方法是 Database.atomic() 方法,非常簡單

當(dāng)事務(wù)執(zhí)行成功之后,它會(huì)自動(dòng)commit(),不需要我們手動(dòng)調(diào)。當(dāng)事務(wù)的代碼塊中拋出異常時(shí),它會(huì)自動(dòng)調(diào)用rollback(),將數(shù)據(jù)庫狀態(tài)恢復(fù)到操作之前,保證要么命令全部執(zhí)行,要么全部不執(zhí)行。

Peewee中實(shí)現(xiàn)事務(wù)有兩種使用方式,一種是將atomic當(dāng)做Context manager使用,另外一種將atomic當(dāng)修飾器使用。

Context manager

with db.atomic():
    for data_dict in data_source:
        MyModel.create(**data_dict)

裝飾器

@db.atomic()
def insert_data()
    for data_dict in data_source:
        MyModel.create(**data_dict)

事務(wù)其他特性:

  • 除了自動(dòng)commit()和rollback()之外,也可以手動(dòng)調(diào)用commit()和rollback()方法
  • 事務(wù)支持嵌套使用
  • 在一個(gè)事務(wù)中對(duì)數(shù)據(jù)庫操作能夠有效減少事務(wù)的耗時(shí),增加操作效率

6、過濾

您可以使用普通的python操作符過濾特定的記錄。

>>> user = User.get(User.username == 'Charlie')
>>> for tweet in Tweet.select().where(Tweet.user == user, Tweet.is_published == True):
...     print(tweet.user.username, '->', tweet.message)
...
Charlie -> hello world
Charlie -> this is fun

>>> for tweet in Tweet.select().where(Tweet.created_date < datetime.datetime(2011, 1, 1)):
...     print(tweet.message, tweet.created_date)
...
Really old tweet 2010-01-01 00:00:00
...     
print(tweet.message)
hello world
this is fun
look at this picture of my food

7、記錄分類

給返回的數(shù)據(jù)排序,可以使用order_by

普通使用:

>>> for t in Tweet.select().order_by(Tweet.created_date):
...     print(t.pub_date)

倒序排列:

可以使用desc或者 - 號(hào)

Tweet.select().order_by(Tweet.created_date.desc())

Tweet.select().order_by(-Tweet.created_date)  # Note the "-" prefix.

正序排列:

User.select().order_by(+User.username)

高級(jí)使用:

對(duì)計(jì)算值進(jìn)行排序時(shí),可以包括必要的SQL表達(dá)式,也可以引用指定給該值的別名。

query = (User
         .select(User.username, fn.COUNT(Tweet.id).alias('num_tweets'))
         .join(Tweet, JOIN.LEFT_OUTER)
         .group_by(User.username))


您可以使用select子句中使用的相同計(jì)數(shù)表達(dá)式進(jìn)行訂購。在下面的示例中,我們按tweet ID的COUNT()降序排序:

query = (User
         .select(User.username, fn.COUNT(Tweet.id).alias('num_tweets'))
         .join(Tweet, JOIN.LEFT_OUTER)
         .group_by(User.username)
         .order_by(fn.COUNT(Tweet.id).desc()))


或者,可以在select子句中引用指定給計(jì)算值的別名。這種方法的優(yōu)點(diǎn)是易于閱讀。請注意,我們不是直接引用命名別名,而是使用SQL幫助程序?qū)ζ溥M(jìn)行包裝:

query = (User
         .select(User.username, fn.COUNT(Tweet.id).alias('num_tweets'))
         .join(Tweet, JOIN.LEFT_OUTER)
         .group_by(User.username)
         .order_by(SQL('num_tweets').desc()))


同樣,也可以使用如上

ntweets = fn.COUNT(Tweet.id)
query = (User
         .select(User.username, ntweets.alias('num_tweets'))
         .join(Tweet, JOIN.LEFT_OUTER)
         .group_by(User.username)
         .order_by(ntweets.desc())

8、計(jì)數(shù)

可以使用count來計(jì)算返回?cái)?shù)量

>>> Tweet.select().count()
100
>>> Tweet.select().where(Tweet.id > 50).count()
50

9、分頁

paginate() 方法可以很簡單的獲取一個(gè)分頁的數(shù)據(jù)。paginate有兩個(gè)參數(shù):page_number 和 items_per_page。第一個(gè)參數(shù)是取回?cái)?shù)據(jù)的頁數(shù);第二個(gè)參數(shù)是每一頁多少元素。這兩個(gè)參數(shù)加起來才能完成分頁

>>> for tweet in Tweet.select().order_by(Tweet.id).paginate(2, 10):
...     print(tweet.message)
...
tweet 10
tweet 11
tweet 12
tweet 13
tweet 14
tweet 15
tweet 16
tweet 17
tweet 18
tweet 19


分頁的功能也可以用 limit() 和 offset() 來實(shí)現(xiàn)

Tweet.select().order_by(Tweet.id).offset(10).limit(10)


offset(10) 跳過10個(gè)記錄

limit(10) 取10個(gè)記錄

六、聚合查詢

聚合查詢:對(duì)查詢出來的結(jié)果進(jìn)一步處理,包括統(tǒng)計(jì),分組,求最大值,求平均值等。

聚合常用的函數(shù):

  1. COUNT:計(jì)算表中的記錄數(shù)(行數(shù))
  2. SUM:計(jì)算表中數(shù)值列中數(shù)據(jù)的合計(jì)值
  3. AVG:計(jì)算表中數(shù)值列中數(shù)據(jù)的平均值
  4. MAX:求出表中任意列中數(shù)據(jù)的最大值
  5. MIN:求出表中任意列中數(shù)據(jù)的最小值

用于匯總的函數(shù)稱為聚合函數(shù)或者聚集函數(shù)。所謂聚合,就是將多行匯總為一行。實(shí)際上,所有的聚合函數(shù)都是這樣,輸入多行輸出一行。

聚合函數(shù)的使用:

mysql> select * from person;
+----+------+-----+------+-----+
| id | name | age | High | sex |
+----+------+-----+------+-----+
|  1 | ljk  |  30 |  177 |   1 |
|  2 | aghj |  23 |  168 |   1 |
+----+------+-----+------+-----+
2 rows in set (0.00 sec)
************************************
*              聚合函數(shù)              *
************************************
mysql> select count(*) from person;
+----------+
| count(*) |
+----------+
|        2 |
+----------+
1 row in set (0.00 sec)
----------------------------------------
mysql> select sum(age) from person;
+----------+
| sum(age) |
+----------+
|       53 |
+----------+
1 row in set (0.00 sec)
----------------------------------------
mysql> select avg(high) from person;
+-----------+
| avg(high) |
+-----------+
|  172.5000 |
+-----------+
1 row in set (0.00 sec)
----------------------------------------
mysql> select max(high) from person;
+-----------+
| max(high) |
+-----------+
|       177 |
+-----------+
1 row in set (0.00 sec)
mysql> select * from person;
+----+------+-----+------+-----+
| id | name | age | High | sex |
+----+------+-----+------+-----+
|  1 | ljk  |  30 |  177 |   1 |
|  2 | aghj |  23 |  168 |   1 |
|  3 | 0    |  22 |  165 |   0 |
+----+------+-----+------+-----+
3 rows in set (0.00 sec)

mysql> select avg(High) from person group by sex;
+-----------+
| avg(High) |
+-----------+
|  172.5000 |
|  165.0000 |
+-----------+
2 rows in set (0.00 sec)

# 使用having對(duì)分組的數(shù)據(jù)篩選
mysql> select avg(High) as high from person group by sex having high > 170;
+----------+
| high     |
+----------+
| 172.5000 |
+----------+
1 row in set (0.00 sec)

where :分組之前篩選數(shù)據(jù)

where 子句的作用是在對(duì)查詢結(jié)果進(jìn)行分組前,將不符合where條件的行去掉,即在分組之前過濾數(shù)據(jù),where條件中不能包含聚組函數(shù),使用where條件過濾出特定的行。

having : 對(duì)分組之后篩選分組的數(shù)據(jù)

having 子句的作用是篩選滿足條件的組,即在分組之后過濾數(shù)據(jù),條件中經(jīng)常包含聚組函數(shù),使用having 條件過濾出特定的組,也可以使用多個(gè)分組標(biāo)準(zhǔn)進(jìn)行分組。

總結(jié)一下過濾的順序

on->join->where->group by->having

分組

查詢用戶以及每個(gè)人擁有的tweet賬號(hào)數(shù)量。這里使用了group_by,將結(jié)果根據(jù)User表分類。

query = (User
         .select(User, fn.Count(Tweet.id).alias('count'))
         .join(Tweet, JOIN.LEFT_OUTER)
         .group_by(User))


假設(shè)有如下數(shù)據(jù)庫,一個(gè)多對(duì)多的關(guān)系。

class Photo(Model):
    image = CharField()

class Tag(Model):
    name = CharField()

class PhotoTag(Model):
    photo = ForeignKeyField(Photo)
    tag = ForeignKeyField(Tag)

查詢Tag記錄,按照Tag分組,篩選出每組Tag里Photo數(shù)量超過5個(gè)的記錄。

query = (Tag
         .select()
         .join(PhotoTag)
         .join(Photo)
         .group_by(Tag)
         .having(fn.Count(Photo.id) > 5))

HAVING 子句可以讓我們篩選分組后的各組數(shù)據(jù)。

HAVING,它與 GROUP BY 配合使用,為聚合操作指定條件。

WHERE 子句只能指定行的條件,而不能指定組的條件。所以當(dāng)數(shù)據(jù)分組之后就需要 HAVING 對(duì)分組的數(shù)據(jù)篩選。

具體區(qū)別:

where 用在group_by前,having用在group_by之后。
聚合函數(shù)(avg、sum、max、min、count),不能作為條件放在where之后,但可以放在having之后

七、Scalar

對(duì)查詢出來的數(shù)據(jù)做處理

可以通過調(diào)用Query.scalar()來檢索標(biāo)量值。例如

>>> Employee.select(
...     fn.Min(Employee.salary), fn.Max(Employee.salary)
... ).scalar(as_tuple=True)
(30000, 50000)


您可以通過傳遞來檢索多個(gè)標(biāo)量值

>>> Employee.select(
...     fn.Min(Employee.salary), fn.Max(Employee.salary)
... ).scalar(as_tuple=True)
(30000, 50000)

八、窗口

窗口函數(shù)是指對(duì)作為SELECT查詢一部分處理的數(shù)據(jù)滑動(dòng)窗口進(jìn)行操作的聚合函數(shù)。窗口功能可以執(zhí)行以下操作:

對(duì)結(jié)果集的子集執(zhí)行聚合。

計(jì)算一個(gè)運(yùn)行總數(shù)。

排名結(jié)果。

將行值與前面(或后面!)行中的值進(jìn)行比較。

peewee支持SQL窗口函數(shù),可以通過調(diào)用Function.over()并傳入分區(qū)或排序參數(shù)來創(chuàng)建這些函數(shù)。

九、復(fù)雜篩選

peewee支持以下類型的比較

1、查詢中支持的篩選運(yùn)算符

Comparison Meaning
== x equals y
< x is less than y
<= x is less than or equal to y
> x is greater than y
>= x is greater than or equal to y
!= x is not equal to y
<< x IN y, where y is a list or query
>> x IS y, where y is None/NULL
% x LIKE y where y may contain wildcards
** x ILIKE y where y may contain wildcards
^ x XOR y
~ Unary negation (e.g., NOT x)

2、篩選方法

因?yàn)橛猛炅艘貙懙牟僮鞣?,所以有一些額外的查詢操作可以作為方法使用

Method Meaning
.in_(value) 查詢在范圍內(nèi)
.not_in(value) 查詢不在范圍內(nèi)
.is_null(is_null) 為空或不為空。接受布爾參數(shù)
.contains(substr) 通配符搜索子字符串
.startswith(prefix) 查詢以prefix開頭的數(shù)據(jù)
.endswith(suffix) 查詢以prefix結(jié)尾的數(shù)據(jù)
.between(low, high) 查詢在low和high中間的值
.regexp(exp) 正則表達(dá)式匹配匹配的數(shù)據(jù),貪婪模式
.iregexp(exp) 正則表達(dá)式匹配匹配的數(shù)據(jù),非貪婪模式
.bin_and(value) 二進(jìn)制加
.bin_or(value) 二進(jìn)制或
.concat(other) Concatenate two strings or objects using ||.
.distinct() 標(biāo)記重復(fù)的數(shù)據(jù)
.collate(collation) 指定具有給定排序規(guī)則的列
.cast(type) 將列的值強(qiáng)制轉(zhuǎn)換為給定類型

3、聯(lián)合查詢邏輯操作

使用邏輯操作的聯(lián)合查詢

Operator Meaning Example
& AND (User.is_active == True) & (User.is_admin == True)
| OR (User.is_admin) | (User.is_superuser)
~ NOT (unary negation) ~(User.username.contains('admin'))

# Find the user whose username is "charlie".
User.select().where(User.username == 'charlie')

# Find the users whose username is in [charlie, huey, mickey]
User.select().where(User.username.in_(['charlie', 'huey', 'mickey']))

Employee.select().where(Employee.salary.between(50000, 60000))

Employee.select().where(Employee.name.startswith('C'))

Blog.select().where(Blog.title.contains(search_string))

請注意,實(shí)際的比較用括號(hào)括起來。 Python 的運(yùn)算符優(yōu)先級(jí)要求將比較括在括號(hào)中。

# Find any users who are active administrations.
User.select().where(
  (User.is_admin == True) &
  (User.is_active == True))
可能你嘗試使用python語法中的in and or 和not操作,但是在查詢中是不生效的。所有的操作返回都是一個(gè)布爾值。

建議如下:

  1. 用 .in_() 和 .not_in() 替換 in和 not in
  2. 用&替換and
  3. 用|替換or
  4. 用~替換not
  5. 用.is_null()替換 is None 或 == None

十、SQL 方法

SQL方法,如 like , sum 等,可以通過 fn 來表達(dá)

從peewee中導(dǎo)入fn: from peewee import fn

query = (User
         .select(User, fn.COUNT(Tweet.id).alias('tweet_count'))
         .join(Tweet, JOIN.LEFT_OUTER)
         .group_by(User)
         .order_by(fn.COUNT(Tweet.id).desc()))
for user in query:
    print('%s -- %s tweets' % (user.username, user.tweet_count))


fn可以表達(dá)任何SQL方法,它的參數(shù)可以是字段,值,子查詢甚至嵌套函數(shù)

基礎(chǔ)使用

  1. fn.AVG() 返回指定列的平均值,NULL值不包括在計(jì)算中。
  2. fn.SUM() 返回指定列的數(shù)目,NULL值不包括在計(jì)算中。
  3. fn.MIN() 返回指定列的最小值,NULL值不包括在計(jì)算中。
  4. fn.MAX() 返回指定列的最大值,NULL值不包括在計(jì)算中。
  5. fn.DATE() 返回指定日期時(shí)間格式列的日期格式
  6. fn.DECIMAL(10, 2) ===> decimal(10,2)中的“2”表示小數(shù)部分的位數(shù)

進(jìn)階使用

  1. fn.to_char() 返回指定列格式化后的字符串 e.g.: fn.to_char(18.88, '99.999') ===> 18.888; fn.to_char(model.field, '')。
  2. fn.char_length(str) 返回字符串字符數(shù)
  3. fn.array_agg() 接受一組值并返回一個(gè)數(shù)組。
  4. fn.array_agg(model.name).order_by(model.id.asc()) # array_agg(name order by id asc)
  5. fn.rank().over(partition_by=[field1, field2, or aggregation_field1], order_by=[fn.SUM(Booking.slots).desc()]) 實(shí)現(xiàn)rank() over(partition by filed order by filed)分區(qū)功能。
  6. fn.length() 返回指定列的長度。也可應(yīng)用于order_by。e.g.: .order_by(fn.length(model.field).asc())。
  7. fn.CONCAT() 返回合并的字符串(CONCAT一定要大寫,小寫的concat用法不一樣)。fn.CONCAT(model.id, '-', model.name) ===> '188-張三'

1、SQL helper

有時(shí),您可能想在sql中傳一些任意的sql語句。您可以使用特殊的SQL類來實(shí)現(xiàn)這一點(diǎn)

# We'll query the user table and annotate it with a count of tweets for
# the given user
query = (User
         .select(User, fn.Count(Tweet.id).alias('ct'))
         .join(Tweet)
         .group_by(User))

# Now we will order by the count, which was aliased to "ct"
query = query.order_by(SQL('ct'))

# You could, of course, also write this as:
query = query.order_by(fn.COUNT(Tweet.id))

使用peewee執(zhí)行手工SQL語句有兩種方法

  1. Database.execute_sql() 用于執(zhí)行任何類型的查詢
  2. RawQuery 執(zhí)行SELECT查詢并返回模型實(shí)例
query = MyModel.raw('SELECT * FROM my_table WHERE data = %s', user_data)
query.execute_sql()


2、安全和SQL注入

默認(rèn)情況下,peewee將參數(shù)化查詢,因此用戶傳入的任何參數(shù)都將被轉(zhuǎn)義。

請確保將任何用戶定義的數(shù)據(jù)作為查詢參數(shù)傳入,而不是作為實(shí)際SQL查詢的一部分傳入:

query = MyModel.raw('SELECT * FROM my_table WHERE data = %s' % (user_data,))

# Good. `user_data` will be treated as a parameter to the query.
query = MyModel.raw('SELECT * FROM my_table WHERE data = %s', user_data)

# Bad! DO NOT DO THIS!
query = MyModel.select().where(SQL('Some SQL expression %s' % user_data))

# Good. `user_data` will be treated as a parameter.
query = MyModel.select().where(SQL('Some SQL expression %s', user_data))

MySQL和Postgresql使用“%s”表示參數(shù)。另一方面,SQLite使用“?”。請確保使用適合數(shù)據(jù)庫的字符。還可以通過檢查Database.param來查找此參數(shù)。

到此這篇關(guān)于python輕量級(jí)orm框架 peewee常用功能速查詳情的文章就介紹到這了,更多相關(guān)python輕量級(jí)orm框架 peewee常用功能速查內(nèi)容請搜索腳本之家以前的文

相關(guān)文章

  • 簡單了解Python變量作用域正確使用方法

    簡單了解Python變量作用域正確使用方法

    這篇文章主要介紹了簡單了解Python變量作用域正確使用方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-06-06
  • Python創(chuàng)建相同值數(shù)組/列表的兩種方法

    Python創(chuàng)建相同值數(shù)組/列表的兩種方法

    眾所周知數(shù)組是一種用來在計(jì)算機(jī)中存儲(chǔ)連續(xù)的相同類型數(shù)值的數(shù)據(jù)結(jié)構(gòu),這篇文章主要給大家介紹了關(guān)于Python創(chuàng)建相同值數(shù)組/列表的兩種方法,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-12-12
  • PyCharm2020.1.1與Python3.7.7的安裝教程圖文詳解

    PyCharm2020.1.1與Python3.7.7的安裝教程圖文詳解

    這篇文章主要介紹了PyCharm2020.1.1與Python3.7.7的安裝教程,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-08-08
  • python爬蟲scrapy基于CrawlSpider類的全站數(shù)據(jù)爬取示例解析

    python爬蟲scrapy基于CrawlSpider類的全站數(shù)據(jù)爬取示例解析

    這篇文章主要介紹了python爬蟲scrapy基于CrawlSpider類的全站數(shù)據(jù)爬取示例解析,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-02-02
  • Python基于列表list實(shí)現(xiàn)的CRUD操作功能示例

    Python基于列表list實(shí)現(xiàn)的CRUD操作功能示例

    這篇文章主要介紹了Python列表list實(shí)現(xiàn)的CRUD操作功能,結(jié)合實(shí)例形式分析了Python基于列表list實(shí)現(xiàn)用戶數(shù)據(jù)CRUD相關(guān)操作技巧,需要的朋友可以參考下
    2018-01-01
  • 利用Python開發(fā)實(shí)現(xiàn)簡單的記事本

    利用Python開發(fā)實(shí)現(xiàn)簡單的記事本

    最近想對(duì)python加深學(xué)習(xí)一下,同時(shí)也是想試著做一些東西,所以使用python,結(jié)合Tkinter來做一個(gè)簡單的跨平臺(tái)記事本。最終實(shí)現(xiàn)的記事本如下,也算是麻雀雖小,五臟俱全了,之后也是會(huì)繼續(xù)完善的。文中通過圖文及示例代碼介紹的很詳細(xì),有需要的朋友們可以參考借鑒。
    2016-11-11
  • Pyhton爬蟲知識(shí)之正則表達(dá)式詳解

    Pyhton爬蟲知識(shí)之正則表達(dá)式詳解

    正則表達(dá)式又稱規(guī)則表達(dá)式,計(jì)算機(jī)科學(xué)的一個(gè)概念,正則表達(dá)式通常被用來檢索、替換那些符合某個(gè)模式(規(guī)則)的文本,這篇文章主要給大家介紹了關(guān)于Pyhton爬蟲知識(shí)之正則表達(dá)式的相關(guān)資料,需要的朋友可以參考下
    2022-04-04
  • 用python實(shí)現(xiàn)五子棋實(shí)例

    用python實(shí)現(xiàn)五子棋實(shí)例

    這篇文章主要為大家詳細(xì)介紹了用python實(shí)現(xiàn)五子棋實(shí)例,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • windows下安裝python的C擴(kuò)展編譯環(huán)境(解決Unable to find vcvarsall.bat)

    windows下安裝python的C擴(kuò)展編譯環(huán)境(解決Unable to find vcvarsall.bat)

    這篇文章主要介紹了windows下安裝python的C擴(kuò)展編譯環(huán)境(解決Unable to find vcvarsall.bat),需要的朋友可以參考下
    2018-02-02
  • pandas DataFrame.to_sql()用法小結(jié)

    pandas DataFrame.to_sql()用法小結(jié)

    Pandas是基于NumPy的一種工具,該工具是為了解決數(shù)據(jù)分析任務(wù)而創(chuàng)建的,本文主要介紹了pandas DataFrame.to_sql()用法小結(jié),感興趣的可以了解一下
    2024-02-02

最新評(píng)論