sql >> Base de Datos >  >> RDS >> Mysql

Crear una aplicación web desde cero usando Python Flask y MySQL:Parte 5

En la parte anterior de esta serie, vimos cómo implementar Edit y Delete funcionalidad deseada para nuestra aplicación de lista de deseos. En esta parte, implementaremos la funcionalidad de paginación para nuestra lista de inicio de usuarios.

Cómo empezar

Empecemos clonando la parte anterior del tutorial de GitHub.

git clone https://github.com/jay3dec/PythonFlaskMySQLApp_Part4.git

Una vez que se haya clonado el código fuente, navegue hasta el directorio del proyecto e inicie el servidor web.

cd PythonFlaskMySQLApp_Part4
python app.py

Apunte su navegador a http://localhost:5002/ y debería tener la aplicación ejecutándose.

Implementación de paginación

A medida que aumenta la lista de deseos en la página de inicio del usuario, se desplaza hacia abajo en la página. Por lo tanto, es importante implementar la paginación. Limitaremos la cantidad de elementos que se muestran en una página a un número determinado.

Modificar el procedimiento Obtener deseo

Comenzaremos modificando el sp_GetWishByUser procedimiento para devolver resultados basados ​​en un limit y offset valor. Esta vez crearemos nuestra declaración de procedimiento almacenado dinámicamente para devolver el conjunto de resultados en función del límite y el valor de compensación. Aquí está el sp_GetWishByUser modificado Procedimiento almacenado de 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 se ve en el procedimiento almacenado anterior, creamos nuestra consulta SQL dinámica y la ejecutamos para obtener la lista de deseos basada en el offset y limit parámetros.

Agregar paginación a la IU

Primero, definamos algunas configuraciones predeterminadas. En app.py agregue una variable para el límite de páginas.

# Default setting
pageLimit = 2

Haz el getWish El método Python acepta solicitudes POST.

@app.route('/getWish',methods=['POST'])

Leer el offset y limit dentro de getWish y páselo mientras llama al procedimiento almacenado de 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 el GetWishes Función JavaScript en userHome.html para convertirlo en una solicitud POST y pasar el 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);
        }
    });
}

Guarde todos los cambios y reinicie el servidor. Inicie sesión con una dirección de correo electrónico y una contraseña válidas y solo debería mostrar dos registros en la pantalla.

Entonces, la parte de la base de datos está funcionando bien. A continuación, debemos agregar la interfaz de usuario de paginación a la página de inicio del usuario, lo que permitirá al usuario navegar por los datos.

Usaremos el componente de paginación Bootstrap. Abra userHome.html y agregue el siguiente código HTML después de #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>

Guarde los cambios y reinicie el servidor. Después de iniciar sesión con éxito, debería poder ver la paginación debajo de la lista de deseos.

Dinamización de la paginación

La paginación anterior es cómo se verá nuestra paginación. Pero para que sea funcional, necesitamos crear nuestra paginación dinámicamente en función de la cantidad de registros en la base de datos.

Para crear nuestra paginación, necesitaremos el número total de registros disponibles en la base de datos. Así que modifiquemos el procedimiento almacenado de MySQL sp_GetWishByUser para devolver el número total de registros disponibles como parámetro de salida.

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 se ve en el procedimiento almacenado modificado anterior, agregamos un nuevo parámetro de salida llamado p_total y seleccionó el recuento total de los deseos en función de la identificación del usuario.

También modifique el getWish python para pasar un parámetro de salida.

 _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 puede ver en el código anterior, una vez que llamamos al procedimiento almacenado, cerramos el cursor y abrimos un nuevo cursor para seleccionar el parámetro devuelto.

Anteriormente, devolvíamos una lista de deseos del método Python. Ahora, también debemos incluir el recuento total de registros en el JSON devuelto. Así que convertiremos el diccionario de la lista de deseos en otra lista y luego agregaremos la lista de deseos y el recuento de registros a la lista principal. Aquí está el código modificado de 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)

En el GetWishes Función de JavaScript, dentro de la devolución de llamada exitosa agregue un registro de consola.

console.log(res);

Guarde todos los cambios anteriores y reinicie el servidor. Inicie sesión con una dirección de correo electrónico y una contraseña válidas y, cuando esté en la página de inicio del usuario, consulte la consola del navegador. Debería poder ver una respuesta similar a la que se ​​muestra a continuación:

