1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        純Python輕松開發(fā)在線留言板!

        共 15822字,需瀏覽 32分鐘

         ·

        2021-05-11 19:15

        添加微信號"CNFeffery"加入技術(shù)交流群

        ?

        本文示例代碼已上傳至我的Github倉庫https://github.com/CNFeffery/DataScienceStudyNotes

        ?

        1 簡介

        這是我的系列教程「Python+Dash快速web應(yīng)用開發(fā)」的第十七期,在之前的各期教程中,我們針對Dash中各種基礎(chǔ)且常用的概念展開了學(xué)習(xí),但一直沒有針對與數(shù)據(jù)庫之間交互進行專門的介紹,只是在某些示例中利用pandas、SQLAlchemy等工具簡陋地操作數(shù)據(jù)庫。

        而在今天的教程中,我就將帶大家學(xué)習(xí)在Dash中利用簡單好用的ORMpeewee,快速高效地將數(shù)據(jù)庫整合進Dash應(yīng)用中。

        圖1

        2 利用peewee在Dash中整合數(shù)據(jù)庫

        說起peewee,很多使用過ORM(Object Relational Mapping,對象關(guān)系映射)工具的朋友都聽說過,它跟SQLAlchemy等框架從功能上看都大同小異,目的都是為了「不寫SQL」,而是利用面向?qū)ο缶幊痰姆绞?,?code style="font-size: 14px;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">Python中實現(xiàn)常用的SQL功能。

        圖2

        peewee雖然相比SQLAlchemy等重型的ORM框架已經(jīng)輕量很多了,但內(nèi)容還是非常豐富,我們今天就針對一些典型場景,展示一下其與Dash應(yīng)用如何相互結(jié)合。

        2.1 創(chuàng)建數(shù)據(jù)表

        利用peewee構(gòu)建數(shù)據(jù)表,需要定義相應(yīng)的Model類,在類中構(gòu)建的屬性即對應(yīng)表中的字段,并且在Meta類中定義其他的一些屬性,譬如下面的例子我們就以最簡單的SQLite數(shù)據(jù)庫為例:

        ?

        model1.py

        ?
        from peewee import SqliteDatabase, Model
        from peewee import CharField, IntegerField, DateTimeField

        from datetime import datetime

        # 關(guān)聯(lián)數(shù)據(jù)庫,對于sqlite數(shù)據(jù)庫若不存在則會直接創(chuàng)建
        db = SqliteDatabase('17 整合數(shù)據(jù)庫/model1.db')

        class Model1(Model):

            # 用戶名為字符型,并設(shè)置唯一性約束
            username = CharField(unique=True)

            # 用戶等級設(shè)定為整數(shù)型
            level = IntegerField()

            # 用戶加入時間為時間日期類型
            join_datetime = DateTimeField()

            class Meta:
                database = db # 指定數(shù)據(jù)庫
                table_name = 'user_info' # 自定義數(shù)據(jù)表名,不設(shè)置則自動根據(jù)類名推導(dǎo)

        # 創(chuàng)建數(shù)據(jù)表,若對應(yīng)數(shù)據(jù)庫中已存在此表,則會跳過
        db.create_tables([Model1])

        上述的代碼在執(zhí)行之后,便會在關(guān)聯(lián)到的SQLite數(shù)據(jù)庫中創(chuàng)建對應(yīng)的表:

        圖3

        而除了最簡單的SQLite之外,peewee還支持MySQL、PostgreSQL,你可以在http://docs.peewee-orm.com/en/latest/peewee/database.html查看更多使用示例,關(guān)于更多有關(guān)Model創(chuàng)建的知識可以參考http://docs.peewee-orm.com/en/latest/peewee/models.html。

        2.2 向表中新增記錄

        在數(shù)據(jù)表創(chuàng)建完成之后,我們第一件事當(dāng)然是要向表中插入數(shù)據(jù),這在peewee中操作非常簡單:

        • 「插入單條數(shù)據(jù)」

        peewee中向表中插入單條記錄可以使用create()方法:

        # 創(chuàng)建單條記錄
        Model1.create(username='張三', level=6, join_datetime=datetime(202011102845))

        Model1.create(username='李四', level=1, join_datetime=datetime(202051102845))

        執(zhí)行完上述命令后旋即會更新到數(shù)據(jù)庫表中:

        圖4
        • 「插入多條數(shù)據(jù)」

        peewee中批量插入數(shù)據(jù)可以使用insert_many()方法傳入對應(yīng)每行內(nèi)容的字典列表,記得最后要跟著執(zhí)行execute()方法才會真正向數(shù)據(jù)庫執(zhí)行:

        # 批量插入數(shù)據(jù)
        (
            Model1
            .insert_many([
            {'username''王五''level'3'join_datetime': datetime(202031102845)},
            {'username''趙六''level'2'join_datetime': datetime(202041102845)}])
            .execute()
        )
        圖5

        2.3 從表中刪除數(shù)據(jù)

        對于已存在數(shù)據(jù)的表,進行數(shù)據(jù)刪除可以使用到delete()方法其后再鏈?zhǔn)缴?code style="font-size: 14px;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">where()來聲明判斷條件,最后同樣跟上execute()方法執(zhí)行即可,如果要清空整張表則不用加where(),譬如我們要刪除level小于3的記錄:

        # 刪除level小于3的記錄
        Model1.delete().where(Model1.level < 3).execute()
        圖6

        更多關(guān)于peewee數(shù)據(jù)刪除的知識可以參考官方文檔http://docs.peewee-orm.com/en/latest/peewee/querying.html#deleting-records部分內(nèi)容。

        2.4 對表中數(shù)據(jù)進行更新

        作為「增刪改查」中非常重要的「改」,在peewee中實現(xiàn)也是非常的方便,基礎(chǔ)的用法是配合update()where()如下面的例子那樣:

        # 修改username為張三的記錄值level字段為8
        Model1.update(level=8).where(Model1.username == '張三').execute()
        圖7

        更多內(nèi)容可參考官方文檔http://docs.peewee-orm.com/en/latest/peewee/querying.html#updating-existing-records。

        2.5 對表中數(shù)據(jù)進行查詢

        作為「增刪改查」中使用頻次最高的「查」,在peewee中涉及到的知識內(nèi)容非常之龐大,但基礎(chǔ)的格式都是利用select()方法,常用的有以下方式:

        # 獲取查詢結(jié)果方式1:
        query_results = Model1.select().where(Model1.level > 2).execute()

        for query_result in query_results:
            print(query_result.username)
        圖8
        # 獲取查詢結(jié)果方式2:
        query_results = Model1.select().where(Model1.level > 2).dicts()
        list(query_results)
        圖9

        而有關(guān)跨表連接等進階的查詢操作,請參考官方文檔http://docs.peewee-orm.com/en/latest/peewee/query_examples.html#query-examples。

        2.6 基于已存在的表逆向生成Model

        如果你的數(shù)據(jù)庫表已然存在,又希望生成相應(yīng)的Model類,peewee提供了命令行工具幫我們做這件事,以SQLite為例:

        python -m pwiz -e sqlite model1.db >model2.py

        自動生成的model2.py代碼如下,在這個基礎(chǔ)上我們可以進一步的優(yōu)化修改:

        from peewee import *

        database = SqliteDatabase('model1.db')


        class UnknownField(object):
            def __init__(self, *_, **__): pass


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


        class UserInfo(BaseModel):
            join_datetime = DateTimeField()
            level = IntegerField()
            username = CharField(unique=True)

            class Meta:
                table_name = 'user_info'

        而更多關(guān)于peewee利用pwiz生成Model類的參數(shù)和用法可參考官方文檔http://docs.peewee-orm.com/en/latest/peewee/playhouse.html#pwiz-a-model-generator

        3 peewee配合Dash實現(xiàn)在線留言板功能

        getpeewee的常用基礎(chǔ)用法之后,我們回到本文的重點——結(jié)合Dash整合數(shù)據(jù)庫,要實現(xiàn)的功能很簡單,就是實現(xiàn)一個在線留言板,每個訪問應(yīng)用的用戶都可以在填寫若干信息后,發(fā)表自己的留言,其他用戶后續(xù)訪問可以看到前面用戶發(fā)表過的留言信息。

        為了方便演示,我選擇SQLite作為示例數(shù)據(jù)庫,首先我們需要構(gòu)建一個model.py來設(shè)計表模型,來存放每條留言信息,并自定義一些功能函數(shù):

        ?

        model.py

        ?
        from peewee import SqliteDatabase, Model
        from peewee import CharField, DateTimeField, TextField
        from datetime import datetime

        db = SqliteDatabase('17 整合數(shù)據(jù)庫/message_board.db')


        class MessageBoard(Model):
            nickname = CharField()

            pub_datetime = DateTimeField()

            message_content = TextField()

            class Meta:
                database = db  # 指定數(shù)據(jù)庫
                table_name = 'message_board'  # 自定義數(shù)據(jù)表名,不設(shè)置則自動根據(jù)類名推導(dǎo)


        db.create_tables([MessageBoard])


        # 新增留言記錄
        def submit_new_message(nickname, message_content):
            MessageBoard.create(
                nickname=nickname,
                pub_datetime=datetime.now(),
                message_content=message_content
            )


        # 獲取全部留言記錄
        def fetch_all_message():
            return list(MessageBoard.select().dicts())

        接著我們只需要在對應(yīng)Dash應(yīng)用的app.py中調(diào)用model.py中的相關(guān)功能即可,效果如下(動圖錄制有些花屏,大家可以自己運行嘗試,效果更佳):

        圖10
        ?

        app.py

        ?
        import dash
        import dash_html_components as html
        import dash_bootstrap_components as dbc
        from dash.dependencies import Input, Output, State

        from model import MessageBoard, submit_new_message, fetch_all_message

        app = dash.Dash(__name__)

        app.layout = html.Div(
            dbc.Container(
                [
                    html.Div(style={'height''20px'}),
                    html.H2('Dash示例留言板'),
                    dbc.Container(
                        id='history-message',
                        style={
                            'paddingTop''50px',
                            'width''70%',
                            'height''70%',
                            'overflowY''auto',
                            'backgroundColor''#fafafa'
                        }
                    ),
                    dbc.Container(
                        dbc.Row(
                            [
                                dbc.Col(
                                    dbc.Input(placeholder='輸入昵稱:', id='nickname', style={'width''100%'}),
                                    width=3,
                                    style={
                                        'padding'0
                                    }
                                ),
                                dbc.Col(
                                    dbc.Input(placeholder='輸入留言內(nèi)容:', id='message', style={'width''100%'}),
                                    width=7,
                                    style={
                                        'padding'0
                                    }
                                ),
                                dbc.Col(
                                    dbc.Button('提交', id='submit', color='primary', block=True),
                                    width=2,
                                    style={
                                        'padding'0
                                    }
                                )
                            ]
                        ),
                        style={
                            'paddingTop''10px',
                            'width''70%',
                        }
                    )
                ],
                style={
                    'height''800px',
                    'boxShadow''rgb(0 0 0 / 20%) 0px 13px 30px, rgb(255 255 255 / 80%) 0px -13px 30px',
                    'borderRadius''10px'
                }
            ),
            style={
                'paddingTop''50px'
            }
        )


        @app.callback(
            Output('history-message''children'),
            Input('submit''n_clicks'),
            [State('nickname''value'),
             State('message''value')]
        )
        def refresh_message_board(n_clicks, nickname, message):
            if nickname and message:
                submit_new_message(nickname, message)

            return [
                html.Div(
                    [
                        html.Strong(record['nickname']),
                        html.Span(' '),
                        html.Em(record['pub_datetime'].strftime(format='%Y-%m-%d %H:%M:%S')),
                        html.Br(),
                        html.P(record['message_content'])
                    ]
                )
                for record in fetch_all_message()
            ]


        if __name__ == '__main__':
            app.run_server(debug=True)


        有關(guān)peewee的內(nèi)容非常豐富,想要完全記住不太現(xiàn)實,大家可以養(yǎng)成多查官網(wǎng)http://docs.peewee-orm.com/en/latest/的習(xí)慣,內(nèi)容非常詳細(xì)生動,給官方點個贊!

        以上就是本文的全部內(nèi)容,歡迎在評論區(qū)發(fā)表你的意見和想法。

        加入知識星球【我們談?wù)摂?shù)據(jù)科學(xué)】

        400+小伙伴一起學(xué)習(xí)!






        · 推薦閱讀 ·

        jupyter中那些神奇的第三方拓展魔術(shù)命令

        高級,這個Python庫助力pandas智能可視化分析

        100行Python代碼輕松開發(fā)個人博客


        瀏覽 77
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            国产靠逼 | 热久久最新 | 99久热| 豆花在线视频观看 | 国产天堂视频 | 亚洲精品网站在线播放gif | 午夜av在线电影 午夜伦欧美伦电影理论片 69国产精品视频 京香一区二区三区 | 超碰中文字幕在线 | 亚洲淫片 | 91色影视|