トルネード+ブートストラップはすぐに自分のWebアプリケーションを構築します

序文

最近のpython tordadoフレームワークと、ページ全体のテンプレート、表示やデータアクセスを公開するため、

それはまた、簡単に使用され、ブートストラップより人気の、使いやすく竜巻、と一緒に非常に迅速に小さなケースを実行します。


技術的準備金

  1. パイソン

    オブジェクト指向のカプセル化の基礎知識、継承

  2. データベース

    mysqlの

  3. フレーム

    竜巻、SQLAlchemyの(ORM)、テンプレート

  4. 開発ツール

    pycharm、クロム


機能開発

A.要件分析

  1. 統計は、日付によって逆の順序で、5ページあたりに表示さ

    「一時的な無ドッキング統計」:統計的なデータがない場合は、テキストプロンプトがなければなりません

  2. 日付別のサポート問い合わせ

    ページネーションクエリを表示しません

  3. 現在のページ番号が配置されている示唆、ページングクエリをサポートしています、あなたは、任意のページにジャンプすることができます


II。ページプロトタイプ

リミテッドのフロントエンド、個人レベル、既製の部品がたくさんある内部ブートストラップ・テンプレートを探して、半日費やす必要がスクラッチの見積もりから、このようなページを取得するために直接使用することができ、その後、次のレイアウトを変更、スタイルトーンダウン、簡単な操作を行いますページは十分です。

ブートストラップ:https://v3.bootcss.com/components/


竜巻を構築するためのIII。フレームワーク

生徒たちは、Python、直接easy_installを精通しているか、最新の竜巻、SQLAlchemyの、pymysqlモジュールをインストールPIP

bootstrap.js直接ライン上でダウンロードする公式サイトに、当然のことながら、また依存JQuery.jsをブートストラップする必要があります

app.py

静的リソースのパスを設定します。

"static_path": os.path.join(os.path.dirname(__file__), "statics"),

設定テンプレートのパス:

"template_path": os.path.join(os.path.dirname(__file__), 'templates'),

動作モードを設定します。

# 通过脚本传参的方式指定
define("debug", default=1, help="debug mode: 1 to open, 2 to test env, other to production")
"debug": bool(options.debug),

開発は、デバッグモードを、シングルプロセスを開きます。

application.listen(options.port)
tornado.ioloop.IOLoop.instance().start()

プロダクションモード、オープンマルチプロセス:

application.bind(options.port)
application.start(3)  # 开启 3 个进程
tornado.ioloop.IOLoop.instance().start()


IV。MySQLの接続

あなたが使用したい買収DBSessionクラス、オブジェクト[セッション= DBSessionを()]を作成をすることができ、

データベースは、特に通常の操作ではない場合、セッションの回復期間は、たとえば、少し長く設定することができます。pool_recycle = 60

# coding: utf-8
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine
from settings.setting import MYSQL_SERVER, MYSQL_DRIVER, MYSQL_USERNAME, MYSQL_PASSWORD, DB_NAME, DB_CHARSET

# MYSQL_USERNAME = os.getenv('MYSQL_USER') or settings.MYSQL_USERNAME
# MYSQL_PASSWORD =

# 数据库
engine = create_engine("mysql+{driver}://{username}:{password}@{server}/{database}?charset={charset}"
                       .format(driver=MYSQL_DRIVER,
                               username=MYSQL_USERNAME,
                               password=MYSQL_PASSWORD,
                               server=MYSQL_SERVER,
                               database=DB_NAME,
                               charset=DB_CHARSET),
                       pool_size=20,
                       max_overflow=100,
                       pool_recycle=1,
                       echo=False)
engine.execute("SET NAMES {charset};".format(charset=DB_CHARSET))
MapBase = declarative_base(bind=engine)
DBSession = sessionmaker(bind=engine)


V.処理クラス

基本クラスは、APIの仕様および方法一般的なツールを定義します

まず基底クラスはGlobalBaseHandler、データベースセッション、および取得パラメータパッケージの方法をカプセル化

