Lista ToDo Aplikacja internetowa



Podobne dokumenty
Quiz Aplikacja internetowa

Chatter Aplikacja internetowa

Laboratorium 7 Blog: dodawanie i edycja wpisów

Projektowanie aplikacji w modelu MVC opartej o framework CodeIgniter

Laboratorium 6 Tworzenie bloga w Zend Framework

Dzięki arkuszom zewnętrznym uzyskujemy centralne sterowanie wyglądem serwisu. Zewnętrzny arkusz stylów to plik tekstowy z rozszerzeniem css.

Bazy danych i strony WWW

Zaawansowany kurs języka Python

Laboratorium nr 4. Temat: SQL część II. Polecenia DML

Tomasz Grześ. Systemy zarządzania treścią, cz. II

Wykład 5: PHP: praca z bazą danych MySQL

Język SQL, zajęcia nr 1

Podstawowe wykorzystanie Hibernate

Danuta ROZPŁOCH-NOWAKOWSKA Strona Moduł 4. Przykład 1. Przykład 2. HTML 4.01 Transitional).

Podstawy technologii WWW

Bazy Danych i Usługi Sieciowe

znaleźć wszystkie rekordy dotyczące adresów przy ulicy Hożej (dowolnego miasta!);

CSS. Kaskadowe Arkusze Stylów

ASP.NET MVC. Podstawy. Zaawansowane programowanie internetowe Instrukcja nr 3

Modele danych walidacja widoki zorientowane na model

koledzy, Jan, Nowak, ul. Niecała 8/23, , Wrocław, , ,

Wdrożenie modułu płatności eservice. dla systemu Zen Cart

Specyfikacja instalacji usługi SMS Premium w Przelewy24.pl

Oracle Application Express

Wykład 5. SQL praca z tabelami 2

Budowa aplikacji ASP.NET współpracującej z bazą dany do przeprowadzania ankiet internetowych

1. Połączenie z bazą danych. W wybranym edytorze tworzymy plik sqltest.py i umieszczamy w nim poniższy kod. #!/usr/bin/python3 import sqlite3

Budowa aplikacji ASP.NET współpracującej z bazą dany do przeprowadzania ankiet internetowych

Dokumentacja Skryptu Mapy ver.1.1

Wydział Elektrotechniki, Informatyki i Telekomunikacji Instytut Informatyki i Elektroniki

Bazy danych. Polecenia SQL

Bazy danych. Wykład IV SQL - wprowadzenie. Copyrights by Arkadiusz Rzucidło 1

PLAN WYNIKOWY PROGRAMOWANIE APLIKACJI INTERNETOWYCH. KL IV TI 6 godziny tygodniowo (6x15 tygodni =90 godzin ),

Aplikacje internetowe - laboratorium

Referat z przedmiotu Technologie Internetowe SPIS TREŚCI

Dokumentacja REST API v 3.0. Kraków, 7 marca FreshMail, ul. Fabryczna 20a, Kraków tel , freshmail.

Dokumentacja systemu NTP rekrut. Autor: Sławomir Miller

Ćwiczenia laboratoryjne nr 11 Bazy danych i SQL.

Backend Administratora

PROGRAMOWANIE. WNPiD UAM, Programowanie, inż. Piotr Jabłoński

