このシリーズの前のパートでは、Edit
を実装する方法を見ました およびDelete
バケットリストアプリケーションの機能を希望します。このパートでは、ユーザーホームリストのページング機能を実装します。
はじめに
チュートリアルの前の部分をGitHubから複製することから始めましょう。
git clone https://github.com/jay3dec/PythonFlaskMySQLApp_Part4.git
ソースコードのクローンが作成されたら、プロジェクトディレクトリに移動して、Webサーバーを起動します。
cd PythonFlaskMySQLApp_Part4 python app.py
ブラウザでhttp:// localhost:5002 /を指定すると、アプリケーションが実行されているはずです。
ページネーションの実装
ユーザーのホームページの希望のリストが増えると、ページを下にスクロールします。したがって、ページネーションを実装することが重要です。 1ページに表示されるアイテムの数を特定の数に制限します。
GetWishプロシージャを変更する
まず、sp_GetWishByUser
を変更します。 limit
に基づいて結果を返す手順 およびoffset
価値。今回は、ストアドプロシージャステートメントを動的に作成して、制限値とオフセット値に基づいて結果セットを返します。変更されたsp_GetWishByUser
は次のとおりです MySQLストアドプロシージャ。
USE `BucketList`; DROP procedure IF EXISTS `sp_GetWishByUser`; DELIMITER $$ USE `BucketList`$$ CREATE DEFINER=`root`@`localhost` PROCEDURE `sp_GetWishByUser`( IN p_user_id bigint, IN p_limit int, IN p_offset int ) BEGIN SET @t1 = CONCAT( 'select * from tbl_wish where wish_user_id = ', p_user_id, ' order by wish_date desc limit ',p_limit,' offset ',p_offset); PREPARE stmt FROM @t1; EXECUTE stmt; DEALLOCATE PREPARE stmt1; END$$ DELIMITER ;
上記のストアドプロシージャに見られるように、動的SQLクエリを作成して実行し、offset
に基づいてウィッシュリストを取得しました。 およびlimit
パラメータ。
UIにページ付けを追加する
まず、いくつかのデフォルト設定を定義しましょう。 app.py
内 ページ制限の変数を追加します。
# Default setting pageLimit = 2
getWish
を作成します PythonメソッドはPOSTリクエストを受け入れます。
@app.route('/getWish',methods=['POST'])
offset
を読む およびlimit
getWish
内 メソッドを実行し、MySQLストアドプロシージャsp_GetWishByUser
を呼び出しているときに渡します。 。
_limit = pageLimit _offset = request.form['offset'] con = mysql.connect() cursor = con.cursor() cursor.callproc('sp_GetWishByUser',(_user,_limit,_offset)) wishes = cursor.fetchall()
GetWishes
を変更します userHome.html
のJavaScript関数 それをPOSTリクエストにして、offset
を渡します 値。
function GetWishes() { $.ajax({ url: '/getWish', type: 'POST', data: { offset: 0 }, success: function(res) { var wishObj = JSON.parse(res); $('#ulist').empty(); $('#listTemplate').tmpl(wishObj).appendTo('#ulist'); }, error: function(error) { console.log(error); } }); }
すべての変更を保存して、サーバーを再起動します。有効なメールアドレスとパスワードを使用してサインインすると、画面に表示されるレコードは2つだけになります。
したがって、データベース部分はうまく機能しています。次に、ページネーションUIをユーザーのホームページに追加する必要があります。これにより、ユーザーはデータ間を移動できるようになります。
Bootstrapページネーションコンポーネントを使用します。 userHome.html
を開きます #ulist
の後に次のHTMLコードを追加します UL。
<nav> <ul class="pagination"> <li> <a href="#" aria-label="Previous"> <span aria-hidden="true">«</span> </a> </li> <li><a href="#">1</a> </li> <li><a href="#">2</a> </li> <li><a href="#">3</a> </li> <li><a href="#">4</a> </li> <li><a href="#">5</a> </li> <li> <a href="#" aria-label="Next"> <span aria-hidden="true">»</span> </a> </li> </ul> </nav>
変更を保存して、サーバーを再起動します。サインインに成功すると、ウィッシュリストの下にページネーションが表示されるはずです。
ページネーションを動的にする
上記のページ付けは、私たちのページ付けがどのように見えるかです。ただし、機能させるには、データベース内のレコード数に基づいて動的にページネーションを作成する必要があります。
ページネーションを作成するには、データベースで使用可能なレコードの総数が必要です。それでは、MySQLストアドプロシージャsp_GetWishByUser
を変更しましょう。 outパラメータとして使用可能なレコードの総数を返します。
USE `BucketList`; DROP procedure IF EXISTS `sp_GetWishByUser`; DELIMITER $$ USE `BucketList`$$ CREATE DEFINER=`root`@`localhost` PROCEDURE `sp_GetWishByUser`( IN p_user_id bigint, IN p_limit int, IN p_offset int, out p_total bigint ) BEGIN select count(*) into p_total from tbl_wish where wish_user_id = p_user_id; SET @t1 = CONCAT( 'select * from tbl_wish where wish_user_id = ', p_user_id, ' order by wish_date desc limit ',p_limit,' offset ',p_offset); PREPARE stmt FROM @t1; EXECUTE stmt; DEALLOCATE PREPARE stmt; END$$ DELIMITER ;
上記の変更されたストアドプロシージャに見られるように、p_total
という新しい出力パラメータを追加しました。 そして、ユーザーIDに基づいてウィッシュの総数を選択しました。
getWish
も変更します 出力パラメータを渡すPythonメソッド。
_limit = pageLimit _offset = request.form['offset'] _total_records = 0 con = mysql.connect() cursor = con.cursor() cursor.callproc('sp_GetWishByUser',(_user,_limit,_offset,_total_records)) wishes = cursor.fetchall() cursor.close() cursor = con.cursor() cursor.execute('SELECT @_sp_GetWishByUser_3'); outParam = cursor.fetchall()
上記のコードでわかるように、ストアドプロシージャを呼び出したら、カーソルを閉じて新しいカーソルを開き、返されたパラメータを選択します。
以前は、Pythonメソッドからウィッシュのリストを返していました。ここで、返されたJSONに合計レコード数も含める必要があります。そこで、ウィッシュリスト辞書を別のリストにしてから、ウィッシュリストとレコード数をメインリストに追加します。これがgetWish
の変更されたコードです Pythonメソッド。
response = [] wishes_dict = [] for wish in wishes: wish_dict = { 'Id': wish[0], 'Title': wish[1], 'Description': wish[2], 'Date': wish[4]} wishes_dict.append(wish_dict) response.append(wishes_dict) response.append({'total':outParam[0][0]}) return json.dumps(response)
GetWishes
で JavaScript関数、成功コールバック内にコンソールログを追加します。
console.log(res);
上記の変更をすべて保存して、サーバーを再起動します。有効な電子メールアドレスとパスワードを使用してサインインし、ユーザーのホームページでブラウザコンソールを確認します。以下に示すような応答が表示されるはずです。
[ [{ "Date": "Sun, 15 Feb 2015 15:10:45 GMT", "Description": "wwe", "Id": 5, "Title": "wwe" }, { "Date": "Sat, 24 Jan 2015 00:13:50 GMT", "Description": "Travel to Spain", "Id": 4, "Title": "Spain" }], { "total": 5 } ]
回答から受け取った合計数を使用して、合計ページ数を取得できます。
var total = wishObj[1]['total']; var pageCount = total/itemsPerPage;
合計アイテム数をitemsPerPage
から除算します countは、必要なページ数を示します。ただし、これは、合計がitemsPerPage
の倍数である場合にのみ当てはまります。 。そうでない場合は、それを確認し、それに応じてページ数を処理する必要があります。
var pageRem = total%itemsPerPage; if(pageRem !=0 ){ pageCount = Math.floor(pageCount)+1; }
これで正しいページ数が得られます。
これでページの総数がわかったので、ページネーションHTMLを動的に作成します。 LI
を削除します 以前に追加したページネーションHTMLの要素。
<nav> <ul class="pagination"> // li we'll create dynamically </ul> </nav>
GetWishes
で 成功したコールバック、jQueryを使用して前のリンクを動的に作成しましょう。
var prevLink = $('<li/>').append($('<a/>').attr({ 'href': '#' }, { 'aria-label': 'Previous' }) .append($('<span/>').attr('aria-hidden', 'true').html('«'))); $('.pagination').append(prevLink);
上記のコードでは、前のボタンリンクを作成し、それをページネーションULに追加しました。
上記の変更を保存して、サーバーを再起動します。サインインに成功すると、リストの下に前のリンクが表示されます。
同様に、ページ数に基づいてページネーションにページを追加しましょう。
for (var i = 0; i < pageCount; i++) { var page = $('<li/>').append($('<a/>').attr('href', '#').text(i + 1)); $('.pagination').append(page); }
ページリンクを追加した後、次のリンクも追加しましょう。
var nextLink = $('<li/>').append($('<a/>').attr({ 'href': '#' }, { 'aria-label': 'Next' }) .append($('<span/>').attr('aria-hidden', 'true').html('»'))); $('.pagination').append(nextLink);
変更を保存して、サーバーを再起動します。有効なメールアドレスとパスワードを使用してログインすると、ユーザーのホームページにアクセスすると、ページネーションが表示されます。
クリックイベントをページ番号に添付する
ここで、ページネーションを機能させるメインロジックが登場します。これから行うことは、各ページインデックスにクリックイベント呼び出しをアタッチして、GetWishes
を呼び出すことです。 JavaScript関数。まず、ページ番号を表示するアンカー要素にクリックイベントを添付しましょう。
for (var i = 0; i < pageCount; i++) { var aPage = $('<a/>').attr('href', '#').text(i + 1); $(aPage).click(function() { }); var page = $('<li/>').append(aPage); $('.pagination').append(page); }
そのため、onclickイベントをページアンカーにアタッチしました。クリックするたびに、GetWishes
を呼び出します。 関数を実行し、offset
を渡します 。したがって、offset
を宣言します forループの外側。
var offset = 0;
GetWishes
を呼び出します クリックイベント呼び出し内で機能します。
GetWishes(offset);
また、offset
をインクリメントします 表示されたレコードの数に基づきます。
offset = offset + 2;
しかし、毎回GetWishes
関数が呼び出され、offset
の値 常に最後のセットになります。そのため、JavaScriptクロージャを使用して、正しいオフセットをGetWishes
に渡します。 機能。
var offset = 0; for (var i = 0; i < pageCount; i++) { var aPage = $('<a/>').attr('href', '#').text(i + 1); $(aPage).click(function(offset) { return function() { GetWishes(offset); } }(offset)); var page = $('<li/>').append(aPage); $('.pagination').append(page); offset = offset + itemsPerPage; }
上記の変更をすべて保存して、サーバーを再起動します。有効な認証情報を使用してログインし、ユーザーのホームページが表示されたら、ページネーションULのページをクリックしてみてください。
次に、前のページと次のページのリンクを実装します。少し複雑に思えるかもしれませんので、実装を始める前に少し説明しましょう。
一度に5ページを表示します。次と前のリンクを使用して、ユーザーはそれぞれ次の5ページと前の5ページに移動できます。開始ページと終了ページの値を保存し、次と前のボタンクリックの両方で更新を続けます。それでは、2つの非表示フィールドをuserHome.html
に追加することから始めましょう。 ページ。
<input type="hidden" id="hdnStart" value="1" /> <input type="hidden" id="hdnEnd" value="5"/>
GetWishes
で .pagination
を空にした後の成功コールバック ULの場合、次のコード行を追加して、最新の開始ページと終了ページを取得します。
$('.pagination').empty(); var pageStart = $('#hdnStart').val(); var pageEnd = $('#hdnEnd').val();
1〜5ページを表示する場合、前のボタンのリンクは表示されません。表示されるページが5より大きい場合は、前のボタンのリンクが表示されます。
if (pageStart > 5) { var aPrev = $('<a/>').attr({ 'href': '#' }, { 'aria-label': 'Previous' }) .append($('<span/>').attr('aria-hidden', 'true').html('«')); $(aPrev).click(function() { // Previous button logic }); var prevLink = $('<li/>').append(aPrev); $('.pagination').append(prevLink); }
ユーザーが前のボタンをクリックすると、hdnStart
がリセットされます およびhdnEnd
値を入力し、GetWishes
を呼び出します JavaScript関数。
$(aPrev).click(function() { $('#hdnStart').val(Number(pageStart) - 5); $('#hdnEnd').val(Number(pageStart) - 5 + 4); GetWishes(Number(pageStart) - 5); });
次に、開始ページと終了ページに基づいて、ループしてページリンクを作成し、.pagination
を追加します。 UL。
for (var i = Number(pageStart); i <= Number(pageEnd); i++) { if (i > pageCount) { break; } var aPage = $('<a/>').attr('href', '#').text(i); // Attach the page click event $(aPage).click(function(i) { return function() { GetWishes(i); } }(i)); var page = $('<li/>').append(aPage); // Attach the active page class if ((_page) == i) { $(page).attr('class', 'active'); } $('.pagination').append(page); }
合計ページ数とページ開始値を比較して、次のボタンリンクの表示を決定します。
if ((Number(pageStart) + 5) <= pageCount) { var nextLink = $('<li/>').append($('<a/>').attr({ 'href': '#' }, { 'aria-label': 'Next' }) .append($('<span/>').attr('aria-hidden', 'true').html('»').click(function() { $('#hdnStart').val(Number(pageStart) + 5); $('#hdnEnd').val(Number(pageStart) + 5 + 4); GetWishes(Number(pageStart) + 5); }))); $('.pagination').append(nextLink); }
上記のコードに見られるように、次のボタンをクリックすると、hdnStart
がリセットされます。 およびhdnEnd
ボタンの値とGetWishes
の呼び出し JavaScript関数。
これが最後のGetWishes
です JavaScript関数。
function GetWishes(_page) { var _offset = (_page - 1) * 2; $.ajax({ url: '/getWish', type: 'POST', data: { offset: _offset }, success: function(res) { var itemsPerPage = 2; var wishObj = JSON.parse(res); $('#ulist').empty(); $('#listTemplate').tmpl(wishObj[0]).appendTo('#ulist'); var total = wishObj[1]['total']; var pageCount = total / itemsPerPage; var pageRem = total % itemsPerPage; if (pageRem != 0) { pageCount = Math.floor(pageCount) + 1; } $('.pagination').empty(); var pageStart = $('#hdnStart').val(); var pageEnd = $('#hdnEnd').val(); if (pageStart > 5) { var aPrev = $('<a/>').attr({ 'href': '#' }, { 'aria-label': 'Previous' }) .append($('<span/>').attr('aria-hidden', 'true').html('«')); $(aPrev).click(function() { $('#hdnStart').val(Number(pageStart) - 5); $('#hdnEnd').val(Number(pageStart) - 5 + 4); GetWishes(Number(pageStart) - 5); }); var prevLink = $('<li/>').append(aPrev); $('.pagination').append(prevLink); } for (var i = Number(pageStart); i <= Number(pageEnd); i++) { if (i > pageCount) { break; } var aPage = $('<a/>').attr('href', '#').text(i); $(aPage).click(function(i) { return function() { GetWishes(i); } }(i)); var page = $('<li/>').append(aPage); if ((_page) == i) { $(page).attr('class', 'active'); } $('.pagination').append(page); } if ((Number(pageStart) + 5) <= pageCount) { var nextLink = $('<li/>').append($('<a/>').attr({ 'href': '#' }, { 'aria-label': 'Next' }) .append($('<span/>').attr('aria-hidden', 'true').html('»').click(function() { $('#hdnStart').val(Number(pageStart) + 5); $('#hdnEnd').val(Number(pageStart) + 5 + 4); GetWishes(Number(pageStart) + 5); }))); $('.pagination').append(nextLink); } }, error: function(error) { console.log(error); } }); }
上記の変更をすべて保存して、サーバーを再起動します。有効なメールアドレスとパスワードを使用してサインインします。ユーザーの希望リストの完全に機能するページネーションを確認できるはずです。