# 全局基类方法
class GlobalBaseHandler(BaseHandler):
    @property
    def session(self):
        if hasattr(self, "_session"):
            return self._session
        self._session = DBSession()
        return self._session

    # 关闭数据库会话
    def on_finish(self):
        if hasattr(self, "_session"):
            self._session.close()

    def prepare(self):
        pass


お問い合わせ、ページング業務処理クラス

なお:(最初のケース未満);(総ページ数よりも大きいが、総ページ数がゼロです)。

class IllegalStats(GlobalBaseHandler):
    def get(self):
        """
        获取接入,发布统计数据
        :return:
        """
        date = self.get_argument("date")
        current_page = self.get_argument("current_page")  # 当前页
        if date:
            return self.query_by_date(date)
        elif current_page:
            return self.query_paginate(current_page)
        # 默认返回第一页的数据
        else:
            return self.query_paginate()

    def query_paginate(self, current_page=None):
        if current_page is None:
            current_page = 1
        else:
            current_page = int(current_page)
        #
        page_size = 5  # 分页条数
        # 总记录数, 总页数
        total_count = IllegalAccessStats.query_count(self.session)
        if total_count % page_size == 0:
            total_page = int(total_count / page_size)
        else:
            total_page = int(total_count / page_size) + 1

        # 小于第一页
        if current_page <= 0:
            current_page = 1
        # 大于最后一页
        if total_page > 0:
            if current_page > total_page:
                current_page = total_page
        else:
            current_page = 1

        # 当前页的数据
        stats_list = IllegalAccessStats.query_paginate(self.session, current_page=current_page, page_size=page_size)
        return self.render("statistics.html", stats_list=stats_list, date="", total_count=total_count, total_page=total_page, current_page=current_page)

    def query_by_date(self, date):
        stats_list = IllegalAccessStats.query_by_date(self.session, date=date)
        #
        return self.render("statistics.html", stats_list=stats_list, date=date, total_count=None, total_page=None, current_page=None)


VI。レンダリングテンプレート

、HTMLコード内の書き込みのpythonに、と判断すれば、まったく同じ範囲とPythonの構文ステートメントのために、多くの困難がありませんが、ゆっくりとデバッグ出てきたテンプレート、非常に詳細な、非常に良いデバッグをレンダリングエラープロンプトテンプレート、

泥棒、だけでなく、ラベル、だけでなく、論理的なプロセスを記述するために病気を感じます。

statistics.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <!-- viewport视口:网页可以根据设置的宽度自动进行适配,在浏览器的内部虚拟一个容器,容器的宽度与设备的宽度相同。
    width: 默认宽度与设备的宽度相同
    initial-scale: 初始的缩放比,为1:1 -->
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>接入&发布统计信息</title>
    <!-- Bootstrap -->
    <link href="{{static_url('css/bootstrap.min.css')}}" rel="stylesheet">
    <script src="{{static_url('js/jquery-2.1.0.min.js')}}"></script>
    <script src="{{static_url('js/bootstrap.min.js')}}"></script>
    <style type="text/css">
        th, td {
            text-align: center;
            height: 50px;
            vertical-align:middle;
        }
    </style>