Sprawdzenie czy połączenie przebiegło poprawnie if (mysqli_connect_errno()) { echo Błąd; Połączenie z bazą danych nie powiodło się.

Specyfikacja HTTP API. Wersja 1.6

Budowa aplikacji ASP.NET współpracującej z bazą dany do obsługi przesyłania wiadomości

Systemy baz danych Prowadzący: Adam Czyszczoń. Systemy baz danych. 1. Import bazy z MS Access do MS SQL Server 2012:

Aplikacje internetowe

PHP: bazy danych, SQL, AJAX i JSON

Programowanie w Ruby

Źródła. cript/1.5/reference/ Ruby on Rails: AJAX: ssays/archives/

Podstawy (X)HTML i CSS

app/ - folder zawiera pliki konfiguracyjne dla całej aplikacji src/ - folder zawiera cały kod PHP aplikacji

Laboratorium nr 3 Podstawy Ruby on Rails

Aplikacje WWW - laboratorium

DECLARE VARIABLE zmienna1 typ danych; BEGIN

Wdrożenie modułu płatności eservice. dla systemu oscommerce 2.3.x

Programowanie w SQL procedury i funkcje. UWAGA: Proszę nie zapominać o prefiksowaniu nazw obiektów ciągiem [OLIMP\{nr indeksu}] Funkcje użytkownika

Programowanie w Ruby

Wdrożenie modułu płatności eservice. dla systemu Magento

Oczywiście występują także znaczniki, bez ich odpowiednika kończącego, np. <BR>

Aktualizacja SMSFall v Data publikacji:

Wprowadzenie do JDBC z wykorzystaniem bazy H2

Portal SRG BFG. Instrukcja korzystania z Portalu SRG BFG

Budowa aplikacji ASP.NET współpracującej z bazą dany do obsługi przesyłania wiadomości

Aplikacje WWW - laboratorium

Zdefiniowane style mogą określać układ treści na stronie i sposób jej formatowania np. kolor czcionki, pogrubienia, tło tabel, rysunków itp.

app/ - folder zawiera pliki konfiguracyjne dla całej aplikacji Można wybrać sposób zapisu konfiguracji: YML, XML, PHP

Ajax. 1. Wprowadzenie. 2. Aplikacja serwerowa

Języki skryptowe - PHP. PHP i bazy danych. Paweł Kasprowski. pawel@kasprowski.pl. vl07

Programowanie w Ruby

Wdrożenie modułu płatności eservice. dla systemu Gekosale 1.4

Aplikacje WWW - laboratorium

Przykład integracji kalkulatora mbank RATY na platformie IAI

Programowanie i projektowanie obiektowe

Spis treści. Wstęp 5 Rozdział 1. Praca z AJAX-em 9. Rozdział 2. Współpraca ze skryptami PHP 55. Rozdział 3. Obsługa formularzy 81

Dokumentacja smsapi wersja 1.4

E.14 Bazy Danych cz. 18 SQL Funkcje, procedury składowane i wyzwalacze

Języki programowania wysokiego poziomu. PHP cz.4. Bazy danych

Java Server Faces narzędzie do implementacji w wy prezentacji

Krótki przegląd własności języka CSS

2. Prezentacja wizualna

MasterEdytor. Podprogram pomocniczy do programu mpfotoalbum 1.2 INSTRUKCJA

Integracja frameworku Wicket z serwisem Platnosci.pl.

Gerard Frankowski, Zespół Bezpieczeństwa PCSS. Nowoczesne technologie bliżej nas Poznań,

29. Poprawność składniowa i strukturalna dokumentu XML

Dokumentacja interfejsu MySQL. Platforma BSMS.PL Instrukcja podłączenia po przez mysql

Autor: Joanna Karwowska

Aby uruchomić program klienta i połączyć się z serwerem, należy komendę:

CREATE DATABASE ksiegarnia_internetowa DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;

Programowanie w Ruby

Specyfikacja techniczna. mprofi Interfejs API

REFERAT O PRACY DYPLOMOWEJ

Internetowe bazy danych

Aplikacje WWW - laboratorium

Portal SRG BFG Instrukcja korzystania z Portalu SRG BFG

Laboratorium Kierunki Rozwoju oprogramowania REST, Django

Aplikacje webowe w obliczu ataków internetowych na przykładzie CodeIgniter Framework

Instrukcja importu dokumentów z programu Fakt do programu Płatnik

Podstawy HTML i CSS. Wydział Matematyki, Informatyki i Ekonometrii Uniwersytet Zielonogórski

Pierwsza strona internetowa

Aplikacje internetowe - laboratorium

Transkrypt:

- 1 - Lista ToDo Aplikacja internetowa Opis: Realizacja prostej listy ToDo (lista zadań do zrobienia), jako aplikacji internetowej, z wykorzystaniem Pythona i frameworka Flask w wersji 0.10.1. Autorzy: Tomasz Nowacki, Robert Bednarz Czas realizacji: 90 min Poziom trudności: Poziom 2 Spis treści Lista ToDo Aplikacja internetowa...1 I. Katalog, plik i przeznaczenie aplikacji...2 Terminal I.1...2 II. Szkielet aplikacji...2 Kod II.1...2 III. Definiowanie widoków...3 Kod III.1...3 IV. Model bazy danych...3 Kod IV.1...3 Terminal IV.1...3 V. Połączenie z bazą danych...4 Kod V.1...4 VI. Pobieranie i wyświetlanie danych...5 Kod VI.1...5 Kod VI.2...5 VII. Formularz dodawania zadań...6 Kod VII.1...6 Kod VII.2...7 VIII. Wygląd aplikacji (opcja)...8 Kod VIII.1...8 Kod VIII.2...9 IX. Oznaczanie zadań jako wykonane (opcja)...9 Kod IX.1...9 Kod IX.2...10 Zadania dodatkowe:...11

- 2 - I. Katalog, plik i przeznaczenie aplikacji Zaczynamy od utworzenia katalogu projektu ToDo, w którym zamieścimy wszystkie pliki niezbędne do realizacji tej implementacji. W katalogu użytkownika tworzymy nowy katalog todo, a w nim plik todo.py: ~ $ mkdir todo; cd todo; touch todo.py Terminal I.1 Nasza aplikacja ma pozwalać na dodawanie z określoną datą, przeglądanie i oznaczanie jako wykonane różnych zadań, które zapisywane będą w bazie danych SQLite. II. Szkielet aplikacji Utworzenie minimalnej aplikacji Flask pozwoli na uruchomienie serwera deweloperskiego, umożliwiającego wygodne rozwijanie kodu. W pliku todo.py wpisujemy: # -*- coding: utf-8 -*- # todo/todo.py Kod II.1 from flask import Flask app = Flask( name ) if name == ' main ': app.run(debug=true) Serwer uruchamiamy komendą: python todo.py Domyślnie serwer uruchamia się pod adresem 127.0.0.1:5000. Po wpisaniu adresu do przeglądarki internetowej otrzymamy stronę z błędem HTTP 404, co wynika z faktu, że nasza aplikacja nie ma jeszcze zdefiniowanego żadnego zachowania (widoku) dla tego adresu. W uproszczeniu możemy widok utożsamiać z pojedynczą stroną w ramach aplikacji internetowej.

III. Definiowanie widoków - 3 - W pliku todo.py umieścimy funkcję index(), domyślny widok naszej strony: # -*- coding: utf-8 -*- # todo/todo.py Kod III.1 from flask import Flask app = Flask( name ) # dekorator laczacy adres glowny z widokiem index @app.route('/') def index(): return 'Hello, SWOI' if name == ' main ': app.run(debug=true) Widok index() za pomocą dekoratora związaliśmy z adresem głównym (/). Po odświeżeniu adresu 127.0.0.1:5000 zamiast błędu powinniśmy zobaczyć napis: "Hello, SWOI" IV. Model bazy danych W katalogu aplikacji tworzymy plik schema.sql, który zawiera opis struktury tabel z zadaniami. Do tabel wprowadzimy przykładowe dane. -- todo/schema.sql Kod IV.1 -- tabela z zadaniami drop table if exists entries; create table entries ( id integer primary key autoincrement, -- unikalny indentyfikator title text not null, -- opis zadania do wykonania is_done boolean not null, -- informacja czy zadania zostalo juz wykonane created_at datetime not null -- data dodania zadania ); -- pierwsze dane insert into entries (id, title, is_done, created_at) values (null, 'Wyrzucić śmieci', 0, datetime(current_timestamp)); insert into entries (id, title, is_done, created_at) values (null, 'Nakarmić psa', 0, datetime(current_timestamp)); Tworzymy bazę danych w pliku db.sqlite, łączymy się z nią i próbujemy wyświetlić dane, które powinny były zostać zapisane w tabeli entries: sqlite3 db.sqlite < schema.sql sqlite3 db.sqlite select * from entries; Terminal IV.1

- 4 - Połączenie z bazą zamykamy poleceniem.quit. V. Połączenie z bazą danych W pliku todo.py dodajemy: # -*- coding: utf-8 -*- # todo/todo.py Kod V.1 # importujemy biblioteki potrzebne do nawiązania połączenia z baza import os import sqlite3 from flask import Flask, g app = Flask( name ) # konfiguracja aplikacji app.config.update(dict( # nieznany nikomu sekret dla mechanizmu sesji SECRET_KEY = 'bardzosekretnawartosc', # polozenie naszej bazy DATABASE = os.path.join(app.root_path, 'db.sqlite'), # nazwa aplikacji SITE_NAME = 'Moja lista ToDo' )) def connect_db(): """Nawiazywanie polaczenia z baza danych okreslona w konfiguracji.""" rv = sqlite3.connect(app.config['database']) rv.row_factory = sqlite3.row return rv def get_db(): """Funkcja pomocnicza, ktora tworzy polaczenia z baza przy pierwszym wywolaniu i umieszcza ja w kontekscie aplikacji (obiekt g). W kolejnych wywolaniach zwraca polaczenie z kontekstu.""" if not hasattr(g, 'db'): g.db = connect_db() # jezeli kontekst nie zawiera informacji o polaczeniu to je tworzymy return g.db # zwracamy polaczenie z baza # dekorator wykonujacy funkcje po wyslaniu odpowiedzi do klienta @app.teardown_request

def close_db(error): """Zamykanie polaczenia z baza.""" if hasattr(g, 'db'): g.db.close() # dekorator laczacy adres glowny z widokiem index @app.route('/') def index(): return 'Hello, SWOI' if name == ' main ': app.run(debug=true) - 5 - Dodaliśmy sekretny klucz zabezpieczający mechanizm sesji, ustawiliśmy ścieżkę do pliku bazy danych (w katalogu aplikacji, dlatego funkcja app.root_path) oraz nazwę aplikacji. Utworzyliśmy trzy funkcje odpowiedzialne za nawiązywanie (connect_db, get_db) i kończenie (close_db) połączenia z bazą danych. VI. Pobieranie i wyświetlanie danych Wyświetlanie danych umożliwia wbudowany we Flask system szablonów (templatek), czyli mechanizm renderowania kodu HTML na podstawie plików zawierających kod wstawiający wybrane dane z aplikacji oraz znaczniki HTML. Modyfikujemy funkcję index() w pliku todo.py: # dodajemy nowe importy do pozostalych from flask import render_template Kod VI.1 # dekorator laczacy adres glowny z widokiem index @app.route('/') def index(): db = get_db() # laczymy sie z baza # pobieramy wszystkie wpisy z bazy: cur = db.execute('select id, title, is_done, created_at from entries order by created_at desc;') entries = cur.fetchall() # renderujemy tempaltke i zwracamy ja do klienta return render_template('show_entries.html', entries=entries) W widoku index() pobieramy obiekt bazy danych (db) i wykonujemy zapytanie (select...), by wyciągnąć wszystkie zapisane zadania. Na koniec renderujemy szablon przekazując do niej pobrane zadania (entries). Szablon, czyli plik show_entries.html, umieszczamy w podkatalogu templates aplikacji. Poniżej jego zawartość: Kod VI.2 <!-- todo/templates/show_entries.html --> <html> <head> <!-- automatycznie przekazana informacja z konfiguracji aplikacji --> <title>{{ config.site_name }}</title> </head>

- 6 - <body> <h1>{{ config.site_name }}:</h1> <ol> <!-- wypisujemy kolejno wszystkie zdania --> {% for entry in entries %} <li> {{ entry.title }}<em>{{ entry.created_at }}</em> </li> {% endfor %} </ol> </body> </html> Wewnątrz szablonu przeglądamy wszystkie wpisy (entries) i umieszczamy je na liście HTML. Do szablonu automatycznie przekazywany jest obiekt config (dane konfiguracyjne), z którego pobieramy tytuł strony (SITE_NAME). Po odwiedzeniu strony 127.0.0.1:5000 powinniśmy zobaczyć listę zadań. VII. Formularz dodawania zadań Aby umożliwić dodawanie i zapisywanie w bazie nowych zadań, modyfikujemy widok index(), tak aby obsługiwał żądania POST, które zawierają dane wysłane z formularza na serwer. # dodajemy importy from datetime import datetime from flask import flash, redirect, url_for, request # dekorator laczacy adres glowny z widokiem index # poza powiazaniem adresu / z funkcja index, dodajemy mozliwosc akcpetacji # zadan HTTP POST (domyslnie dozwolone sa tyko zadania GET) @app.route('/', methods=['get', 'POST']) def index(): """Glowny widok strony. Obsluguje wyswietlanie i dodawanie zadan.""" # zmienna przechowujaca informacje o ewentualnych bledach error = None Kod VII.1 # jezeli otrzymujemy dane POST z formularza, dodajemy nowe zadanie if request.method == 'POST': if len(request.form['entry']) > 0: # sprawdzamy poprawnosc przeslanych danych db = get_db() # nawiazujemy polaczenie z baza danych new_entry = request.form['entry'] # wyciagamy tresc zadania z przeslanego formularza is_done = '0' # ustalamy, ze nowo dodane zadanie nie jest jeszcze wykonane

created_at = datetime.now() # data dodania # zapytanie do bazy, ktore wstawia nowy wiersz z danymi db.execute('insert into entries (title, is_done, created_at) values (?,?,?);', [new_entry, is_done, created_at]) db.commit() # wykonujemy zapytanie flash('dodano nowe zadanie') # informacja o pomyslnym dodaniu nowego zadania return redirect(url_for('index')) # przekierowujemy na strone glowna error = u'nie możesz dodać pustego zadania' # komunikat o bledzie - 7 - db = get_db() # laczymy sie z baza # pobieramy wszystkie wpisy z bazy: cur = db.execute('select id, title, is_done, created_at from entries order by created_at desc;') entries = cur.fetchall() # renderujemy tempaltke i zwracamy do klienta: return render_template('show_entries.html', entries=entries, error=error) Wpisując adres w polu adresu przeglądarki, wysyłamy do serwera żądanie typu GET, które obsługujemy zwracając klientowi odpowiednie dane (listę zadań). Natomiast żądania typu POST są wykorzystywane do zmiany informacji na serwerze (np. dodania nowego wpisu). Dlatego widok index() rozszerzyliśmy o sprawdzanie typu żądania, w razie wykrycia danych POST, sprawdzamy poprawność danych przesłanych z formularz i jeżeli są poprawne, dodajemy nowe zadanie do bazy. W przeciwnym razie zwracamy użytkownikowi informację o błędzie. Szablon show_entries.html aktualizujemy, dodając odpowiedni formularz: <!-- todo/templates/show_entries.html --> <html> <head> <title>{{ config.site_name }}</title> </head> <body> <h1>{{ config.site_name }}:</h1> Kod VII.2 <!-- formularz dodawania zadania --> <form class="add-form" method="post" action="{{ url_for('index') }}"> <input name="entry" value=""/> <button type="submit">dodaj zadanie</button> </form> <!-- informacje o sukcesie lub bledzie --> <p> {% if error %} <strong class="error">błąd: {{ error }}</strong> {% endif %} {% for message in get_flashed_messages() %} <strong class="success">{{ message }}</strong> {% endfor %} </p>

- 8 - </body> </html> <ol> {% for entry in entries %} <li> {{ entry.title }}<em>{{ entry.created_at }}</em> </li> {% endfor %} </ol> W szablonie dodaliśmy formularz oraz informację o błędzie lub sukcesie przy próbie dodawania zadania. Określając atrybut action w formularzu, skorzystaliśmy z wbudowanej funkcji url_for, która zamienia nazwę widoku (w tym wypadku index) na odpowiadający jej adres URL (w tym wypadku /). W ten sposób łączymy formularz z konkretną funkcją Pythonową (widokiem), a nie z adresem URL. VIII. Wygląd aplikacji (opcja) Wygląd aplikacji możemy zdefiniować w arkuszu stylów CSS o nazwie style.css, który zapisujemy w podkatalogu static aplikacji: /* todo/static/style.css */ body { margin-top: 20px; } h1, p { margin-left: 20px; }.add-form { margin-left: 20px; } ol { text-align: left; } em { font-size: 11px; margin-left: 10px; } form { display: inline-block; margin-bottom: 0;} input[name="entry"] { width: 300px; } input[name="entry"]:focus { border-color: blue; border-radius: 5px; } li { margin-bottom: 5px; } button { padding: 0; Kod VIII.1

- 9 - cursor: pointer; font-size: 11px; background: white; border: none; color: blue; }.error { color: red; }.success { color: green; }.done { text-decoration: line-through; } Zdefiniowane style podpinamy do pliku show_entries.html, dodając w sekcji head wpis <link... >: Kod VIII.2 <head> <title>{{ config.site_name }}</title> <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='style.css') }}"> </head> Dzięki temu nasza aplikacja nabierze nieco lepszego wyglądu. IX. Oznaczanie zadań jako wykonane (opcja) Do każdego zadania dodamy formularz, którego wysłanie będzie oznaczało, że wykonaliśmy dane zadanie, czyli zmienimy atrybut is_done wpisu z 0 (niewykonane) na 1 (wykonane). Odpowiednie żądanie typu POST obsłuży nowy widok w pliku todo.py. W szablonie show_entries.html dodamy kod wyróżniający zadania wykonane. # todo/todo.py # dodajemy ponad definicja if main (...) # nadajemy osobny adres, oraz zezwalamy jedynie na zadania typu POST @app.route('/mark_as_done', methods=['post']) Kod IX.1

