In het vorige deel van deze serie hebben we gezien hoe de Edit
. te implementeren en Delete
wensfunctionaliteit voor onze Bucket List-applicatie. In dit deel zullen we de paging-functionaliteit voor onze home-lijst van gebruikers implementeren.
Aan de slag
Laten we beginnen met het klonen van het vorige deel van de tutorial van GitHub.
git clone https://github.com/jay3dec/PythonFlaskMySQLApp_Part4.git
Nadat de broncode is gekloond, navigeert u naar de projectdirectory en start u de webserver.
cd PythonFlaskMySQLApp_Part4 python app.py
Ga met je browser naar http://localhost:5002/ en je zou de app moeten laten draaien.
Paginering implementeren
Naarmate de lijst met wensen op de homepage van de gebruiker groter wordt, wordt deze naar beneden gescrold. Het is dus belangrijk om paginering te implementeren. We beperken het aantal items dat op een pagina wordt weergegeven tot een bepaald aantal.
Wijzig de procedure voor het verkrijgen van een wens
We beginnen met het aanpassen van de sp_GetWishByUser
procedure om resultaten te retourneren op basis van een limit
en offset
waarde. Deze keer zullen we onze opgeslagen procedure-instructie dynamisch maken om de resultaatset te retourneren op basis van de limiet- en offsetwaarde. Hier is de gewijzigde sp_GetWishByUser
MySQL opgeslagen procedure.
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 ;
Zoals te zien is in de bovenstaande opgeslagen procedure, hebben we onze dynamische SQL-query gemaakt en uitgevoerd om de verlanglijst te krijgen op basis van de offset
en limit
parameters.
Paginering toevoegen aan de gebruikersinterface
Laten we eerst een paar standaardinstellingen definiëren. In app.py
voeg een variabele toe voor paginalimiet.
# Default setting pageLimit = 2
Maak de getWish
python-methode accepteert POST-verzoeken.
@app.route('/getWish',methods=['POST'])
Lees de offset
en limit
binnen de getWish
methode en geef deze door tijdens het aanroepen van de MySQL-opgeslagen procedure sp_GetWishByUser
.
_limit = pageLimit _offset = request.form['offset'] con = mysql.connect() cursor = con.cursor() cursor.callproc('sp_GetWishByUser',(_user,_limit,_offset)) wishes = cursor.fetchall()
Wijzig de GetWishes
JavaScript-functie in userHome.html
om er een POST-verzoek van te maken en de offset
. door te geven waarde.
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); } }); }
Sla alle wijzigingen op en start de server opnieuw op. Meld u aan met een geldig e-mailadres en wachtwoord en er zouden slechts twee records op het scherm moeten worden weergegeven.
Het databasegedeelte werkt dus goed. Vervolgens moeten we de gebruikersinterface voor paginering toevoegen aan de startpagina van de gebruiker, zodat de gebruiker door de gegevens kan navigeren.
We gebruiken de Bootstrap-paginatiecomponent. Open userHome.html
en voeg de volgende HTML-code toe na de #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>
Sla de wijzigingen op en start de server opnieuw op. Nadat u zich heeft aangemeld, zou u de paginering onder de verlanglijst moeten kunnen zien.
Paginering dynamisch maken
De bovenstaande paginering is hoe onze paginering eruit zal zien. Maar om het functioneel te maken, moeten we onze paginering dynamisch maken op basis van het aantal records in de database.
Om onze paginering te maken, hebben we het totale aantal records nodig dat beschikbaar is in de database. Dus laten we de MySQL-opgeslagen procedure aanpassen sp_GetWishByUser
om het totale aantal beschikbare records als een out-parameter te retourneren.
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 ;
Zoals te zien is in de bovenstaande gewijzigde opgeslagen procedure, hebben we een nieuwe uitvoerparameter toegevoegd met de naam p_total
en selecteerde het totale aantal wensen op basis van de gebruikers-ID.
Wijzig ook de getWish
python-methode om een uitvoerparameter door te geven.
_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()
Zoals je kunt zien in de bovenstaande code, sluiten we de cursor zodra we de opgeslagen procedure hebben aangeroepen en openen we een nieuwe cursor om de geretourneerde out-parameter te selecteren.
Eerder stuurden we een lijst met wensen van de Python-methode terug. Nu moeten we ook het totale aantal records opnemen in de geretourneerde JSON. Dus we zullen het verlanglijstje van de verlanglijst in een andere lijst maken en vervolgens de verlanglijst en het aantal records aan de hoofdlijst toevoegen. Hier is de gewijzigde code van de getWish
python-methode.
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 de GetWishes
JavaScript-functie, voeg binnen de succesvolle callback een consolelog toe.
console.log(res);
Sla alle bovenstaande wijzigingen op en start de server opnieuw op. Meld u aan met een geldig e-mailadres en wachtwoord en controleer op de startpagina van de gebruiker de browserconsole. U zou een antwoord moeten kunnen zien dat lijkt op het antwoord dat hieronder wordt weergegeven:
[ [{ "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 } ]
Met behulp van het totale aantal ontvangen van de reactie, kunnen we het totale aantal pagina's krijgen.
var total = wishObj[1]['total']; var pageCount = total/itemsPerPage;
Het totale aantal items delen van itemsPerPage
count geeft ons het aantal benodigde pagina's. Maar dit geldt alleen als het totaal een veelvoud is van itemsPerPage
. Als dat niet het geval is, moeten we dat controleren en het aantal pagina's dienovereenkomstig aanpassen.
var pageRem = total%itemsPerPage; if(pageRem !=0 ){ pageCount = Math.floor(pageCount)+1; }
Dus dat geeft ons het juiste aantal pagina's.
Omdat we nu het totale aantal pagina's hebben, maken we de paginering-HTML dynamisch. Verwijder de LI
element uit de paginering-HTML die we eerder hebben toegevoegd.
<nav> <ul class="pagination"> // li we'll create dynamically </ul> </nav>
In de GetWishes
succes terugbellen, laten we de vorige link dynamisch maken met jQuery.
var prevLink = $('<li/>').append($('<a/>').attr({ 'href': '#' }, { 'aria-label': 'Previous' }) .append($('<span/>').attr('aria-hidden', 'true').html('«'))); $('.pagination').append(prevLink);
In de bovenstaande code hebben we zojuist de vorige knoplink gemaakt en toegevoegd aan de paginering UL.
Sla de bovenstaande wijzigingen op en start de server opnieuw op. Na succesvolle aanmelding zou u de vorige link onder de lijst moeten kunnen zien.
Laten we op dezelfde manier de pagina's in de paginering toevoegen op basis van het aantal pagina's.
for (var i = 0; i < pageCount; i++) { var page = $('<li/>').append($('<a/>').attr('href', '#').text(i + 1)); $('.pagination').append(page); }
Laten we ook de link Volgende toevoegen nadat de link naar de pagina's is toegevoegd.
var nextLink = $('<li/>').append($('<a/>').attr({ 'href': '#' }, { 'aria-label': 'Next' }) .append($('<span/>').attr('aria-hidden', 'true').html('»'))); $('.pagination').append(nextLink);
Sla de wijzigingen op en start de server opnieuw op. Meld u aan met een geldig e-mailadres en wachtwoord, en eenmaal op de startpagina van de gebruiker zou u de paginering moeten kunnen zien.
Een klikgebeurtenis aan een paginanummer koppelen
Nu komt de belangrijkste logica die onze paginering functioneel zal maken. Wat we gaan doen, is een klikgebeurtenisaanroep toevoegen aan elke pagina-index om de GetWishes
aan te roepen JavaScript-functie. Laten we eerst een klikgebeurtenis koppelen aan het ankerelement dat het paginanummer weergeeft.
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); }
Dus we hebben zojuist een onclick-gebeurtenis toegevoegd aan het pagina-anker. Bij elke klik bellen we de GetWishes
functie en geef de offset
. door . Dus declareer de offset
buiten de for-lus.
var offset = 0;
Bel de GetWishes
functie binnen de klikgebeurtenisaanroep.
GetWishes(offset);
Verhoog ook de offset
gebaseerd op het aantal getoonde records.
offset = offset + 2;
Maar elke keer dat de GetWishes
functie wordt aangeroepen, de waarde van offset
is altijd de laatste set. We zullen dus gebruik maken van JavaScript-sluitingen om de juiste offset door te geven aan de GetWishes
functie.
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; }
Sla alle bovenstaande wijzigingen op en start de server opnieuw op. Log in met geldige inloggegevens en klik op de startpagina van de gebruiker op de pagina's in de UL voor paginering.
Vervolgens implementeren we de links naar de vorige en volgende pagina. Het lijkt misschien een beetje ingewikkeld, dus laat me het een beetje uitleggen voordat we beginnen met de implementatie.
We geven vijf pagina's tegelijk weer. Met de volgende en vorige link kan de gebruiker respectievelijk naar de volgende vijf en de vorige vijf pagina's navigeren. We slaan de waarden van de startpagina en de eindpagina op en blijven zowel bij de volgende als de vorige klik op de knop bijwerken. Dus laten we beginnen met het toevoegen van twee verborgen velden aan de userHome.html
pagina.
<input type="hidden" id="hdnStart" value="1" /> <input type="hidden" id="hdnEnd" value="5"/>
In de GetWishes
succes terugbellen, nadat we de .pagination
. hebben geleegd UL, voeg de volgende regel code toe om de laatste startpagina en eindpagina te krijgen.
$('.pagination').empty(); var pageStart = $('#hdnStart').val(); var pageEnd = $('#hdnEnd').val();
Er wordt geen link naar de vorige knop weergegeven bij het weergeven van pagina's 1 tot 5. Als de weergegeven pagina's groter zijn dan 5, geven we de link naar de vorige knop weer.
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); }
Wanneer de gebruiker op de vorige knop klikt, resetten we de hdnStart
en hdnEnd
waarden en roep de GetWishes
JavaScript-functie.
$(aPrev).click(function() { $('#hdnStart').val(Number(pageStart) - 5); $('#hdnEnd').val(Number(pageStart) - 5 + 4); GetWishes(Number(pageStart) - 5); });
Vervolgens zullen we op basis van de startpagina en de eindpagina een lus maken en de paginalinks maken en de .pagination
toevoegen 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); }
Door het totale aantal pagina's en de startwaarde van de pagina te vergelijken, bepalen we de weergave van de volgende knoplink.
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); }
Zoals te zien is in de bovenstaande code, resetten we bij de volgende klik op de knop de hdnStart
en hdnEnd
knopwaarden en het aanroepen van de GetWishes
JavaScript-functie.
Dus hier is de laatste GetWishes
JavaScript-functie.
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); } }); }
Sla alle bovenstaande wijzigingen op en start de server opnieuw op. Log in met een geldig e-mailadres en wachtwoord. U zou de volledig functionele paginering voor de gebruikersverlanglijst moeten kunnen zien.