Na parte anterior desta série, vimos como implementar o
Edit
e Delete
desejo funcionalidade para nosso aplicativo Bucket List. Nesta parte, implementaremos a funcionalidade de paginação para nossa lista inicial de usuários. Primeiros passos
Vamos começar clonando a parte anterior do tutorial do GitHub.
git clone https://github.com/jay3dec/PythonFlaskMySQLApp_Part4.git
Depois que o código-fonte for clonado, navegue até o diretório do projeto e inicie o servidor web.
cd PythonFlaskMySQLApp_Part4 python app.py
Aponte seu navegador para http://localhost:5002/ e você deve ter o aplicativo em execução.
Implementando a paginação
À medida que a lista de desejos na página inicial do usuário aumenta, ela é rolada para baixo na página. Portanto, é importante implementar a paginação. Limitaremos o número de itens exibidos em uma página a um determinado número.
Modifique o procedimento Obter desejo
Começaremos modificando o
sp_GetWishByUser
procedimento para retornar resultados com base em um limit
e offset
valor. Desta vez, criaremos nossa instrução de procedimento armazenado dinamicamente para retornar o conjunto de resultados com base no valor limite e deslocamento. Aqui está o arquivo sp_GetWishByUser
modificado Procedimento armazenado do 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 ;
Como visto no procedimento armazenado acima, criamos nossa consulta SQL dinâmica e a executamos para obter a lista de desejos com base no
offset
e limit
parâmetros. Adicionar paginação à IU
Primeiro, vamos definir algumas configurações padrão. Em
app.py
adicione uma variável para limite de página. # Default setting pageLimit = 2
Faça o
getWish
O método python aceita solicitações POST. @app.route('/getWish',methods=['POST'])
Leia o
offset
e limit
dentro do getWish
e transmita-o ao chamar o procedimento armazenado do 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()
Modifique o
GetWishes
Função JavaScript em userHome.html
para torná-lo uma solicitação POST e passar o offset
valor. 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); } }); }
Salve todas as alterações e reinicie o servidor. Faça login usando um endereço de e-mail e senha válidos e você deverá ter apenas dois registros exibidos na tela.
Portanto, a parte do banco de dados está funcionando bem. Em seguida, precisamos adicionar a interface do usuário de paginação à página inicial do usuário, o que permitirá que o usuário navegue pelos dados.
Usaremos o componente de paginação Bootstrap. Abra
userHome.html
e adicione o seguinte código HTML após o #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>
Salve as alterações e reinicie o servidor. Depois de fazer login com sucesso, você poderá ver a paginação na lista de desejos.
Dinamizando a paginação
A paginação acima é como nossa paginação ficará. Mas para torná-lo funcional, precisamos criar nossa paginação dinamicamente com base no número de registros no banco de dados.
Para criar nossa paginação, precisaremos do número total de registros disponíveis no banco de dados. Então, vamos modificar o procedimento armazenado do MySQL
sp_GetWishByUser
para retornar o número total de registros disponíveis como um parâmetro de saída. 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 ;
Como visto no procedimento armazenado modificado acima, adicionamos um novo parâmetro de saída chamado
p_total
e selecionou a contagem total dos desejos com base no ID do usuário. Modifique também o
getWish
python para passar um parâmetro de saída. _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()
Como você pode ver no código acima, uma vez que chamamos o procedimento armazenado, fechamos o cursor e abrimos um novo cursor para selecionar o parâmetro de saída retornado.
Anteriormente, estávamos retornando uma lista de desejos do método Python. Agora, também precisamos incluir a contagem total de registros no JSON retornado. Assim, transformaremos o dicionário da lista de desejos em outra lista e, em seguida, adicionaremos a lista de desejos e a contagem de registros à lista principal. Aqui está o código modificado do
getWish
método 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)
No
GetWishes
Função JavaScript, dentro do retorno de chamada de sucesso, adicione um log do console. console.log(res);
Salve todas as alterações acima e reinicie o servidor. Faça login usando um endereço de e-mail e senha válidos e, quando estiver na página inicial do usuário, verifique o console do navegador. Você verá uma resposta semelhante à mostrada abaixo:
[ [{ "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 } ]
Usando a contagem total recebida da resposta, podemos obter o número total de páginas.
var total = wishObj[1]['total']; var pageCount = total/itemsPerPage;
Dividindo a contagem total de itens de
itemsPerPage
count nos dá o número de páginas necessárias. Mas isso vale apenas quando o total for um múltiplo de itemsPerPage
. Se esse não for o caso, teremos que verificar isso e lidar com a contagem de páginas de acordo. var pageRem = total%itemsPerPage; if(pageRem !=0 ){ pageCount = Math.floor(pageCount)+1; }
Isso nos dará a contagem de páginas correta.
Agora, como temos o número total de páginas, criaremos o HTML de paginação dinamicamente. Remova o
LI
elemento do HTML de paginação que adicionamos anteriormente. <nav> <ul class="pagination"> // li we'll create dynamically </ul> </nav>
No
GetWishes
sucesso, vamos criar o link anterior dinamicamente usando jQuery. var prevLink = $('<li/>').append($('<a/>').attr({ 'href': '#' }, { 'aria-label': 'Previous' }) .append($('<span/>').attr('aria-hidden', 'true').html('«'))); $('.pagination').append(prevLink);
No código acima, acabamos de criar o link do botão anterior e o anexamos à paginação UL.
Salve as alterações acima e reinicie o servidor. Ao entrar com sucesso, você poderá ver o link anterior na lista.
Da mesma forma, vamos adicionar as páginas na paginação com base na contagem de páginas.
for (var i = 0; i < pageCount; i++) { var page = $('<li/>').append($('<a/>').attr('href', '#').text(i + 1)); $('.pagination').append(page); }
Vamos também adicionar o link Avançar depois que o link das páginas for adicionado.
var nextLink = $('<li/>').append($('<a/>').attr({ 'href': '#' }, { 'aria-label': 'Next' }) .append($('<span/>').attr('aria-hidden', 'true').html('»'))); $('.pagination').append(nextLink);
Salve as alterações e reinicie o servidor. Faça login usando um endereço de e-mail e senha válidos e, uma vez na página inicial do usuário, você poderá ver a paginação.
Anexando um evento de clique a um número de página
Agora vem a lógica principal que tornará nossa paginação funcional. O que faremos é anexar uma chamada de evento de clique em cada índice de página para chamar o método
GetWishes
Função JavaScript. Vamos primeiro anexar um evento de clique ao elemento âncora que exibe o número da página. 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); }
Então, acabamos de anexar um evento onclick à âncora da página. Em cada clique, chamaremos o
GetWishes
função e passe o offset
. Então declare o offset
fora do laço for. var offset = 0;
Chame o
GetWishes
função dentro da chamada do evento click. GetWishes(offset);
Incremente também o
offset
com base no número de registros mostrados. offset = offset + 2;
Mas cada vez que o
GetWishes
função é chamada, o valor de offset
será sempre o último conjunto. Portanto, usaremos JavaScript Closures para passar o deslocamento correto para o GetWishes
função. 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; }
Salve todas as alterações acima e reinicie o servidor. Faça login usando credenciais válidas e, uma vez na página inicial do usuário, tente clicar nas páginas na UL de paginação.
Em seguida, implementaremos os links da página anterior e seguinte. Pode parecer um pouco complicado, então deixe-me explicar um pouco antes de começarmos com a implementação.
Estaremos exibindo cinco páginas por vez. Usando o link seguinte e anterior, o usuário pode navegar para as próximas cinco e cinco páginas anteriores, respectivamente. Armazenaremos os valores da página inicial e da página final e continuaremos atualizando no clique do botão seguinte e anterior. Então vamos começar adicionando dois campos ocultos ao
userHome.html
página. <input type="hidden" id="hdnStart" value="1" /> <input type="hidden" id="hdnEnd" value="5"/>
No
GetWishes
retorno de chamada de sucesso, depois de esvaziarmos o .pagination
UL, adicione a seguinte linha de código para obter a página inicial e a página final mais recentes. $('.pagination').empty(); var pageStart = $('#hdnStart').val(); var pageEnd = $('#hdnEnd').val();
Nenhum link do botão anterior será exibido ao exibir as páginas 1 a 5. Se as páginas exibidas forem maiores que 5, exibiremos o link do botão anterior.
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 o usuário clicar no botão anterior, redefiniremos o
hdnStart
e hdnEnd
valores e chame o método GetWishes
Função JavaScript. $(aPrev).click(function() { $('#hdnStart').val(Number(pageStart) - 5); $('#hdnEnd').val(Number(pageStart) - 5 + 4); GetWishes(Number(pageStart) - 5); });
Em seguida, com base na página inicial e na página final, faremos um loop e criaremos os links da página e anexaremos o
.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); }
Ao comparar a contagem total de páginas e o valor inicial da página, decidiremos a exibição do próximo link do botão.
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); }
Como visto no código acima, no próximo clique do botão estamos redefinindo o
hdnStart
e hdnEnd
valores do botão e chamando o método GetWishes
Função JavaScript. Então aqui está o
GetWishes
final Função 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); } }); }
Salve todas as alterações acima e reinicie o servidor. Faça login usando um endereço de e-mail e senha válidos. Você deve conseguir ver a paginação totalmente funcional para a lista de desejos do usuário.