Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Tworzenie aplikacji internetowej od podstaw przy użyciu Python Flask i MySQL:część 5

W poprzedniej części tej serii widzieliśmy, jak zaimplementować Edit i Delete funkcja życzeń dla naszej aplikacji Bucket List. W tej części zaimplementujemy funkcjonalność stronicowania dla naszej listy domowej użytkowników.

Pierwsze kroki

Zacznijmy od sklonowania poprzedniej części samouczka z GitHub.

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

Po sklonowaniu kodu źródłowego przejdź do katalogu projektu i uruchom serwer WWW.

cd PythonFlaskMySQLApp_Part4
python app.py

Skieruj przeglądarkę na http://localhost:5002/ i powinieneś mieć uruchomioną aplikację.

Implementacja stronicowania

W miarę powiększania się listy życzeń na stronie głównej użytkownika jest ona przewijana w dół strony. Dlatego ważne jest, aby wdrożyć paginację. Ograniczymy liczbę elementów wyświetlanych na stronie do określonej liczby.

Zmień procedurę pobierania życzeń

Zaczniemy od zmodyfikowania sp_GetWishByUser procedura zwracania wyników w oparciu o limit i offset wartość. Tym razem będziemy tworzyć naszą instrukcję procedury składowanej dynamicznie, aby zwrócić zestaw wyników na podstawie wartości limitu i przesunięcia. Oto zmodyfikowany sp_GetWishByUser Procedura składowana 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 ;

Jak widać w powyższej procedurze składowanej, stworzyliśmy nasze dynamiczne zapytanie SQL i wykonaliśmy je, aby uzyskać listę życzeń opartą na offset i limit parametry.

Dodawanie stronicowania do interfejsu

Najpierw zdefiniujmy kilka domyślnych ustawień. W app.py dodaj zmienną dla limitu stron.

# Default setting
pageLimit = 2

Zrób getWish Metoda Pythona akceptuje żądania POST.

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

Przeczytaj offset i limit wewnątrz getWish i przekazać ją podczas wywoływania procedury składowanej 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()


Zmodyfikuj GetWishes Funkcja JavaScript w userHome.html aby uczynić to żądaniem POST i przekazać offset wartość.

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);
        }
    });
}

Zapisz wszystkie zmiany i uruchom ponownie serwer. Zaloguj się przy użyciu prawidłowego adresu e-mail i hasła, a na ekranie powinny być wyświetlane tylko dwa rekordy.

Więc część bazy danych działa dobrze. Następnie musimy dodać interfejs stronicowania do strony głównej użytkownika, co umożliwi użytkownikowi nawigację po danych.

Wykorzystamy składnik stronicowania Bootstrap. Otwórz userHome.html i dodaj następujący kod HTML po #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>

Zapisz zmiany i uruchom ponownie serwer. Po pomyślnym zalogowaniu powinieneś być w stanie zobaczyć paginację pod listą życzeń.

Dynamiczne tworzenie stronicowania

Powyższa paginacja jest tym, jak będzie wyglądać nasza paginacja. Ale aby było funkcjonalne, musimy tworzyć naszą paginację dynamicznie w oparciu o liczbę rekordów w bazie danych.

Aby stworzyć naszą paginację, będziemy potrzebować całkowitej liczby rekordów dostępnych w bazie danych. Zmodyfikujmy więc procedurę składowaną MySQL sp_GetWishByUser aby zwrócić całkowitą liczbę rekordów dostępnych jako parametr out.

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 ;

Jak widać w powyższej zmodyfikowanej procedurze składowanej, dodaliśmy nowy parametr wyjściowy o nazwie p_total i wybrał całkowitą liczbę życzeń na podstawie identyfikatora użytkownika.

Zmodyfikuj także getWish metoda Pythona do przekazania parametru wyjściowego.

 _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()

Jak widać w powyższym kodzie, po wywołaniu procedury składowanej zamykamy kursor i otwieramy nowy kursor, aby wybrać zwrócony parametr out.

Wcześniej zwracaliśmy listę życzeń z metody Pythona. Teraz musimy również uwzględnić całkowitą liczbę rekordów w zwróconym pliku JSON. Utworzymy więc słownik listy życzeń w innej liście, a następnie dodamy listę życzeń i liczbę rekordów do głównej listy. Oto zmodyfikowany kod getWish metoda Pythona.

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)

W GetWishes Funkcja JavaScript, wewnątrz wywołania zwrotnego sukcesu dodaj dziennik konsoli.

console.log(res);

Zapisz wszystkie powyższe zmiany i uruchom ponownie serwer. Zaloguj się przy użyciu prawidłowego adresu e-mail i hasła, a na stronie głównej użytkownika sprawdź konsolę przeglądarki. Powinna być widoczna odpowiedź podobna do tej pokazanej poniżej:

