sql >> Database teknologi >  >> RDS >> Mysql

Oprettelse af en webapp fra bunden ved hjælp af Python Flask og MySQL:Del 5

I den forrige del af denne serie så vi, hvordan man implementerer Edit og Delete ønsker funktionalitet til vores Bucket List Application. I denne del implementerer vi personsøgningsfunktionaliteten til vores brugerhjemmeliste.

Kom godt i gang

Lad os starte med at klone den forrige del af selvstudiet fra GitHub.

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

Når kildekoden er blevet klonet, skal du navigere til projektbiblioteket og starte webserveren.

cd PythonFlaskMySQLApp_Part4
python app.py

Peg din browser til http://localhost:5002/ og du burde have applikationen kørende.

Implementering af sideinddeling

Efterhånden som listen over ønsker på brugerhjemmesiden øges, bliver den rullet ned på siden. Så det er vigtigt at implementere paginering. Vi vil begrænse antallet af elementer, der vises på en side, til et bestemt antal.

Rediger Get Wish-proceduren

Vi starter med at ændre sp_GetWishByUser procedure for at returnere resultater baseret på en limit og offset værdi. Denne gang vil vi oprette vores lagrede procedure-sætning dynamisk for at returnere resultatsættet baseret på grænse- og offsetværdien. Her er den ændrede sp_GetWishByUser MySQL-lagret 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 ;

Som det fremgår af ovenstående lagrede procedure, oprettede vi vores dynamiske SQL-forespørgsel og udførte den for at få ønskeliste baseret på offset og limit parametre.

Tilføjelse af sideinddeling til brugergrænsefladen

Lad os først definere et par standardindstillinger. I app.py tilføje en variabel for sidegrænse.

# Default setting
pageLimit = 2

Lav getWish python-metoden accepterer POST-anmodninger.

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

Læs offset og limit inde i getWish metode og videregive den, mens du kalder MySQL-lagrede 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()


Rediger GetWishes JavaScript-funktion i userHome.html for at gøre det til en POST-anmodning og videregive offset værdi.

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

Gem alle ændringerne og genstart serveren. Log ind med en gyldig e-mailadresse og adgangskode, og du bør kun have to poster vist på skærmen.

Så databasedelen fungerer godt. Dernæst skal vi tilføje pagineringsbrugergrænsefladen til brugerens startside, hvilket vil gøre det muligt for brugeren at navigere på tværs af dataene.

Vi bruger Bootstrap-pagineringskomponenten. Åbn userHome.html og tilføj følgende HTML-kode efter #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>

Gem ændringerne og genstart serveren. Når du har logget ind, bør du kunne se sideinddelingen under ønskeliste.

Gør sideinddeling dynamisk

Ovenstående paginering er, hvordan vores paginering vil se ud. Men for at gøre det funktionelt, er vi nødt til at oprette vores paginering dynamisk baseret på antallet af poster i databasen.

For at oprette vores paginering skal vi bruge det samlede antal poster, der er tilgængelige i databasen. Så lad os ændre den MySQL-lagrede procedure sp_GetWishByUser for at returnere det samlede antal tilgængelige poster som en ud-parameter.

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 ;

Som det ses i den ovenfor ændrede lagrede procedure, tilføjede vi en ny outputparameter kaldet p_total og valgte det samlede antal ønsker baseret på bruger-id.

Rediger også getWish python-metode til at sende en outputparameter.

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

Som du kan se i ovenstående kode, lukker vi markøren, når vi har kaldt den lagrede procedure, og åbner en ny markør for at vælge den returnerede parameter.

Tidligere returnerede vi en liste over ønsker fra Python-metoden. Nu skal vi også inkludere det samlede antal poster i den returnerede JSON. Så vi laver ønskesedlens ordbog om til en anden liste og tilføjer så ønskesedlen og registreringsantallet til hovedlisten. Her er den ændrede kode for getWish python-metoden.

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)

I GetWishes JavaScript-funktion, inde i succes-tilbagekaldet tilføj en konsollog.

console.log(res);

Gem alle ovenstående ændringer og genstart serveren. Log ind med en gyldig e-mailadresse og adgangskode, og tjek browserkonsollen, når du er på brugerhjemmesiden. Du burde kunne se et svar, der ligner det vist nedenfor:

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

Ved at bruge det samlede antal modtaget fra svaret kan vi få det samlede antal sider.

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

