This shows you the differences between two versions of the page.
ii:lab:laborator5 [2021/01/09 01:01] eduard.staniloiu |
ii:lab:laborator5 [2021/01/20 08:51] (current) florin.stancu [Exerciții] |
||
---|---|---|---|
Line 32: | Line 32: | ||
</code> | </code> | ||
+ | |||
+ | <note important> | ||
+ | Dacă nu vă merge (diferite setup-uri), încercați una dintre comenzile echivalente: | ||
+ | <code bash> | ||
+ | pip3 install ... # pip pentru python3, dacă este aliasat | ||
+ | python3 -mpip install ... # pentru python3 | ||
+ | |||
+ | python -mpip install ... # pentru python2 | ||
+ | </code> | ||
+ | </note> | ||
===== Hello World ===== | ===== Hello World ===== | ||
Line 191: | Line 201: | ||
După ce am făcut modificările, accesăm pagina [[http://127.0.0.1:5000]]. | După ce am făcut modificările, accesăm pagina [[http://127.0.0.1:5000]]. | ||
+ | |||
+ | |||
+ | ==== Structuri de control ==== | ||
+ | |||
+ | În cadrul template-urilor Jinja putem folosi și structuri de control precum **if** și **for**. | ||
+ | Sintaxa pentru acestea este următoarea: | ||
+ | |||
+ | <code html> | ||
+ | |||
+ | <html> | ||
+ | <head> | ||
+ | {% if title %} | ||
+ | <title>{{ title }}</title> | ||
+ | {% else %} | ||
+ | <title>Welcome</title> | ||
+ | {% endif %} | ||
+ | </head> | ||
+ | <body> | ||
+ | {% for user in users %} | ||
+ | <div><p>{{ user.username }}</p></div> | ||
+ | {% endfor %} | ||
+ | </body> | ||
+ | </html> | ||
+ | |||
+ | </code> | ||
+ | |||
+ | <note tip> | ||
+ | |||
+ | În cadrul **{****{** ... **}****}** folosim cod python. | ||
+ | |||
+ | </note> | ||
+ | |||
+ | ==== Extinderea unor template-uri de bază ==== | ||
+ | |||
+ | Majoritatea paginilor unei aplicații web conțin componente comune (cum ar fi bara de navigație). | ||
+ | Pentru a evita scrierea repetată a componentelor comune în fiecare pagină, putem folosi **template inheritance**: componentele comune sunt scrise într-un template de bază care este apoi extins de fiecare pagină. | ||
+ | |||
+ | Pentru aceasta, în directorul **~/hello-flask/templates** definim fișierul **base.html**, ca mai jos: | ||
+ | |||
+ | <code html base.html> | ||
+ | |||
+ | <html> | ||
+ | <head> | ||
+ | {% if title %} | ||
+ | <title>{{ title }}</title> | ||
+ | {% else %} | ||
+ | <title>Welcome</title> | ||
+ | {% endif %} | ||
+ | </head> | ||
+ | <body> | ||
+ | <div><a href="/index">Home</a></div> | ||
+ | <hr> | ||
+ | {% block content %}{% endblock %} | ||
+ | </body> | ||
+ | </html> | ||
+ | |||
+ | </code> | ||
+ | |||
+ | Fișierul template de mai sus este acum baza noastră. | ||
+ | El definește structura generală a paginii. | ||
+ | Orice pagină nouă o să extindă această bază și apoi trebuie să definească doar blocul **content**. | ||
+ | |||
+ | Astfel, modificăm fișierul **~/hello-flask/templates/index.html** ca mai jos: | ||
+ | |||
+ | <code html index.html> | ||
+ | |||
+ | {% extends "base.html" %} | ||
+ | |||
+ | {% block content %} | ||
+ | <h1>Hello, {{ user.username }}!</h1> | ||
+ | {% endblock %} | ||
+ | |||
+ | </code> | ||
+ | |||
+ | ===== Bootstrap ===== | ||
+ | |||
+ | [[https://getbootstrap.com/docs/5.0/getting-started/introduction/|Bootstrap]] este un framework foarte popular folosit pentru a crea interfețe cu utilizatorul (UI). | ||
+ | |||
+ | Pentru a folosi **Bootstrap**, adăugăm următoarele linii în fișierul **base.html** | ||
+ | |||
+ | <code html base.html> | ||
+ | |||
+ | <html> | ||
+ | <head> | ||
+ | <meta charset="utf-8"> | ||
+ | <meta name="viewport" content="width=device-width, initial-scale=1"> | ||
+ | |||
+ | <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous"> | ||
+ | <link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.3.0/font/bootstrap-icons.css" rel="stylesheet"> | ||
+ | |||
+ | <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.5.4/dist/umd/popper.min.js" crossorigin="anonymous"></script> | ||
+ | <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/js/bootstrap.min.js" crossorigin="anonymous"></script> | ||
+ | |||
+ | {% if title %} | ||
+ | <title>{{ title }}</title> | ||
+ | {% else %} | ||
+ | <title>Welcome</title> | ||
+ | {% endif %} | ||
+ | </head> | ||
+ | <body> | ||
+ | <div><a href="/index">Home</a></div> | ||
+ | <hr> | ||
+ | {% block content %}{% endblock %} | ||
+ | </body> | ||
+ | </html> | ||
+ | |||
+ | </code> | ||
+ | |||
+ | Acum putem folosi Bootstrap pentru a ne înfrumuseța pagina. | ||
+ | Începem prin a centra textul din fișierul **index.html**: | ||
+ | |||
+ | <code html index.html> | ||
+ | |||
+ | {% extends "base.html" %} | ||
+ | |||
+ | {% block content %} | ||
+ | <h1 class="text-center">Hello, {{ user.username }}!</h1> | ||
+ | {% endblock %} | ||
+ | |||
+ | </code> | ||
+ | |||
+ | Observăm că a fost necesar doar să adăugăm clasa **text-center** elementului **h1**. | ||
+ | Acesta este modul de funcționare Bootstrap: tot ce trebuie făcut este să includem elementele în clasa pe care ne-o dorim. | ||
+ | |||
+ | Bootstrap împarte (imaginar) pagina în 12 [[https://getbootstrap.com/docs/5.0/layout/grid/|coloane]]. | ||
+ | Noi apoi decidem, prin intermediul atributului **class**, [[https://getbootstrap.com/docs/5.0/layout/grid/|câte din aceste coloane vor ocupa elementele noastre]]. | ||
+ | |||
+ | De exemplu: | ||
+ | |||
+ | <code html> | ||
+ | |||
+ | <div class="container"> | ||
+ | <div class="row"> | ||
+ | <div class="col-sm"> | ||
+ | One of three columns | ||
+ | </div> | ||
+ | <div class="col-sm"> | ||
+ | One of three columns | ||
+ | </div> | ||
+ | <div class="col-sm"> | ||
+ | One of three columns | ||
+ | </div> | ||
+ | </div> | ||
+ | </div> | ||
+ | |||
+ | </code> | ||
+ | |||
+ | Exemplul de mai sus va împărți lățimea rândului în mod egal între cele trei coloane. | ||
+ | |||
+ | ==== Bootstrap Icons ==== | ||
+ | |||
+ | Bootstrap ne oferă și un set de imagini SVG pe care le putem folosi pe post de [[https://icons.getbootstrap.com/|icons]]. | ||
+ | |||
+ | Ca să înlocuim textul **Home** din fișierul **base.html** cu un icon, trebuie să: | ||
+ | * identificăm icon-ul unei [[https://icons.getbootstrap.com/icons/house/|case]] | ||
+ | * înlocuim textul **Home** cu textul din **Icon font**. | ||
+ | |||
+ | Astfel, textul | ||
+ | |||
+ | <code html> | ||
+ | <div><a href="/index">Home</a></div> | ||
+ | </code> | ||
+ | | ||
+ | Devine | ||
+ | | ||
+ | <code html> | ||
+ | <div><a href="/index"><i class="bi bi-house"></i></a></div> | ||
+ | </code> | ||
+ | |||
+ | |||
+ | ===== Exerciții ===== | ||
+ | |||
+ | O să scrieți o aplicație web care are rolul unui CV. | ||
+ | CV-ul trebuie să conțină secțiunile: Work Experience, Education, Projects și Languages and Technologies | ||
+ | |||
+ | 1. **[10]** Aplicația trebuie să aibă două pagini: Home (CV-ul) și Contact | ||
+ | |||
+ | 2. **[30]** Informațiile secțiunilor din CV sunt populate de către server, și nu sunt scrise în template-ul Jinja. | ||
+ | Informațiile secțiunilor sunt stocate sub formă de dicționar. | ||
+ | De exemplu: | ||
+ | <code python> | ||
+ | work_exp = [ { position: "swe", company: "xyz", period: "Jun 2020 - Oct 2020" } ] | ||
+ | </code> | ||
+ | |||
+ | 3. **[10]** Folosiți icon-uri pentru Home și Contact | ||
+ | |||
+ | 4. **[20]** Folosiți componenta Bootstrap [[https://getbootstrap.com/docs/5.0/components/navbar/|Navbar]] pentru butoanele Home și Contact | ||
+ | |||
+ | 5. **[30]** Pagina de contact trebuie să conțină și un formular prin intermediul căruia un utilizator să vă poată contacta. | ||
+ | Formularul trebuie să conțină câmpurile: Nume, Adresă de e-mail și Mesaj. | ||
+ | Atunci când utilizatorul apasă butonul **Trimite** al formularului, serverul flask vă va //[simula că]// trimite un e-mail cu informațiile formularului prin scrierea unui fișier pe server (e.g., ''contact-mail.txt''). |