- 10 - def mark_as_done(): """Zmiana statusu zadania na wykonane.""" # z przeslanego formularza pobieramy identyfikator zadania entry_id = request.form['id'] db = get_db() # laczymy sie z baza danych # przygotowujemy zapytanie aktualizujace pole is_done zadania o danym identyfikatorze db.execute('update entries set is_done=1 where id=?', [entry_id,]) db.commit() # zapisujemy nowe dane return redirect(url_for('index')) # na koniec przekierowujemy na liste wszystkich zadan W szablonie show_entries.html modyfikujemy fragment wyświetlający listę zadań i dodajemy formularz: <ol> {% for entry in entries %} <li> <!-- dodatkowe dekoracje dla zadan zakonczonych --> {% if entry.is_done %} <span class="done"> {% endif %} Kod IX.2 }}"> value="{{ entry.id }}"/> {{ entry.title }}<em>{{ entry.created_at }}</em> <!-- dodatkowe dekoracje dla zadan zakonczonych --> {% if entry.is_done %} </span> {% endif %} <!-- formularz zmiany statusu zadania --> {% if not entry.is_done %} <form method="post" action="{{ url_for('mark_as_done') <!-- wysylamy jedynie informacje o id zadania --> <input type="hidden" name="id" <button type="submit">wykonane</button> </form> {% endif %} </li> {% endfor %} </ol> Aplikację można uznać za skończoną. Możemy dodawać zadania oraz zmieniać ich status.