[
    [{
        "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 el recuento total recibido de la respuesta, podemos obtener el número total de páginas.

var total = wishObj[1]['total'];
var pageCount = total/itemsPerPage;

Dividir el recuento total de elementos de itemsPerPage count nos da el número de páginas requeridas. Pero esto solo es cierto cuando el total es un múltiplo de itemsPerPage . Si ese no es el caso, tendremos que comprobarlo y gestionar el recuento de páginas en consecuencia.

var pageRem = total%itemsPerPage;
if(pageRem !=0 ){
	pageCount = Math.floor(pageCount)+1;
}

Eso nos dará el recuento de páginas correcto.

Ahora que tenemos el número total de páginas, crearemos el HTML de paginación dinámicamente. Eliminar el LI elemento del HTML de paginación que agregamos anteriormente.

<nav>
    <ul class="pagination">
        // li we'll create dynamically
    </ul>
</nav>

En el GetWishes devolución de llamada exitosa, creemos el enlace anterior dinámicamente usando jQuery.

var prevLink = $('<li/>').append($('<a/>').attr({
        'href': '#'
    }, {
        'aria-label': 'Previous'
    })
    .append($('<span/>').attr('aria-hidden', 'true').html('&laquo;')));

$('.pagination').append(prevLink);

En el código anterior, acabamos de crear el enlace del botón anterior y lo agregamos a la paginación UL.

Guarde los cambios anteriores y reinicie el servidor. Al iniciar sesión correctamente, debería poder ver el enlace anterior debajo de la lista.

Del mismo modo, agreguemos las páginas en la paginación según el recuento de páginas.

for (var i = 0; i < pageCount; i++) {
    var page = $('<li/>').append($('<a/>').attr('href', '#').text(i + 1));
    $('.pagination').append(page);
}

Agreguemos también el enlace Siguiente después de que se haya agregado el enlace de las páginas.

var nextLink = $('<li/>').append($('<a/>').attr({
        'href': '#'
    }, {
        'aria-label': 'Next'
    })
    .append($('<span/>').attr('aria-hidden', 'true').html('&raquo;')));

$('.pagination').append(nextLink);

Guarde los cambios y reinicie el servidor. Inicie sesión con una dirección de correo electrónico y una contraseña válidas y, una vez en la página de inicio del usuario, debería poder ver la paginación.

Adjuntar un evento de clic a un número de página

Ahora viene la lógica principal que hará que nuestra paginación sea funcional. Lo que vamos a hacer es adjuntar una llamada de evento de clic en cada índice de página para llamar a GetWishes Función JavaScript. Primero adjuntemos un evento de clic al elemento ancla que muestra el número de 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);

}

Así que simplemente adjuntamos un evento onclick al ancla de la página. En cada clic llamaremos al GetWishes función y pasar el offset . Así que declara el offset fuera del bucle for.

var offset = 0;

Llame al GetWishes función dentro de la llamada de evento de clic.

GetWishes(offset);

También incrementa el offset basado en el número de registros mostrados.

offset = offset + 2;

Pero cada vez que GetWishes se llama a la función, el valor de offset siempre será el último conjunto. Así que haremos uso de cierres de JavaScript para pasar el desplazamiento correcto a GetWishes función.

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;

}

Guarde todos los cambios anteriores y reinicie el servidor. Inicie sesión con credenciales válidas y, una vez en la página de inicio del usuario, intente hacer clic en las páginas de la UL de paginación.

A continuación, implementaremos los enlaces de página anterior y siguiente. Puede parecer un poco complicado, así que déjame explicarlo un poco antes de comenzar con la implementación.

Mostraremos cinco páginas a la vez. Usando el enlace siguiente y anterior, el usuario puede navegar a las cinco páginas siguientes y cinco anteriores, respectivamente. Almacenaremos los valores de la página de inicio y la página final y seguiremos actualizando tanto en el clic del botón siguiente como en el anterior. Entonces, comencemos agregando dos campos ocultos a userHome.html página.

<input type="hidden" id="hdnStart" value="1" />
<input type="hidden" id="hdnEnd" value="5"/>

En el GetWishes devolución de llamada exitosa, después de haber vaciado el .pagination UL, agregue la siguiente línea de código para obtener la página de inicio y la página final más recientes.

$('.pagination').empty();

var pageStart = $('#hdnStart').val();
var pageEnd = $('#hdnEnd').val();

No se mostrará ningún enlace de botón anterior cuando se muestren las páginas 1 a 5. Si las páginas mostradas son mayores que 5, mostraremos el enlace de botón 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);
}

Cuando el usuario haga clic en el botón anterior, restableceremos hdnStart y hdnEnd valores y llame al GetWishes Función JavaScript.

$(aPrev).click(function() {
    $('#hdnStart').val(Number(pageStart) - 5);
    $('#hdnEnd').val(Number(pageStart) - 5 + 4);
    GetWishes(Number(pageStart) - 5);
});

A continuación, en función de la página de inicio y la página final, crearemos un bucle y crearemos los enlaces de la página y agregaremos el .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);


}

Al comparar el recuento total de páginas y el valor de inicio de la página, decidiremos la visualización del enlace del siguiente botón.

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 se ve en el código anterior, al hacer clic en el botón siguiente estamos restableciendo el hdnStart y hdnEnd valores de los botones y llamando a GetWishes Función JavaScript.

Así que aquí está el GetWishes final Función 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);
        }
    });
}

Guarde todos los cambios anteriores y reinicie el servidor. Inicie sesión con una dirección de correo electrónico y una contraseña válidas. Debería poder ver la paginación completamente funcional para la lista de deseos del usuario.