Nella parte precedente di questa serie, abbiamo visto come implementare la Edit
e Delete
wish funzionalità per la nostra applicazione Bucket List. In questa parte implementeremo la funzionalità di paging per il nostro elenco di utenti home.
Per iniziare
Iniziamo clonando la parte precedente del tutorial da GitHub.
git clone https://github.com/jay3dec/PythonFlaskMySQLApp_Part4.git
Una volta clonato il codice sorgente, vai alla directory del progetto e avvia il server web.
cd PythonFlaskMySQLApp_Part4 python app.py
Punta il browser su http://localhost:5002/ e dovresti avere l'applicazione in esecuzione.
Implementazione dell'impaginazione
Man mano che l'elenco dei desideri nella home page dell'utente aumenta, viene fatto scorrere verso il basso nella pagina. Quindi è importante implementare l'impaginazione. Limiteremo il numero di elementi mostrati in una pagina a un certo numero.
Modifica la procedura di acquisizione dei desideri
Inizieremo modificando sp_GetWishByUser
procedura per restituire i risultati in base a un limit
e offset
valore. Questa volta creeremo la nostra istruzione di stored procedure in modo dinamico per restituire il set di risultati in base al limite e al valore di offset. Ecco il sp_GetWishByUser
modificato Procedura memorizzata 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 ;
Come visto nella procedura memorizzata sopra, abbiamo creato la nostra query SQL dinamica e l'abbiamo eseguita per ottenere la lista dei desideri basata sull'offset
e limit
parametri.
Aggiunta dell'impaginazione all'interfaccia utente
Innanzitutto, definiamo alcune impostazioni predefinite. In app.py
aggiungi una variabile per il limite di pagine.
# Default setting pageLimit = 2
Crea getWish
python accetta richieste POST.
@app.route('/getWish',methods=['POST'])
Leggi il offset
e limit
all'interno di getWish
metodo e passarlo durante la chiamata alla stored procedure 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()
Modifica il GetWishes
Funzione JavaScript in userHome.html
per farne una richiesta POST e passare l'offset
valore.
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); } }); }
Salva tutte le modifiche e riavvia il server. Accedi utilizzando un indirizzo email e una password validi e dovresti avere solo due record visualizzati sullo schermo.
Quindi la parte del database funziona bene. Successivamente, dobbiamo aggiungere l'interfaccia utente di impaginazione alla home page dell'utente, che consentirà all'utente di navigare tra i dati.
Useremo il componente di impaginazione Bootstrap. Apri userHome.html
e aggiungi il seguente codice HTML dopo #ulist
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>
Salva le modifiche e riavvia il server. Dopo aver eseguito correttamente l'accesso, dovresti essere in grado di vedere l'impaginazione nella lista dei desideri.
Rendere dinamica l'impaginazione
L'impaginazione sopra è come apparirà la nostra impaginazione. Ma per renderlo funzionale, dobbiamo creare la nostra impaginazione dinamicamente in base al numero di record nel database.
Per creare la nostra impaginazione, avremo bisogno del numero totale di record disponibili nel database. Quindi modifichiamo la stored procedure MySQL sp_GetWishByUser
per restituire il numero totale di record disponibili come parametro 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 ;
Come visto nella procedura memorizzata modificata sopra, abbiamo aggiunto un nuovo parametro di output chiamato p_total
e selezionato il conteggio totale dei desideri in base all'ID utente.
Modifica anche il getWish
python per passare un parametro di output.
_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()
Come puoi vedere nel codice sopra, una volta chiamata la stored procedure chiudiamo il cursore e apriamo un nuovo cursore per selezionare il parametro restituito.
In precedenza, stavamo restituendo un elenco di desideri dal metodo Python. Ora, dobbiamo anche includere il conteggio totale dei record nel JSON restituito. Quindi trasformeremo il dizionario della lista dei desideri in un altro elenco e quindi aggiungeremo la lista dei desideri e il conteggio dei record all'elenco principale. Ecco il codice modificato di getWish
metodo 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)
In GetWishes
Funzione JavaScript, all'interno della callback di successo aggiungi un log della console.
console.log(res);
Salva tutte le modifiche precedenti e riavvia il server. Accedi utilizzando un indirizzo e-mail e una password validi e quando sei nella home page dell'utente, controlla la console del browser. Dovresti essere in grado di visualizzare una risposta simile a quella mostrata di seguito:
[ [{ "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 } ]
Utilizzando il conteggio totale ricevuto dalla risposta, possiamo ottenere il numero totale di pagine.
var total = wishObj[1]['total']; var pageCount = total/itemsPerPage;
Dividendo il conteggio totale degli articoli da itemsPerPage
count ci dà il numero di pagine richieste. Ma questo vale solo quando il totale è un multiplo di itemsPerPage
. In caso contrario, dovremo verificarlo e gestire il conteggio delle pagine di conseguenza.
var pageRem = total%itemsPerPage; if(pageRem !=0 ){ pageCount = Math.floor(pageCount)+1; }
Questo ci darà il numero di pagine corretto.
Ora, poiché abbiamo il numero totale di pagine, creeremo l'HTML di impaginazione in modo dinamico. Rimuovere il LI
elemento dall'HTML di paginazione che abbiamo aggiunto in precedenza.
<nav> <ul class="pagination"> // li we'll create dynamically </ul> </nav>
In GetWishes
callback di successo, creiamo il collegamento precedente in modo dinamico usando jQuery.
var prevLink = $('<li/>').append($('<a/>').attr({ 'href': '#' }, { 'aria-label': 'Previous' }) .append($('<span/>').attr('aria-hidden', 'true').html('«'))); $('.pagination').append(prevLink);
Nel codice sopra, abbiamo appena creato il collegamento del pulsante precedente e l'abbiamo aggiunto all'impaginazione UL.
Salva le modifiche precedenti e riavvia il server. Dopo l'accesso, dovresti essere in grado di vedere il link precedente sotto l'elenco.
Allo stesso modo, aggiungiamo le pagine nell'impaginazione in base al conteggio delle pagine.
for (var i = 0; i < pageCount; i++) { var page = $('<li/>').append($('<a/>').attr('href', '#').text(i + 1)); $('.pagination').append(page); }
Aggiungiamo anche il collegamento Avanti dopo che il collegamento alle pagine è stato aggiunto.
var nextLink = $('<li/>').append($('<a/>').attr({ 'href': '#' }, { 'aria-label': 'Next' }) .append($('<span/>').attr('aria-hidden', 'true').html('»'))); $('.pagination').append(nextLink);
Salva le modifiche e riavvia il server. Accedi utilizzando un indirizzo email e una password validi e una volta nella home page dell'utente dovresti essere in grado di vedere l'impaginazione.
Allegare un evento di clic a un numero di pagina
Ora arriva la logica principale che renderà funzionale la nostra impaginazione. Quello che faremo è allegare una chiamata all'evento clic su ogni indice di pagina per chiamare il GetWishes
funzione JavaScript. Per prima cosa alleghiamo un evento click all'elemento anchor che mostra il numero di pagina.
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); }
Quindi abbiamo appena allegato un evento onclick all'ancora della pagina. Ad ogni clic chiameremo GetWishes
funzione e passare l'offset
. Quindi dichiara l'offset
fuori dal ciclo for.
var offset = 0;
Chiama GetWishes
funzione all'interno della chiamata all'evento click.
GetWishes(offset);
Incrementa anche l'offset
in base al numero di record visualizzati.
offset = offset + 2;
Ma ogni volta il GetWishes
viene chiamata la funzione, il valore di offset
sarà sempre l'ultimo set. Quindi utilizzeremo le chiusure JavaScript per passare l'offset corretto a GetWishes
funzione.
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; }
Salva tutte le modifiche precedenti e riavvia il server. Accedi utilizzando credenziali valide e una volta nella home page dell'utente, prova a fare clic sulle pagine nell'UL di impaginazione.
Successivamente, implementeremo i collegamenti alla pagina precedente e successiva. Può sembrare un po' complicato, quindi lascia che lo spieghi un po' prima di iniziare con l'implementazione.
Visualizzeremo cinque pagine alla volta. Utilizzando il collegamento successivo e precedente l'utente può passare rispettivamente alle cinque pagine successive e alle cinque precedenti. Memorizziamo i valori della pagina iniziale e della pagina finale e continueremo ad aggiornare sia il clic del pulsante successivo che quello precedente. Quindi iniziamo aggiungendo due campi nascosti a userHome.html
pagina.
<input type="hidden" id="hdnStart" value="1" /> <input type="hidden" id="hdnEnd" value="5"/>
In GetWishes
callback di successo, dopo aver svuotato il .pagination
UL, aggiungi la seguente riga di codice per ottenere la pagina iniziale e la pagina finale più recenti.
$('.pagination').empty(); var pageStart = $('#hdnStart').val(); var pageEnd = $('#hdnEnd').val();
Non verrà mostrato alcun collegamento al pulsante precedente durante la visualizzazione delle pagine da 1 a 5. Se le pagine visualizzate sono maggiori di 5, verrà visualizzato il collegamento al pulsante precedente.
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); }
Quando l'utente fa clic sul pulsante precedente, reimposteremo hdnStart
e hdnEnd
valori e chiama il GetWishes
funzione JavaScript.
$(aPrev).click(function() { $('#hdnStart').val(Number(pageStart) - 5); $('#hdnEnd').val(Number(pageStart) - 5 + 4); GetWishes(Number(pageStart) - 5); });
Successivamente, in base alla pagina iniziale e alla pagina finale, eseguiremo il ciclo e creeremo i collegamenti alla pagina e aggiungeremo il .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); }
Confrontando il conteggio totale delle pagine e il valore iniziale della pagina, decideremo la visualizzazione del collegamento del pulsante successivo.
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); }
Come visto nel codice sopra, al clic del pulsante successivo stiamo reimpostando hdnStart
e hdnEnd
valori dei pulsanti e chiamando il GetWishes
funzione JavaScript.
Quindi ecco il GetWishes
finale funzione 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); } }); }
Salva tutte le modifiche precedenti e riavvia il server. Accedi utilizzando un indirizzo email e una password validi. Dovresti essere in grado di vedere l'impaginazione completamente funzionale per la lista dei desideri dell'utente.