Zadania dodatkowe: - 11 - Dodać możliwość usuwania zadań. Dodać mechanizm logowania użytkownika tak, aby użytkownik mógł dodawać i edytować tylko swoją listę zadań. Można rozważyć wprowadzenie osobnych list dla każdego użytkownika. Film instruktażowy: http://youtu.be/1fik9ashspo Słownik pojęć: Aplikacja program komputerowy. Baza danych program przeznaczony do przechowywania i przetwarzania danych. CSS język służący do opisu formy prezentacji stron WWW. Framework zestaw komponentów i bibliotek wykorzystywany do budowy aplikacji. GET typ żądania HTTP, służący do pobierania zasobów z serwera WWW. HTML język znaczników wykorzystywany do formatowania dokumentów, zwłaszcza stron WWW. HTTP protokół przesyłania dokumentów WWW. POST typ żądania HTTP, służący do umieszczania zasobów na serwerze WWW. Serwer deweloperski serwer używany w czasie prac nad oprogramowaniem. Serwer WWW serwer obsługujący protokół HTTP. Templatka szablon strony WWW wykorzystywany przez Flask do renderowania widoków. URL ustandaryzowany format adresowania zasobów w internecie (przykład: adres strony WWW). Widok fragment danych, który jest reprezentowany użytkownikowi. Materiały pomocnicze: 1. Strona projektu Flask http://flask.pocoo.org/ 2. Informacje o SQLite http://pl.wikipedia.org/wiki/sqlite 3. Co to jest framework? http://pl.wikipedia.org/wiki/framework 4. Co nieco o HTTP i żądaniach GET i POST http://pl.wikipedia.org/wiki/http