Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Criando um aplicativo Web do zero usando Python Flask e MySQL:Parte 5


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">&laquo;</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">&raquo;</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('&laquo;')));

$('.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('&raquo;')));

$('.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('&laquo;'));

    $(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('&raquo;').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('&laquo;'));

                $(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('&raquo;').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.