Opdeling af det samlede antal varer fra itemsPerPage count giver os det nødvendige antal sider. Men dette gælder kun, når totalen er et multiplum af itemsPerPage . Hvis det ikke er tilfældet, bliver vi nødt til at tjekke for det og håndtere sideantallet i overensstemmelse hermed.

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

Så det vil give os det korrekte sideantal.

Nu, da vi har det samlede antal sider, opretter vi paginerings-HTML'en dynamisk. Fjern LI element fra paginerings-HTML, vi tilføjede tidligere.

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

I GetWishes succes tilbagekald, lad os oprette det forrige link dynamisk ved hjælp af jQuery.

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

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

I ovenstående kode har vi lige oprettet det forrige knaplink og tilføjet det til paginering UL.

Gem ovenstående ændringer og genstart serveren. Ved vellykket login skulle du kunne se det forrige link under listen.

Lad os på samme måde tilføje siderne i pagineringen baseret på sideantallet.

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

Lad os også tilføje næste link, efter at sidelinket er blevet tilføjet.

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

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

Gem ændringerne og genstart serveren. Log ind med en gyldig e-mailadresse og adgangskode, og når du først er på brugerhjemmesiden, bør du kunne se pagineringen.

Vedhæftning af en klikbegivenhed til et sidenummer

Nu kommer hovedlogikken, der vil gøre vores paginering funktionel. Det, vi skal gøre, er at vedhæfte et klikhændelseskald på hvert sideindeks for at kalde GetWishes JavaScript funktion. Lad os først vedhæfte en klikhændelse til ankerelementet, der viser sidenummeret.

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

}

Så vi har lige knyttet en onclick-begivenhed til sideankeret. Ved hvert klik kalder vi GetWishes funktion og videregive offset . Så erklær offset uden for for-løkken.

var offset = 0;

Ring til GetWishes funktion inde i klikhændelseskaldet.

GetWishes(offset);

Forøg også offset baseret på antallet af viste poster.

offset = offset + 2;

Men hver gang GetWishes funktionen kaldes, værdien af ​​offset vil altid være det sidste sæt. Så vi vil gøre brug af JavaScript-lukninger til at overføre den korrekte offset til GetWishes funktion.

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;

}

Gem alle ovenstående ændringer og genstart serveren. Log ind med gyldige legitimationsoplysninger, og prøv at klikke på siderne i paginering UL en gang på brugerhjemmesiden.

Dernæst implementerer vi de forrige og næste sidelinks. Det kan virke lidt kompliceret, så lad mig forklare det lidt, inden vi begynder med implementeringen.

Vi viser fem sider ad gangen. Ved at bruge næste og forrige link kan brugeren navigere til henholdsvis de næste fem og fem foregående sider. Vi gemmer værdierne for startsiden og slutsiden og bliver ved med at opdatere både ved næste og forrige knapklik. Så lad os starte med at tilføje to skjulte felter til userHome.html side.

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

I GetWishes succes tilbagekald, efter at vi har tømt .pagination UL, tilføj følgende kodelinje for at få den seneste startside og slutside.

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

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

Der vil ikke blive vist noget tidligere knaplink, når siderne 1 til 5 vises. Hvis de viste sider er større end 5, viser vi det forrige knaplink.

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

Når brugeren klikker på den forrige knap, nulstiller vi hdnStart og hdnEnd værdier og kalde GetWishes JavaScript funktion.

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

Dernæst, baseret på startsiden og slutsiden, vil vi sløjfe og oprette sidelinkene og tilføje .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);


}

Ved at sammenligne det samlede sideantal og sidens startværdi bestemmer vi visningen af ​​det næste knaplink.

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

Som det fremgår af ovenstående kode, nulstiller vi hdnStart ved næste klik på knappen og hdnEnd knapværdier og kalder GetWishes JavaScript-funktion.

Så her er den sidste GetWishes JavaScript funktion.

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

Gem alle ovenstående ændringer og genstart serveren. Log ind med en gyldig e-mailadresse og adgangskode. Du bør være i stand til at se den fuldt funktionelle paginering for brugerens ønskeliste.


  1. Hvordan bruger jeg korrekt CASE..WHEN i MySQL

  2. hvis min tabel har 4 kolonner, og jeg vil hente den 3. kolonne, hvad gør jeg.

  3. Vil du slette en enkelt post fra Entity Framework?

  4. Standard rækkefølge i SELECT-forespørgsel - SQL Server 2008 vs SQL 2012