</head>
<body>
<div class="container">
    <h2 style="text-align: center">接入 & 发布统计信息</h2>
    <br>
    <br>

    <div style="float: left;">
        <form class="form-inline" action="/illegal/stats" method="get">
            <div class="form-group">
                <label for="exampleInputName1">日期</label>
                <input type="text" name="date" value="{{ date }}" class="form-control" id="exampleInputName1" placeholder="yyyy-mm-dd" >
            </div>
            <button type="submit" class="btn btn-default" style="margin: 5px;">查询</button>
        </form>
    </div>

    <br>
    <br>
    <br>
    <br>
    <br>
    <table border="1" class="table table-bordered table-hover">
        <div>
            <a class="btn btn-primary" href="/illegal/stats?" style="float: left; margin: 3px;">接入</a>
            <a class="btn btn-primary" href="/illegal/stats?" style="position: relative; left: 872px; margin: 3px">发布</a>
        </div>

        <tr class="access">
            <th style="background: #f8efc0; vertical-align:middle">日期</th>
            <th style="background: #4cae4c; vertical-align:middle">违法接收</th>
            <th style="background: #4cae4c; vertical-align:middle">入库成功</th>
            <th style="vertical-align: middle">读取成功</th>
            <th style="background: #d9534f; vertical-align:middle">读取失败</th>
            <th style="vertical-align: middle">下载成功</th>
            <th style="background: #d9534f; vertical-align:middle">下载失败</th>
            <th style="vertical-align: middle">写入成功</th>
            <th style="background: #d9534f; vertical-align:middle">写入失败</th>
            <th style="background: #4cae4c; vertical-align:middle">审核接收</th>
            <th style="background: #4cae4c; vertical-align:middle">发布成功</th>
        </tr>


        {% if len(stats_list) > 0 %}
            {% for stats in stats_list %}
                <tr>
                <td style="vertical-align: middle">{{ stats["date"] }}</td>
                <td style="vertical-align: middle">{{ stats["access_received_total"] }}</td>
                <td style="vertical-align: middle">{{ stats["access_inserted_total"] }}</td>
                <td style="vertical-align: middle">{{ stats["read_success_total"] }}</td>
                <td style="vertical-align: middle">{{ stats["read_false_total"] }}</td>
                <td style="vertical-align: middle">{{ stats["download_success_total"] }}</td>
                <td style="vertical-align: middle">{{ stats["download_false_total"] }}</td>
                <td style="vertical-align: middle">{{ stats["write_success_total"] }}</td>
                <td style="vertical-align: middle">{{ stats["write_false_total"] }}</td>
                <td style="vertical-align: middle">{{ stats["publish_received_total"] }}</td>
                <td style="vertical-align: middle">{{ stats["publish_send_total"] }}</td>
                </tr>
            {% end %}
        {% else %}
            <tr>
                <td colspan="11" style="vertical-align: middle">暂没有对接统计信息</td>
            </tr>
        {% end %}

        </table>

<!--    查询的时候不显示分页内容-->
    {% if total_count is not None or total_page is not None %}
        <div>
            <nav aria-label="Page navigation">
                <ul class="pagination">
                    {% if current_page == 1 %}
                        <li class="disabled">
                    {% end %}

                    {% if current_page != 1 %}
                        <li>
                    {% end %}
                            <a href="/illegal/stats?current_page={{current_page - 1}}" aria-label="Previous">
                                <span aria-hidden="false">&laquo;</span>
                            </a>
                        </li>

                    {% for page in range(1, total_page + 1) %}
                        {% if current_page == page %}
                            <li class="active"><a href="/illegal/stats?current_page={{ page }}">{{ page }}</a></li>

                        {% end %}
                        {% if current_page != page %}
                            <li><a href="/illegal/stats?current_page={{ page }}">{{ page }}</a></li>

                        {% end %}

                    {% end %}

                    {% if current_page == total_page or current_page == 1 %}
                        <li class="disabled">
                    {% end %}

                    {% if current_page != total_page and current_page != 1 %}
                        <li>
                    {% end %}
                        <a href="/illegal/stats?current_page={{current_page + 1}}" aria-label="Next">
                            <span aria-hidden="true">&raquo;</span>
                        </a>
                    </li>
                    <span style="font-size: 25px;margin-left: 5px;">
                            共{{ total_count }}条记录,共{{ total_page }}页
                    </span>
                </ul>
            </nav>
        </div>
    {% end %}
</div>
</body>
</html>


要注意

  1. 時間を演出テンプレートは、使用しstatic_url()、それ以外のテンプレートは、JSファイルをCSSを見つけることができません、静的リソースは、(静)のパスを取得する関数を適切にページをロードすることはできません。

    <link href="{{static_url('css/bootstrap.min.css')}}" rel="stylesheet">

    <script src="{{static_url('js/jquery-2.1.0.min.js')}}"></script>

    <script src="{{static_url('js/bootstrap.min.js')}}"></script>


  1. 現在の活性化状態のページへの追加


改善されたプロジェクト

XXX


最後に、プロジェクトのWebアドレス:https://github.com/kaichenkai/TornadoWebApp


エンディング〜


おすすめ

転載: www.cnblogs.com/kaichenkai/p/11999880.html