1. Innledning
1.1 Språk på klientsiden og språk på serversiden ...
HTML(HyperText Markup Language)og CSS(Cascading Style Sheet), er to enkle visningsspråkstatiskinnhold (statisk fordi ingenting endres, innholdet er alltid det samme).
Skriptspråk gjør det mulig å produsere ikke-statiske nettsider,dynamisk, det vil si hvis innhold kan variere i henhold til forskjellige forhold (og spesielt brukerens handlinger).
Det er klientsidespråk (for øyeblikket er det viktigste JavaScript) og serversidespråk.
PHPer et kjent eksempel på et programmeringsspråk som kjører på serversiden. Dette språket gjør det mulig å produsere kode, synlig for kunden, som kan variere etter definerte omstendigheter, som derfor introduserer en viss dynamikk. Denne dynamikken kan økes takket være en tilkobling til en database (PostGreSQL, MySQL, SQLite, etc.).
Kilde: Marlene Villanova
Figuren ovenfor (også presentert i lysbildene fra den første leksjonen) presenterer arkitekturen som kobler et programmeringsspråk og en database for å generere dynamisk innhold på serveren under en forespørsel fra en klient (nettleser): dette er hva vi skal implementere i de neste 2 laboratoriene.
Vi vil ikke bruke PHP-språket, men Python-språket medmikro-rammeverk Kolbe
.
Det er mangerammerav programmeringserverNett på en rekke språk, for eksempel:
- i PHP:
laravel
,Symfoni
, - en Python:
Django
,Kolbe
,cherry.py
- i JavaScript med node.js:
Express.js
, - i java:
Vår
, ... - en Ruby:
Ruby on Rails
, ...
ProgramvareApache HTTP-server
etNGINX
er også HTTP-servere.
På samme måte er det forskjelligeklienter, som du allerede bruker eller kjenner for noen siden det er spesielt nettlesere:
Chrome
,Firefox
,Microsoft Edge
, etc.- På kommandolinjen:
curL
,Wget
- Biblioteker tilbyr å gjøre HTTP-forespørsler på de fleste programmeringsspråk (
forespørsler
ethttpx
i Python for eksempel)
1.2 HTTP-protokollen
I den første leksjonen nevnte vi HTTP-protokollen (forHypertext Transfer Protocol, bokstavelig talt "hypertekstoverføringsprotokoll"). Dette er enklient-server kommunikasjonsprotokoll(plassert på "applikasjonsnivået" til den lagdelte modellen presentert ved denne anledningen og hvis illustrasjon er tilbakekalt nedenfor).
HTTP-protokollen definerer fleremetoder. En metode er en kommando som spesifiserer til serveren enspørringstype, og ber den om å utføre en bestemt handling på ressursen pekt på av URL-en som følger med denne metoden.
Metodene som vil bli brukt i denne serien med laboratorier er følgende (disse er også de mest brukte):
FÅ
: metode for å be om en ressurs (en forespørselFÅ
har ingen effekt på ressursen, du kan gjenta den og få samme resultat), dette er metoden som brukes når du for eksempel henter en webside.POST
: metode for å overføre data for behandling (for eksempel fra et HTML-skjema)
→ Konkret, når en HTML-side konsulteres, består det første trinnet i å hente den: en HTTP-forespørsel av typenFÅ
på url til siden utføres.
→ På samme måte, når du validerer et skjema, en HTTP-forespørsel av typenPOST
utføres på en server-url som gjør det mulig å validere og behandle skjemaet.
Disse andre metodene brukes noen ganger (spesielt når du bruker en REST-type API for de siste 3), husk navnet deres for å vite at de er HTTP-metoder hvis du støter på dem:
HODE
: metode for å be om informasjon om ressursen, uten å hente ressursen.SETTE
: metode for å erstatte eller legge til en ressurs.SLETT
: metode for å slette en ressurs.LAPP
: metode for å gjøre en delvis modifikasjon (i motsetning tilSETTE
hvem som ville erstatte den) av en ressurs.
1.3 Den røde tråden til denne TP og de følgende...
Vi ønsker å byggeen samarbeidsplattform for vurdering og vurdering av campusbygninger. Denne komplekse oppgaven kan deles inn i flere deloppgaver:
- opprette en database for å lagre denne informasjonen
- gi brukeren muligheten til å konsultere informasjonen (plassering av de vurderte bygningene og detaljer om vurderinger/anmeldelser)
- gi brukeren muligheten til å legge inn ny informasjon (legge til et notat/varsel til et sted ved å allerede ha det eller ikke)
I dag (TP7), vil vi se hvordan du organiserer serversidekoden slik at forskjellige handlinger kan utføres avhengig av forespørselstype eller banen til forespørselen(dvs. hvordan gå fra statisk innhold til dynamisk innhold)og vi vil se hvordan du brukermalerHTML.
DeTP8vil bli brukt til å lage et skjema på HTML-siden og til å behandle det på serversiden for å legge til innholdet i en databaseSQLite. Informasjonen som finnes i databasen vil bli mobilisert for å vises på klientsiden; de kan også oppdateres Vi vil da legge til et interaktivt kart på HTML-siden. Det er dette kartet som skal brukes som et grensesnitt for å legge til anmeldelser (når brukeren for eksempel klikker) samt for å vise plasseringen av anmeldelser som finnes i databasen (i form avmarkører). Dette kortet vil bruke JavaScript-kode, utført direkte i klientens nettleser. Den bygde applikasjonen kan distribueres individuelt på plattformenPythonAnywhere.
2. Kolbebiblioteket
Dette er enmikro-rammeverkdesignet for å utvikle en webapplikasjon på serversiden. Som sådan vil det gi generiske verktøy for å lage denne typen applikasjoner samtidig som den fremmer implementeringen av god praksis og begrenser skrivingen av unødvendig kode. Kvalifiseringenmikrobeskriver her flere realiteter:
- har som mål å holde kodebasen enkel, men utvidbar,
- er ikke oppfattet i valg av database,
- endelig,
Kolbe
tar seg av det viktigste (administrerer ruter og HTTP-forespørsler og muliggjør bruk avmaler), men de andre "valgfrie" oppgavene (tilkobling til en DB, autentisering, skjemaer osv.) er overlatt til utvidelser.
Kolbe
er spesielt avhengig av to biblioteker som det er nyttig å være klar over:Verktøy
(et WSGI-verktøysett) ogJinja2
(en motor avmal).
Nyttige lenker:
- Offisiell dokumentasjon av
Kolbe
:https://flask.palletsprojects.com/en/1.1.x/ - Offisiell dokumentasjon av
Jinja2
:https://jinja.palletsprojects.com/en/2.11.x/ - Offisiell dokumentasjon av
Verktøy
:https://werkzeug.palletsprojects.com/en/0.16.x/ - Liste overpluginsog ressurser til
Kolbe
:https://github.com/humiaozuzu/awesome-flask
2.1 Første trinn med Flask - Applikasjon og ruter
applikasjon
Kode:
fra flask import Flaskapp = Flask(__name__)@app.route("/route1")def root(): returner "Hei fra Flask!"
Å teste:http://mthh.pythonanywhere.com/route1
Forklaringer:
app
betyr en Flask-applikasjon;- funksjon
rot
kalles avue. Den returnerer en streng, som vil være innholdet i svaret. Som standard er svarstatusen 200, og innholdstypen er HTML, kodet i UTF-8; - linjen før funksjonen
rot
er endekoratør, brukes den her for å spesifisere URL-en som denne visningen må brukes for (itsrute). Denne dekoratøren er en metode for gjenstandenapp
, Flask-appen, opprettet ovenfor, som denne ruten passer inn i.
Ruter
Innen webutvikling kaller viruteen URL eller et sett med URLer som fører til utførelse av en gitt funksjon.
I Flask deklareres ruter via dekoratøren@app.rute
, som i eksempelet ovenfor. En rute kan parameteriseres, i så fall vil parameteren sendes til visningsfunksjonen:
@app.route("/hello/")def hello(name): returner "Hei {}".format(name)
Å teste:http://mthh.pythonanywhere.com/hello/John
Eksemplene ovenfor lar deg tilpasse svaret basert på brukerens forespørsel eller få utført beregninger på serversiden ved å dra nytte av kraften og bredden av funksjonalitet som tilbys av python og dets økosystem.
- Det er også mulig å angi flere parametere når du definerer en rute ved hjelp av skjemaet
/hei//
:
@app.route("/add//")def add(a, b): returner "Resultat: {}".format(int(a) + int(b))
Å teste:http://mthh.pythonanywhere.com/add/3/12
- Det er mulig å spesifisere forventet type for ruteparametrene; hvis de ikke er fornøyd, et svar av typen
404 IKKE FUNNET
vil bli returnert som standard:
@app.route("/add//")def add(a, b): returner "Resultat: {}".format(a + b)
Å teste:http://mthh.pythonanywhere.com/add/12/abc
Et svar404 IKKE FUNNET
vil også bli returnert hvis du prøver å få tilgang til en rute som ikke er definert (herabdef
) :
Å teste:http://mthh.pythonanywhere.com/abdef
- For enkelhets skyld er det også mulig å spesifisere flere ruter som fører til utførelse av en funksjon:
@app.route("/greetings")@app.route("/greetings/")def greetings(name=None): returner "Hei {} !".format(navn eller 'verden')
Å teste:http://mthh.pythonanywhere.com/greetings
Å teste:http://mthh.pythonanywhere.com/greetings/Paul
HTTP-metoder
Når du oppretter en rute, er det mulig å spesifisere metoden(e) som den er tilgjengelig på. I de foregående eksemplene, siden ingen metode ble spesifisert eksplisitt, var det metodenFÅ. Så vår første funksjon kunne vært skrevet som følger:
@app.route("/", methods=['GET'])def root(): returner "Hei fra Flask!"
En rute som bare godtar én metodePOSTvil bli erklært som følger:
@app.route('/valid-form', methods=['POST'])
Noen ganger kan det være nødvendig å lage ruter som godtar begge metodene. Tenk på eksempelkoden nedenfor. Veien/Oppdater
er laget for å akseptere metoderFÅetPOST:
fra flaskeimportforespørsel, render_template@app.route('/update', methods=['GET', 'POST'])def eksempel(): if request.method == 'GET': return render_template('update.html ') elif request.method == 'POST': # traitement des données envoyées ... return 'Entry updated' !
- Hvis det er en forespørsel av typenFÅ, siden som tilsvarermal
update.html
vil bli returnert til kunden(vi ser for oss at den spesielt inneholder et skjema som gjør det mulig å oppdatere en oppføring i tegneserien). - Hvis det er en forespørsel av typenPOST, behandles de sendte dataene for å oppdatere oppføringen(denne handlingen tilsvarer valideringen og sendingen fra klienten av skjemaet på siden som han tidligere åpnet via ruten
/Oppdater
):
2.2 Maler
Kolbe
har en mekanisme som tillater bruk av enmodell (mal)dokument, hvorav noen deler vil bli dynamisk erstattet under kjøretid, før det sendes til klienten.
Eksemplene som er presentert så langt returnerer bare tegnstrenger. Som nevnt ovenfor er dette faktisk HTML-innhold; slik at du kan skrive ruter som returnerer riktig formatert og dynamisk generert HTML-innhold:
fra datetime import date@app.route("/pretty-add//")def pretty_add(a, b): current_date = date.today().isoformat() resultat = a + b returner """ Tillegg resultatside Resultatside
{} + {} = {}
Beregnet på {}
""".format(a, b, resultat, gjeldende_dato)
Å teste:http://mthh.pythonanywhere.com/pretty-add/12/20
Hvis denne metoden er brukbar, vil den imidlertid raskt gjøre koden vanskelig å forstå, og den letter ikke gjenbruk av kodebiter som kan være det.
Det er her interessen tilmotormalerSistnevnte vil gjøre det mulig å lagre i separate filermodellav våre HTML-sider. Ved kjøretid (med funksjonenrender_mal
presentert neste), vil modellen fullføres med parametrene som er gitt for å produsere et HTML-dokument som kan brukes av klienten.
Syntaks brukt av Jinja2
La oss ta eksempelet på ruten vårpen-add
definert ovenfor; det er mulig å definere (i en filtemplate/pretty-add.html
for eksempel) denmalfølgende:
Tilleggsresultatside < h1>Resultatside {{ a }} + {{ b }} = {{ resultat }}
Beregnet {{ current_date }}
... og omskriv funksjonen som følger:
fra Flask import render_template@app.route("/pretty-add//")def pretty_add(a, b): date_now = date.today().isoformat() resultat = a + b returner render_template('pretty-add.html', a=a, b=b, result=result, current_date=date_now)
I dette eksemplet brukte vi:
- avuttrykkene, avgrenset av symbolene
{{ ... }}
; de kan inneholde Python-uttrykk og her, når du skriver{{ resultat }}
vi søker derfor å bruke innholdet i variabelenresultat
for å vise den på HTML-siden som vil bli returnert.
Andre konstruksjoner kan brukes:
- avuttalelser (uttalelser), avgrenset med symbolene
{% ... %}
(forhold, løkker, etc.), - avkommentarer, avgrenset med symbolene
{# ... #}
.
La merke til:Funksjon
render_mal
aksepterer variablene som forventes avmal(det første argumentet) som navngitte valgfrie argumenter: vi bruker navnet på den forventede variabelen imalsom nøkkelen og variabelnavnet i gjeldende kode som verdien (gjeldende_dato=dato_nå
i forrige eksempel).
Eksempel med en løkke
Det vil dermed være mulig å bruke, imalerkomplekse Python-erklæringer samt ulike elementer som vanligvis brukes for å kontrollere utførelsesflyten til programmet. Se på koden til dettemal:
Min nettside Min nettside
Hei {{ navn }}
{# En kommentar med flere linjer #}
Forklaringer:
- Variabelen
navigasjon
er her enliste
avdikt
, de la forme
det er mulig å bruke uttalelsennavigasjon = [ {"href": "index.html", "caption": "Hjem"}, {"href": "partners.html", "caption": "Partners"}]
{% for element i navigasjon %}
som har samme effekt som en loop ved hjelp avtil
i Python - syntaksen som brukes her, krever imidlertid å lukke blokken som tilsvarer denne sløyfen med erklæringen{% endfor %}
. - Variabelen
Navn
er av typenstr
og vise den som den er. - Den siste blokken
{# ... #}
samsvarer med en kommentar; som på andre språk, bruk den om nødvendig! - De forventede variablene (her
navigasjon
etNavn
) imalskal gis som valgfrie og navngitte argumenter for funksjonenrender_mal
.
Gjenbruk av mal
La oss gå tilbake til eksemplet med sidene vi opprettet i de forrige laboratoriene: de inneholdt en navigasjonslinje og enbunntekstsom begge var ment å være de samme for hver av sidene på nettstedet.
Takk tilmekanisme å inkludereavmaler, vil vi for eksempel kunne definere gjenbrukbare elementer på nettstedet vårt i separate filer, for å inkludere dem framalsom inneholder hovedinnholdet på siden:
{% include 'header.html' %} Contenu principal de la page ici...{% include 'footer.html' %}
DEmalerkalt på denne måten har tilgang til de samme variablene sommalsom inkluderte dem.
3 - Sett det i praksis 🚀 Øvelse 1 🚀 Registrere deg for PythonAnywhere og starte et Flask-prosjekt
3.1 Registrering for PythonAnywhere
Registrering skjer på følgende URL:https://www.pythonanywhere.com/registration/register/beginner/.
Denne plattformen lar deg kjøre Python-kode på en ekstern server. Denne løsningen kan være nyttig hvis du ønsker å frigjøre deg fra begrensningene knyttet til plattformen du jobber på (operativsystem, administratorrettigheter osv.).
I vårt tilfelle vil det være nyttig fordi det gjør det mulig å være vert for en webapplikasjon (opprettet medKolbe
men også medWeb2py
ellerDjango
) og få tilgang til den på en URL til skjemaethttp://{pseudonyme}.pythonanywhere.com
.
Følg instruksjonene nedenfor for å lage en app derKolbe
vide.
- Etter registrering og innlogging på plattformen, klikk på knappen"Web":
- Klikk på "Legg til en ny nettapp"-knappen:
- Et vindu åpnes, klikk på "neste":
- Velg å brukerammeverk Kolbe:
- Velg versjonen av Python du er vant til å jobbe med:
- Ikke endre filbanen
flask_app.py
og klikk "neste":
- Applikasjonen opprettes og er tilgjengelig på URL-en
https://{pseudonyme}.pythonanywhere.com
. Klikk på "Filer"-knappen for å redigere serverkoden din:
- Bla gjennom treet til du finner denne filen. Klikk for å åpne den:
- Du kan redigere den (og lagre den ved å gjøre detctrl+sFor eksempel).
- Etter å ha redigert den, må du laste inn på nyttnettapp. Dette kan gjøres direkte fra koderedigeringssiden (bildet nedenfor) eller fra seksjonenWebav plassen dinPythonAnywhere.
🚀 Last inn appen på nytt og sjekk at alt fungerer som det skal, er nettadressen som skal brukeshttps://{pseudonyme}.pythonanywhere.com
.
La merke til:Du kan se applikasjonsfeilloggene påhttps://www.pythonanywhere.com/user/{pseudonyme}/files/var/log/{pseudonyme}.pythonanywhere.com.error.log
3.2 Første trinn med Flask og prosjektstruktur
I filenmin side
du har nå en filflask_app.py
.
Det er også nødvendig å opprette en mappe som du vil navngimaler
. I filenmaler
du vil pakke ut dagens data:TP7 data- det er 2 filer avmalerved hjelp avJinja2
.
Så du bør ha følgende prosjektstruktur:
mysite├── maler <--- Mappen som inneholder HTML-dokumentmalene våre│ ├── index.html│ └── header.html └── flask_app.py <--- Koden til nettappen som skal opprettes
4. Sette det ut i livet 🚀 Øvelse 2 🚀 Endring av applikasjonen
- Legg til følgende kodebit i filen
flask_app.py
, dette er de første dummyvurderingene som skal brukes før vi bygger databasen i følgende laboratorie:
entries = [ {"id_review": 1, "id_batiment": 26, "rate": 5, "comment": "Mattis molestie a aculis at erat pellentesque adipiscing commodo."}, {"id_review": 2, "id_batiment" : 18, "rate": 4, "comment": "Amet massa vitae tortor saus lacinia."}, {"id_review": 3, "id_batiment": 31, "rate": 3, "comment": "Men ytelse hvis du ikke har en myk porta lore."}, {"id_review": 4, "id_batiment": 22, "rate": 1, "comment": "For den er verdig å bli forgiftet. Urna cursus trenger nå chocolate."}, { "id_review": 5, "id_batiment": 26, "rate": 4, "comment": "A pellentesque sit amet porttitor eget pain morbi."}, {"id_review": 6, "id_batiment ": 18, "rate ": 3, "comment": "Opnår spillerne eller prisen på sengen enn den gangen i livet."},]
Ved å bruke eksemplene vist i begynnelsen av denne labøkten, må du endre den eksisterende ruten slik at ruten
/
og veien/indeks
begge kaller funksjonenrot
. Denne funksjonen bør brukemalindex.html
. Du må også åpne denne filen framalfor å se variablene som forventes og som du må gi som argument til funksjonenrender_mal
.Du må opprette en ny rute med navn
/anmeldelse
må godta et argument av typenint
, identifikatoren for den mening brukeren ønsker å få. Du må også skrive den tilsvarende funksjonen: for en gitt identifikator må den returnere vurderingen og anmeldelsen som en tekstblokk formatert på en enkel måte(for eksempel: "Merk X - Kommentar: xxxxx"). Hvis ingen anmeldelse samsvarer med identifikatoren, returnerer den en tom tegnstreng.Sjekk følgende punkter i nettleseren din før du fortsetter til følgende øvelse:
- veier
/
et/indeks
arbeid og returner det samme innholdet (se bilde). - veien
/anmeldelse
returnerer en feil404 IKKE FUNNET
mens veien/anmeldelse/2
returnerer innholdet i det tilsvarende varselet.
5. Sett det i praksis 🚀 Øvelse 3 🚀 Bruke maler
- I tillegg til å vise antall anmeldelser som finnes i databasen, ønsker vi å vise hele listen over anmeldelser på hjemmesiden. Du må endremal
index.html
for å dynamisk lage en HTML-liste der hvert element vil tilsvare en gjennomgang avliste
Python ringteinnganger
. Et lignende eksempel ble gittici.