Dans la partie précédente de cette série, nous avons vu comment implémenter le Edit
et Delete
fonctionnalité de souhait pour notre application Bucket List. Dans cette partie, nous allons implémenter la fonctionnalité de pagination pour notre liste d'accueil des utilisateurs.
Mise en route
Commençons par cloner la partie précédente du didacticiel à partir de GitHub.
git clone https://github.com/jay3dec/PythonFlaskMySQLApp_Part4.git
Une fois le code source cloné, accédez au répertoire du projet et démarrez le serveur Web.
cd PythonFlaskMySQLApp_Part4 python app.py
Pointez votre navigateur sur http://localhost:5002/ et l'application devrait être en cours d'exécution.
Mise en œuvre de la pagination
À mesure que la liste de souhaits sur la page d'accueil de l'utilisateur augmente, elle défile vers le bas de la page. Il est donc important d'implémenter la pagination. Nous limiterons le nombre d'éléments affichés sur une page à un certain nombre.
Modifier la procédure Get Wish
Nous allons commencer par modifier le sp_GetWishByUser
procédure pour renvoyer des résultats basés sur une limit
et offset
valeur. Cette fois, nous allons créer dynamiquement notre instruction de procédure stockée pour renvoyer le jeu de résultats en fonction de la valeur de limite et de décalage. Voici le sp_GetWishByUser
modifié Procédure stockée 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 ;
Comme on le voit dans la procédure stockée ci-dessus, nous avons créé notre requête SQL dynamique et l'avons exécutée pour obtenir la liste de souhaits basée sur le offset
et limit
paramètres.
Ajout de la pagination à l'interface utilisateur
Tout d'abord, définissons quelques paramètres par défaut. Dans app.py
ajouter une variable pour la limite de pages.
# Default setting pageLimit = 2
Faites le getWish
la méthode python accepte les requêtes POST.
@app.route('/getWish',methods=['POST'])
Lire le offset
et limit
dans le getWish
méthode et la transmettre lors de l'appel de la procédure stockée 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()
Modifier le GetWishes
Fonction JavaScript dans userHome.html
pour en faire une requête POST et passer le offset
valeur.
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); } }); }
Enregistrez toutes les modifications et redémarrez le serveur. Connectez-vous à l'aide d'une adresse e-mail et d'un mot de passe valides et vous ne devriez avoir que deux enregistrements affichés à l'écran.
La partie base de données fonctionne donc bien. Ensuite, nous devons ajouter l'interface utilisateur de pagination à la page d'accueil de l'utilisateur, ce qui permettra à l'utilisateur de naviguer dans les données.
Nous utiliserons le composant de pagination Bootstrap. Ouvrez userHome.html
et ajoutez le code HTML suivant après le #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>
Enregistrez les modifications et redémarrez le serveur. Une fois connecté, vous devriez pouvoir voir la pagination sous la liste de souhaits.
Rendre la pagination dynamique
La pagination ci-dessus est à quoi ressemblera notre pagination. Mais pour le rendre fonctionnel, nous devons créer notre pagination dynamiquement en fonction du nombre d'enregistrements dans la base de données.
Pour créer notre pagination, nous aurons besoin du nombre total d'enregistrements disponibles dans la base de données. Modifions donc la procédure stockée MySQL sp_GetWishByUser
pour renvoyer le nombre total d'enregistrements disponibles en tant que paramètre de sortie.
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 ;
Comme on le voit dans la procédure stockée modifiée ci-dessus, nous avons ajouté un nouveau paramètre de sortie appelé p_total
et sélectionné le nombre total de souhaits en fonction de l'identifiant de l'utilisateur.
Modifiez également le getWish
méthode python pour transmettre un paramètre de sortie.
_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()
Comme vous pouvez le voir dans le code ci-dessus, une fois que nous avons appelé la procédure stockée, nous fermons le curseur et ouvrons un nouveau curseur pour sélectionner le paramètre renvoyé.
Plus tôt, nous retournions une liste de souhaits de la méthode Python. Maintenant, nous devons également inclure le nombre total d'enregistrements dans le JSON renvoyé. Nous allons donc transformer le dictionnaire de la liste de souhaits en une autre liste, puis ajouter la liste de souhaits et le nombre d'enregistrements à la liste principale. Voici le code modifié du getWish
méthode 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)
Dans GetWishes
Fonction JavaScript, à l'intérieur du rappel de réussite, ajoutez un journal de la console.
console.log(res);
Enregistrez toutes les modifications ci-dessus et redémarrez le serveur. Connectez-vous à l'aide d'une adresse e-mail et d'un mot de passe valides et, lorsque vous êtes sur la page d'accueil de l'utilisateur, vérifiez la console du navigateur. Vous devriez pouvoir voir une réponse semblable à celle illustrée ci-dessous :
[ [{ "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 } ]
En utilisant le nombre total reçu de la réponse, nous pouvons obtenir le nombre total de pages.
var total = wishObj[1]['total']; var pageCount = total/itemsPerPage;
Diviser le nombre total d'éléments de itemsPerPage
count nous donne le nombre de pages nécessaires. Mais cela n'est vrai que lorsque le total est un multiple de itemsPerPage
. Si ce n'est pas le cas, nous devrons vérifier cela et gérer le nombre de pages en conséquence.
var pageRem = total%itemsPerPage; if(pageRem !=0 ){ pageCount = Math.floor(pageCount)+1; }
Cela nous donnera donc le bon nombre de pages.
Maintenant que nous avons le nombre total de pages, nous allons créer le HTML de pagination de manière dynamique. Supprimer le LI
élément du HTML de pagination que nous avons ajouté précédemment.
<nav> <ul class="pagination"> // li we'll create dynamically </ul> </nav>
Dans GetWishes
rappel de succès, créons dynamiquement le lien précédent à l'aide de jQuery.
var prevLink = $('<li/>').append($('<a/>').attr({ 'href': '#' }, { 'aria-label': 'Previous' }) .append($('<span/>').attr('aria-hidden', 'true').html('«'))); $('.pagination').append(prevLink);
Dans le code ci-dessus, nous venons de créer le lien du bouton précédent et de l'ajouter à la pagination UL.
Enregistrez les modifications ci-dessus et redémarrez le serveur. Une fois la connexion réussie, vous devriez pouvoir voir le lien précédent sous la liste.
De même, ajoutons les pages dans la pagination en fonction du nombre de pages.
for (var i = 0; i < pageCount; i++) { var page = $('<li/>').append($('<a/>').attr('href', '#').text(i + 1)); $('.pagination').append(page); }
Ajoutons également le lien suivant après l'ajout du lien des pages.
var nextLink = $('<li/>').append($('<a/>').attr({ 'href': '#' }, { 'aria-label': 'Next' }) .append($('<span/>').attr('aria-hidden', 'true').html('»'))); $('.pagination').append(nextLink);
Enregistrez les modifications et redémarrez le serveur. Connectez-vous à l'aide d'une adresse e-mail et d'un mot de passe valides. Une fois sur la page d'accueil de l'utilisateur, vous devriez pouvoir voir la pagination.
Associer un événement de clic à un numéro de page
Vient maintenant la logique principale qui rendra notre pagination fonctionnelle. Ce que nous allons faire, c'est joindre un appel d'événement de clic sur chaque index de page pour appeler le GetWishes
Fonction JavaScript. Attachons d'abord un événement click à l'élément d'ancrage affichant le numéro de page.
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); }
Nous avons donc simplement attaché un événement onclick à l'ancre de la page. À chaque clic, nous appellerons le GetWishes
fonction et passez le offset
. Déclarez donc le offset
en dehors de la boucle for.
var offset = 0;
Appelez le GetWishes
fonction à l'intérieur de l'appel d'événement click.
GetWishes(offset);
Incrémentez également le offset
en fonction du nombre d'enregistrements affichés.
offset = offset + 2;
Mais chaque fois que le GetWishes
la fonction est appelée, la valeur de offset
sera toujours le dernier ensemble. Nous utiliserons donc les fermetures JavaScript pour transmettre le décalage correct au GetWishes
fonction.
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; }
Enregistrez toutes les modifications ci-dessus et redémarrez le serveur. Connectez-vous à l'aide d'identifiants valides et, une fois sur la page d'accueil de l'utilisateur, essayez de cliquer sur les pages dans la pagination UL.
Ensuite, nous allons implémenter les liens des pages précédente et suivante. Cela peut sembler un peu compliqué, alors laissez-moi vous expliquer un peu avant de commencer la mise en œuvre.
Nous allons afficher cinq pages à la fois. En utilisant le lien suivant et précédent, l'utilisateur peut naviguer respectivement vers les cinq pages suivantes et les cinq pages précédentes. Nous allons stocker les valeurs de la page de démarrage et de la page de fin et continuer à mettre à jour les deux lors du clic suivant et précédent sur le bouton. Commençons donc par ajouter deux champs masqués au userHome.html
page.
<input type="hidden" id="hdnStart" value="1" /> <input type="hidden" id="hdnEnd" value="5"/>
Dans GetWishes
rappel de succès, après avoir vidé le .pagination
UL, ajoutez la ligne de code suivante pour obtenir la dernière page de démarrage et la dernière page de fin.
$('.pagination').empty(); var pageStart = $('#hdnStart').val(); var pageEnd = $('#hdnEnd').val();
Aucun lien de bouton précédent ne sera affiché lors de l'affichage des pages 1 à 5. Si les pages affichées sont supérieures à 5, nous afficherons le lien de bouton précédent.
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); }
Lorsque l'utilisateur clique sur le bouton précédent, nous réinitialisons le hdnStart
et hdnEnd
valeurs et appelez GetWishes
Fonction JavaScript.
$(aPrev).click(function() { $('#hdnStart').val(Number(pageStart) - 5); $('#hdnEnd').val(Number(pageStart) - 5 + 4); GetWishes(Number(pageStart) - 5); });
Ensuite, en fonction de la page de démarrage et de la page de fin, nous allons boucler et créer les liens de page et ajouter le .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); }
En comparant le nombre total de pages et la valeur de début de page, nous déciderons de l'affichage du lien du bouton suivant.
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); }
Comme on le voit dans le code ci-dessus, au prochain clic sur le bouton, nous réinitialisons le hdnStart
et hdnEnd
valeurs du bouton et en appelant GetWishes
Fonction JavaScript.
Voici donc le dernier GetWishes
Fonction 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); } }); }
Enregistrez toutes les modifications ci-dessus et redémarrez le serveur. Connectez-vous à l'aide d'une adresse e-mail et d'un mot de passe valides. Vous devriez pouvoir voir la pagination entièrement fonctionnelle pour la liste de souhaits des utilisateurs.