[
    [{
        "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
    }
]

Korzystając z łącznej liczby otrzymanej z odpowiedzi, możemy uzyskać całkowitą liczbę stron.

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

Dzielenie całkowitej liczby elementów z itemsPerPage count podaje nam wymaganą liczbę stron. Ale obowiązuje to tylko wtedy, gdy suma jest wielokrotnością itemsPerPage . Jeśli tak nie jest, będziemy musieli to sprawdzić i odpowiednio obsłużyć liczbę stron.

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

Dzięki temu uzyskamy prawidłową liczbę stron.

Teraz, ponieważ mamy całkowitą liczbę stron, dynamicznie utworzymy kod HTML paginacji. Usuń LI element z kodu HTML stronicowania, który dodaliśmy wcześniej.

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

W GetWishes powodzenia wywołania zwrotnego, stwórzmy poprzedni link dynamicznie za pomocą jQuery.

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

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

W powyższym kodzie właśnie utworzyliśmy poprzedni link do przycisku i dołączyliśmy go do strony UL.

Zapisz powyższe zmiany i uruchom ponownie serwer. Po pomyślnym zalogowaniu powinieneś być w stanie zobaczyć poprzedni link pod listą.

Podobnie dodajmy strony w paginacji na podstawie liczby stron.

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

Dodajmy również link Dalej po dodaniu linku do stron.

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

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

Zapisz zmiany i uruchom ponownie serwer. Zaloguj się przy użyciu prawidłowego adresu e-mail i hasła, a po wejściu na stronę główną użytkownika powinieneś zobaczyć podział na strony.

Dołączanie zdarzenia kliknięcia do numeru strony

Teraz pojawia się główna logika, która sprawi, że nasza paginacja będzie funkcjonalna. Zamierzamy dołączyć wywołanie zdarzenia kliknięcia do każdego indeksu strony, aby wywołać funkcję GetWishes Funkcja JavaScript. Najpierw dołączmy zdarzenie kliknięcia do elementu zakotwiczenia wyświetlającego numer strony.

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);

}

Dlatego właśnie dołączyliśmy zdarzenie onclick do kotwicy strony. Przy każdym kliknięciu wywołamy GetWishes funkcji i przekaż offset . Więc zadeklaruj offset poza pętlą for.

var offset = 0;

Zadzwoń do GetWishes funkcja wewnątrz wywołania zdarzenia kliknięcia.

GetWishes(offset);

Zwiększ także offset na podstawie liczby pokazanych rekordów.

offset = offset + 2;

Ale za każdym razem GetWishes wywoływana jest funkcja, wartość offset zawsze będzie ostatnim zestawem. Dlatego użyjemy zamknięć JavaScript, aby przekazać poprawne przesunięcie do GetWishes funkcja.

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;

}

Zapisz wszystkie powyższe zmiany i uruchom ponownie serwer. Zaloguj się przy użyciu prawidłowych danych logowania, a na stronie głównej użytkownika spróbuj kliknąć strony w UL paginacji.

Następnie zaimplementujemy linki do poprzedniej i następnej strony. Może się to wydawać nieco skomplikowane, więc wyjaśnię to trochę zanim przystąpimy do wdrożenia.

Jednocześnie będziemy wyświetlać pięć stron. Korzystając z następnego i poprzedniego łącza, użytkownik może przejść odpowiednio do następnych pięciu i poprzednich pięciu stron. Będziemy przechowywać wartości strony początkowej i końcowej oraz aktualizować zarówno przy następnym, jak i poprzednim kliknięciu przycisku. Zacznijmy więc od dodania dwóch ukrytych pól do userHome.html strona.

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

W GetWishes powodzenia wywołania zwrotnego, po opróżnieniu .pagination UL, dodaj następujący wiersz kodu, aby uzyskać najnowszą stronę początkową i końcową.

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

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

Żaden link do poprzedniego przycisku nie zostanie wyświetlony podczas wyświetlania stron od 1 do 5. Jeśli liczba wyświetlanych stron jest większa niż 5, wyświetlimy link do poprzedniego przycisku.

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);
}

Gdy użytkownik kliknie poprzedni przycisk, zresetujemy hdnStart i hdnEnd wartości i wywołaj GetWishes Funkcja JavaScript.

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

Następnie, w oparciu o stronę początkową i końcową, zapętlimy i utworzymy linki do stron oraz dołączymy .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);


}

Porównując całkowitą liczbę stron i wartość początkową strony, zdecydujemy o wyświetlaniu następnego linku przycisku.

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);
}

Jak widać w powyższym kodzie, przy następnym kliknięciu przycisku resetujemy hdnStart i hdnEnd wartości przycisków i wywołanie funkcji GetWishes Funkcja JavaScript.

Oto ostatnie GetWishes Funkcja 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);
        }
    });
}

Zapisz wszystkie powyższe zmiany i uruchom ponownie serwer. Zaloguj się przy użyciu prawidłowego adresu e-mail i hasła. Powinieneś być w stanie zobaczyć w pełni funkcjonalną paginację listy życzeń użytkownika.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. SEC_TO_TIME() Przykłady – MySQL

  2. Jak zresetować hasło roota mysql?

  3. Napraw ostrzeżenie MySQL 1287:„BINARY expr” jest przestarzałe i zostanie usunięte w przyszłej wersji

  4. Migracja MySQL do PostgreSQL na AWS RDS, część 3

  5. Długości VARCHAR MySQL i UTF-8