SlideShare uma empresa Scribd logo
1 de 46
Backend разработка
Дмитрий Смаль
Что мы научимся делать?
●

Обрабатывать GET и POST запросы

●

Выводить HTML при помощи шаблонов

●

Хранить данные в СУБД

Типичные задачи
●

Отображение списка объектов

●

Изменение (редактирование) объектов

●

Wizards: последовательности страниц
Языки и интерфейсы
Статические (+/-):
●

СС++ модули к Web серверам.

●

Java – Servlets, ApplicationServers

Динамически (+/-):
●

Perl – CGI, mod_perl, PSGI

●

PHP – mod_php, FastCGI (FPM)

●

Ruby – rack, свой сервер (mongrel)

●

Python – WSGI, свой сервер (Tornado)

●

JavaScript – свой сервер (NodeJS)
CGI
CGI
Запрос:
●

Параметры запроса – environ

●

Тело запроса – stdin

●

URI запроса – QUERY_STRING или argv[1]

Ответ:
●

Тело ответа (с заголовками) - stdout

●

Ошибки выполнения - stderr

●

HTTP код – через псевдозаголовок Status
CGI – окружение
Переменные окружения
REQUEST_METHOD – метод (GET, POST, …)
REQUEST_URI – строка запроса
QUERY_STRING - строка параметров
REMOTE_ADDR – ip адрес клиента
SCRIPT_NAME – имя текущего скрипта
HTTP_COOKIE – заголовок Cookie:
HTTP_REFERER – заголовок Referer:
CGI скрипт
#!/usr/bin/python2.7
import os
import sys
print
print
print
print

"Content-type: text/html"
"Status: 200"
""
"<h1>Hello, world!</h1>"

for k, v in os.environ.items():
print "%s = %s<br>" % (k, v)
print >> sys.stderr, "Nice to meet you"
nph - CGI скрипт
#!/usr/bin/python2.7
print
print
print
print

"HTTP/1.0 301 Found"
"Location: http://go.mail.ru/"
"Set-Cookie: name=value"
""

Как сервер определяет nph скрипт ?
●

По имени файла nph-

●

По первой строчке вывода скрипта

В чем отличие от обычных CGI ?
Обработка HTTP запросов
GET параметры
Гиперссылка
<a href=”/hello.cgi?name=me&greeting=hello”/>Hello!</a>

Переменная окружения
QUERY_STRING=name=me&greeting=hello

CGI скрипт
get_params = {}
qs = os.environ['QUERY_STRING']
for pair in qs.split('&'):
key, value = pair.split('=')
get_params[key] = value
POST параметры
Форма
<form method=”post” action=”/hello.cgi”>
<input name=”name” value=”me”/>
<input name=”greeting” value=”hi”/>
<input type=”submit”/>
</form>

Стандартный поток ввода STDIN
name=me&greeting=hello

CGI скрипт
qs = sys.stdin.read()
...
Файлы и не-ASCII
multipart/form-data
<form method=”post” action=”/hello.cgi”
enctype=”multipart/form-data”>
<input name=”name” value=”me”/>
<input name=”pic” type=”file”/>
<input type=”submit”/>
</form>

URI percent encoding
<a href=”/hello.cgi?name=%D0%B8%D0%BC%D1%8F”>привет</a>
Библиотеки CGI
#!/usr/bin/python2.7
import cgi
import cgitb
cgitb.enable()
form = cgi.FieldStorage()
if “greeting” not in form:
raise BaseException(“can't work”)
greeting = form[“greeting”]
names = form.getlist(“name”)
pic = forms[“pic”].file.read()
Обработка форм
1) Валидация (regex, code)
if not re.match('[a-z]+', form[“name”]):
raise BaseException(“panic”)

2) Очистка
story = re.sub('<[^>]+>', ' ', form[“story”])

3) Экранирование
story = form[“story”]
re.sub('<', '&lt;', story)
re.sub('>', '&gt', story)
Работа с базой данных
СУБД: таблицы
СУБД: SQL
INSERT INTO users (name, age)
VALUES ('petr', 10), ('masha', 25);
UPDATE users SET age = 10 WHERE name = 'petr';
DELETE FROM users WHERE name = 'masha';
SELECT * FROM users WHERE age > 10;
SELECT * FROM users WHERE name = 'masha';
SELECT max(age) FROM users;
SQL в python
import MySQLdb
db = MySQLdb.connect(**options)
cursor = db.cursor()
cursor.execute(“update users set age = age+1 ” 
”where name = ?”, form[“name”])
context = {}
cursor.execute(“select * from users”)
context['friends'] = cursor.fetchall()
cursor.execute(“select * from users where name = ?”,
form[“name”])
context['user'] = cursor.fetchone()
db.close()
Конфигурация
Конфигурация
1) hardcode. Настройки зашиты в код приложения
2) script. Настройки представляют собой скрипт на
целевом ЯП
3) YAML, XML, ini, Config::Apache
4) Переменные, разделение на несколько файлов
Генерация HTML страниц
Шаблонизаторы
print “<html><body><h1>” 
“%s</h1></body></html>” % name

VS

context = {
'user' : get_user(form['name']),
'friends' : get_friends(form['name'])
}
print render('tpl/home.html', context)
Шаблоны
<body>
<h1>{{ user.name }}</h1>
{% if user.sex == 'male' %}
<h2>{{ user.age }}</h2>
{% endif %}
{% for f in friends %}
<a href=”mailto:{{ f.email }}”>{{ f.name }}</a>
<p>{{ f.about|linebreaks }}</p>
{% endfor %}
</body>
Структура страницы
Подшаблоны
{% include 'inc/header.html' %}
<table><tr>
<td>{% include 'inc/left.html' %}</td>
<td> CONTENT </td>
<td>{% include 'inc/right.html' %}</td>
</tr></table>
{% include 'inc/footer.html' %}
Наследование (layouts)
<!-- base.html -->
<div>{% block header %} HEADER {% endblock %}</div>
<table><tr>
<td>LEFT</td>
<td>{% block content %} CONTENT {% endblock %}</td>
<td>RIGHT</td>
</tr></table>
<div>{% block footer %} FOOTER {% endblock %}</div>
Наследование (layouts)
<!-- page.html –->
{% extends 'base.html' %}
{% block header %}
Custom header
{% endblock %}
{% block content %}
<h1>{{ user.name }}</h1>
<div>{{ block.super }}</div>
{% endblock %}
Задача 1.
Листинг объектов
Листинг объектов
1) Параметры: фильтрация, сортировка, номер страницы
2) /images/?order=created&page=3&limit=10
3) Результат работы скрипта: список объектов для данной
страницы и paginator
4) paginator – представляет положение в списке страниц
Листинг объектов
#!/usr/bin/python
import cgi
import psycopg2
import settings
db = psycopg2.connect(**settings.db)
cursor = db.cursor()
form = cgi.FieldStorage()
order = form.getfirst('order', 'created')
if order not in ('created', 'size'):
raise BaseException('oops')
page = int(form.getfirst('page', 1))
limit = int(form.getfirst('limit', 10))
sql = 'select * from img order by %s limit %d offset %d'
% (order, limit, limit * (page – 1))
cursor.execute(sql)
Листинг объектов
context = {}
context['images'] = cursor.fetchall()
cursor.execute('select count(*) as cnt from images')
total = cursor.fetchone()[0]['cnt']
context['pager'] = calc_paginator(total, page, limit)
db.close()
print
print
print
print

“Status: 200”
“Content-Type: text/html”
“”
render('/images.html', context)
Paginator
Аргументы: total, page, limit
Результат:
{
'total': 100, 'page': 5, 'limit': 10,
'next_page': 6, 'prev_page': 4,
'next_page10': 10, 'prev_page10': 1,
'first_page':1, 'last_page': 10,
'pages' : [3, 4, 5, 6, 7]
}
Задача 2.
Изменение объекта
Изменение объекта
1) Два режима работы: отображение формы и
обновление объекта
2) Разделение по методу HTTP (GET | POST). Кеширование
запросов
3) Использование спец. параметра (action)
4) Отображение ошибок и результата действия
Изменение объекта
#!/usr/bin/python
import cgi; import psycopg2; import settings; import os
db = psycopg2.connect(**settings.db)
cursor = db.cursor()
form = cgi.FieldStorage()
if os.environ['HTTP_METHOD'] == 'POST”:
try:
cursor.execute('update users set name = ? where id = ?',
form['name'], form['id'])
redirect('/cgi-bin/object?id=%s&res=updated' % form['id'])
catch BaseException, e:
redirect('/cgi-bin/object?id=%s&fail=fail' % form['id'])
else:
context = {}
cursor.execute('select * from users where id = ?', form['id'])
context['object'] = cursor.fetchone()
render('object.html', context)
Изменение объекта
<form method=”POST” action=”/cgi-bin/object”>
{% if res %}
<p style=”color: green”>Объект обновлен:{{ res }}</p>
{% endif %}
{% if fail %}
<p style=”color: red”>Ошибка: {{ fail }}</p>
{% endif %}
<input type=”hidden” name=”id”
value=”{{ object.id }}”>
<input type=”text” name=”name”
value=”{{ object.name }}”>
<input type=”submit”>
</form>
Best Practice
1) Разделять методы GET – получение, POST – обновление
данных
2) Сообщать об ошибках и успехе
3) Коды возврата при ошибке и успехе
4) Проверять данные пользователя
а) на сервере – безопасность программы
б) на клиенте – удобство пользователя
5) Выделять неправильно введеные поля
Задача 3.
Wizard
Wizard
1) Statefull vs Stateless.
2) Как передать данные между страницами?
выбор товара → информация о клиенте
→ место доставки → подтверждение
3) Варианты:
- через URL
- через скрытые поля
- через Cookie
- через сессии
Скрытые поля
<!-- page2.html →
<form method=”POST” action=”/page3.html”>
<input type=”hidden” name=”item_id” value=”1”>
<input type=”hidden” name=”ammount” value=”4”>
<input type=”text” name=”name” value=””>
<input type=”text” name=”phone” value=””>
<input type=”submit”>
</form>
Cookie и Сессии
Cookie:
Set-Cookie: name=val; path=/; domain=domain.ru;
expires=Tue, 20 Mar 2012 11:52:54 GMT
Cookie: name=val;name2=val2;is_visited=2011-13-15

Сессии:
1) Ключ сессии – в cookie
2) Данные – на сервере (memcached, database, files)
Cookie в Python
Установка:
import Cookie
cookie = Cookie.SimpleCookie()
cookie['name'] = 'val'
cookie['name']['path'] = '/path'

Получение:
import Cookie
cookie = Cookie.SimpleCookie()
cookie.load('a=b;c=d')
for name in cookie:
print '%s => %s' % (name, cookie[name])
Достоинства CGI
1) простая концепция “скриптов”
2) стандарт – поддержка на любом хостинге
3) последовательное исполнение
Недостатки CGI
1) смешение кода и HTML → шаблонизаторы
2) повторение логики → вынесение кода в библиотеки
3) pretty urls → RewriteEngine
4) производительность (fork, exec, parse, db.connect) →
кеширование кода (FastCGI, mod_perl etc)
WSGI – pep 3333
def application(environ, start_response):
start_response('200 OK', [
('Content-Type', 'text/plain')
])
yield 'Hello Worldn'
def application(environ, start_response):
start_response('200 OK', [
('Content-Type', 'text/plain')])
return [ 'Hello Worldn' ]
Спасибо за внимание
Дмитрий Смаль, smal@corp.mail.ru

Mais conteúdo relacionado

Mais procurados

Работа с БД в Drupal 7
Работа с БД в Drupal 7Работа с БД в Drupal 7
Работа с БД в Drupal 7Eugene Fidelin
 
10 - Web-технологии. MVC фреймворки (продолжение)
10 - Web-технологии. MVC фреймворки (продолжение)10 - Web-технологии. MVC фреймворки (продолжение)
10 - Web-технологии. MVC фреймворки (продолжение)Roman Brovko
 
13 - Web-технологии. Отображение данных
13 - Web-технологии. Отображение данных13 - Web-технологии. Отображение данных
13 - Web-технологии. Отображение данныхRoman Brovko
 
Магия метаклассов
Магия метаклассовМагия метаклассов
Магия метаклассовAndrey Zakharevich
 
Web осень 2013 лекция 5
Web осень 2013 лекция 5Web осень 2013 лекция 5
Web осень 2013 лекция 5Technopark
 
Максим Щепелин. "Unittesting. Как?"
Максим Щепелин. "Unittesting. Как?"Максим Щепелин. "Unittesting. Как?"
Максим Щепелин. "Unittesting. Как?"Python Meetup
 
Продвинутое использование ActiveRecord в Yii2
Продвинутое использование ActiveRecord в Yii2Продвинутое использование ActiveRecord в Yii2
Продвинутое использование ActiveRecord в Yii2Paul Klimov
 
Профилирование и отладка Django
Профилирование и отладка DjangoПрофилирование и отладка Django
Профилирование и отладка DjangoVladimir Rudnyh
 
YiiConf: Миграции и инсталляции
YiiConf: Миграции и инсталляцииYiiConf: Миграции и инсталляции
YiiConf: Миграции и инсталляцииPaul Klimov
 
Web весна 2012 лекция 9
Web весна 2012 лекция 9Web весна 2012 лекция 9
Web весна 2012 лекция 9Technopark
 
Web осень 2013 лекция 9
Web осень 2013 лекция 9Web осень 2013 лекция 9
Web осень 2013 лекция 9Technopark
 
12 - Web-технологии. Django модели
12 - Web-технологии. Django модели12 - Web-технологии. Django модели
12 - Web-технологии. Django моделиRoman Brovko
 
I tmozg js_school
I tmozg js_schoolI tmozg js_school
I tmozg js_schoolITmozg
 
Подробная презентация JavaScript 6 в 1
Подробная презентация JavaScript 6 в 1Подробная презентация JavaScript 6 в 1
Подробная презентация JavaScript 6 в 1Vasya Petrov
 
MongoDB - About Performance Optimization, Ivan Griga - Smart Gamma
MongoDB - About Performance Optimization, Ivan Griga - Smart GammaMongoDB - About Performance Optimization, Ivan Griga - Smart Gamma
MongoDB - About Performance Optimization, Ivan Griga - Smart GammaEvgeniy Kuzmin
 
Реализация шаблонов корпоративных приложений в Magento
Реализация шаблонов корпоративных приложений в MagentoРеализация шаблонов корпоративных приложений в Magento
Реализация шаблонов корпоративных приложений в MagentoMagecom Ukraine
 
Meet Magento Belarus debug Pavel Novitsky (rus)
Meet Magento Belarus debug Pavel Novitsky (rus)Meet Magento Belarus debug Pavel Novitsky (rus)
Meet Magento Belarus debug Pavel Novitsky (rus)Pavel Novitsky
 
Web осень 2013 лекция 2
Web осень 2013 лекция 2Web осень 2013 лекция 2
Web осень 2013 лекция 2Technopark
 

Mais procurados (20)

Работа с БД в Drupal 7
Работа с БД в Drupal 7Работа с БД в Drupal 7
Работа с БД в Drupal 7
 
10 - Web-технологии. MVC фреймворки (продолжение)
10 - Web-технологии. MVC фреймворки (продолжение)10 - Web-технологии. MVC фреймворки (продолжение)
10 - Web-технологии. MVC фреймворки (продолжение)
 
13 - Web-технологии. Отображение данных
13 - Web-технологии. Отображение данных13 - Web-технологии. Отображение данных
13 - Web-технологии. Отображение данных
 
Магия метаклассов
Магия метаклассовМагия метаклассов
Магия метаклассов
 
Web осень 2013 лекция 5
Web осень 2013 лекция 5Web осень 2013 лекция 5
Web осень 2013 лекция 5
 
Максим Щепелин. "Unittesting. Как?"
Максим Щепелин. "Unittesting. Как?"Максим Щепелин. "Unittesting. Как?"
Максим Щепелин. "Unittesting. Как?"
 
Продвинутое использование ActiveRecord в Yii2
Продвинутое использование ActiveRecord в Yii2Продвинутое использование ActiveRecord в Yii2
Продвинутое использование ActiveRecord в Yii2
 
Профилирование и отладка Django
Профилирование и отладка DjangoПрофилирование и отладка Django
Профилирование и отладка Django
 
YiiConf: Миграции и инсталляции
YiiConf: Миграции и инсталляцииYiiConf: Миграции и инсталляции
YiiConf: Миграции и инсталляции
 
course js day 4
course js day 4course js day 4
course js day 4
 
Web весна 2012 лекция 9
Web весна 2012 лекция 9Web весна 2012 лекция 9
Web весна 2012 лекция 9
 
Web осень 2013 лекция 9
Web осень 2013 лекция 9Web осень 2013 лекция 9
Web осень 2013 лекция 9
 
12 - Web-технологии. Django модели
12 - Web-технологии. Django модели12 - Web-технологии. Django модели
12 - Web-технологии. Django модели
 
I tmozg js_school
I tmozg js_schoolI tmozg js_school
I tmozg js_school
 
Подробная презентация JavaScript 6 в 1
Подробная презентация JavaScript 6 в 1Подробная презентация JavaScript 6 в 1
Подробная презентация JavaScript 6 в 1
 
MongoDB - About Performance Optimization, Ivan Griga - Smart Gamma
MongoDB - About Performance Optimization, Ivan Griga - Smart GammaMongoDB - About Performance Optimization, Ivan Griga - Smart Gamma
MongoDB - About Performance Optimization, Ivan Griga - Smart Gamma
 
Javascript
JavascriptJavascript
Javascript
 
Реализация шаблонов корпоративных приложений в Magento
Реализация шаблонов корпоративных приложений в MagentoРеализация шаблонов корпоративных приложений в Magento
Реализация шаблонов корпоративных приложений в Magento
 
Meet Magento Belarus debug Pavel Novitsky (rus)
Meet Magento Belarus debug Pavel Novitsky (rus)Meet Magento Belarus debug Pavel Novitsky (rus)
Meet Magento Belarus debug Pavel Novitsky (rus)
 
Web осень 2013 лекция 2
Web осень 2013 лекция 2Web осень 2013 лекция 2
Web осень 2013 лекция 2
 

Destaque

Web весна 2013 лекция 6
Web весна 2013 лекция 6Web весна 2013 лекция 6
Web весна 2013 лекция 6Technopark
 
Web весна 2013 лекция 8
Web весна 2013 лекция 8Web весна 2013 лекция 8
Web весна 2013 лекция 8Technopark
 
Web весна 2013 лекция 9
Web весна 2013 лекция 9Web весна 2013 лекция 9
Web весна 2013 лекция 9Technopark
 
Михаил Давыдов: JavaScript. Базовые знания
Михаил Давыдов: JavaScript. Базовые знанияМихаил Давыдов: JavaScript. Базовые знания
Михаил Давыдов: JavaScript. Базовые знанияYandex
 
Web весна 2013 лекция 2
Web весна 2013 лекция 2Web весна 2013 лекция 2
Web весна 2013 лекция 2Technopark
 
Web весна 2013 лекция 3
Web весна 2013 лекция 3Web весна 2013 лекция 3
Web весна 2013 лекция 3Technopark
 
Web осень 2013 лекция 3
Web осень 2013 лекция 3Web осень 2013 лекция 3
Web осень 2013 лекция 3Technopark
 
Web весна 2013 лекция 5
Web весна 2013 лекция 5Web весна 2013 лекция 5
Web весна 2013 лекция 5Technopark
 
Web весна 2013 лекция 7
Web весна 2013 лекция 7Web весна 2013 лекция 7
Web весна 2013 лекция 7Technopark
 
СУБД 2013 Лекция №5 "Определение узких мест"
СУБД 2013 Лекция №5 "Определение узких мест"СУБД 2013 Лекция №5 "Определение узких мест"
СУБД 2013 Лекция №5 "Определение узких мест"Technopark
 
Михаил Давыдов — JavaScript: События
Михаил Давыдов — JavaScript: СобытияМихаил Давыдов — JavaScript: События
Михаил Давыдов — JavaScript: СобытияYandex
 
Лекция 11. Вычислительная модель Pregel
Лекция 11. Вычислительная модель PregelЛекция 11. Вычислительная модель Pregel
Лекция 11. Вычислительная модель PregelTechnopark
 

Destaque (12)

Web весна 2013 лекция 6
Web весна 2013 лекция 6Web весна 2013 лекция 6
Web весна 2013 лекция 6
 
Web весна 2013 лекция 8
Web весна 2013 лекция 8Web весна 2013 лекция 8
Web весна 2013 лекция 8
 
Web весна 2013 лекция 9
Web весна 2013 лекция 9Web весна 2013 лекция 9
Web весна 2013 лекция 9
 
Михаил Давыдов: JavaScript. Базовые знания
Михаил Давыдов: JavaScript. Базовые знанияМихаил Давыдов: JavaScript. Базовые знания
Михаил Давыдов: JavaScript. Базовые знания
 
Web весна 2013 лекция 2
Web весна 2013 лекция 2Web весна 2013 лекция 2
Web весна 2013 лекция 2
 
Web весна 2013 лекция 3
Web весна 2013 лекция 3Web весна 2013 лекция 3
Web весна 2013 лекция 3
 
Web осень 2013 лекция 3
Web осень 2013 лекция 3Web осень 2013 лекция 3
Web осень 2013 лекция 3
 
Web весна 2013 лекция 5
Web весна 2013 лекция 5Web весна 2013 лекция 5
Web весна 2013 лекция 5
 
Web весна 2013 лекция 7
Web весна 2013 лекция 7Web весна 2013 лекция 7
Web весна 2013 лекция 7
 
СУБД 2013 Лекция №5 "Определение узких мест"
СУБД 2013 Лекция №5 "Определение узких мест"СУБД 2013 Лекция №5 "Определение узких мест"
СУБД 2013 Лекция №5 "Определение узких мест"
 
Михаил Давыдов — JavaScript: События
Михаил Давыдов — JavaScript: СобытияМихаил Давыдов — JavaScript: События
Михаил Давыдов — JavaScript: События
 
Лекция 11. Вычислительная модель Pregel
Лекция 11. Вычислительная модель PregelЛекция 11. Вычислительная модель Pregel
Лекция 11. Вычислительная модель Pregel
 

Semelhante a Web весна 2013 лекция 4

Производительность в Django
Производительность в DjangoПроизводительность в Django
Производительность в DjangoMoscowDjango
 
Take more from Jquery
Take more from JqueryTake more from Jquery
Take more from JqueryMagento Dev
 
django cheBit'11
django cheBit'11django cheBit'11
django cheBit'11dva
 
MyBatis на практике
MyBatis на практикеMyBatis на практике
MyBatis на практикеVitebsk Miniq
 
Взломать Web-сайт на ASP.NET? Сложно, но можно!
Взломать Web-сайт на ASP.NET? Сложно, но можно!Взломать Web-сайт на ASP.NET? Сложно, но можно!
Взломать Web-сайт на ASP.NET? Сложно, но можно!Vladimir Kochetkov
 
Пластилиновый код: как перестать кодить и начать жить
Пластилиновый код: как перестать кодить и начать житьПластилиновый код: как перестать кодить и начать жить
Пластилиновый код: как перестать кодить и начать житьMoscow.pm
 
GAE - плюсы/минусы/подводные камни
GAE - плюсы/минусы/подводные камниGAE - плюсы/минусы/подводные камни
GAE - плюсы/минусы/подводные камниYehor Nazarkin
 
Web весна 2012 лекция 7
Web весна 2012 лекция 7Web весна 2012 лекция 7
Web весна 2012 лекция 7Technopark
 
kranonitS20 Сергей Бурма. Django - легко, быстро, эффективно
kranonitS20 Сергей Бурма. Django - легко, быстро, эффективноkranonitS20 Сергей Бурма. Django - легко, быстро, эффективно
kranonitS20 Сергей Бурма. Django - легко, быстро, эффективноKrivoy Rog IT Community
 
PHP Tricks
PHP TricksPHP Tricks
PHP TricksBlackFan
 
Web весна 2013 лекция 10
Web весна 2013 лекция 10Web весна 2013 лекция 10
Web весна 2013 лекция 10Technopark
 
константин лебедев
константин лебедевконстантин лебедев
константин лебедевkuchinskaya
 
View как чистая функция от состояния базы данных - Илья Беда, bro.agency
View как чистая функция от состояния базы данных  - Илья Беда, bro.agencyView как чистая функция от состояния базы данных  - Илья Беда, bro.agency
View как чистая функция от состояния базы данных - Илья Беда, bro.agencyit-people
 
Yii2
Yii2Yii2
Yii2Noveo
 
Новая eCommerce платформа D7: заказы, холдинг, персональный раздел
Новая eCommerce платформа D7:  заказы, холдинг, персональный разделНовая eCommerce платформа D7:  заказы, холдинг, персональный раздел
Новая eCommerce платформа D7: заказы, холдинг, персональный раздел1С-Битрикс
 
Архитектура кода нового 2ГИС Web API или куда мы дели MVC
Архитектура кода нового 2ГИС Web API или куда мы дели MVCАрхитектура кода нового 2ГИС Web API или куда мы дели MVC
Архитектура кода нового 2ГИС Web API или куда мы дели MVCDevDay
 

Semelhante a Web весна 2013 лекция 4 (20)

Jsfwdays 2013-2
Jsfwdays 2013-2Jsfwdays 2013-2
Jsfwdays 2013-2
 
Производительность в Django
Производительность в DjangoПроизводительность в Django
Производительность в Django
 
Take more from Jquery
Take more from JqueryTake more from Jquery
Take more from Jquery
 
django cheBit'11
django cheBit'11django cheBit'11
django cheBit'11
 
MyBatis на практике
MyBatis на практикеMyBatis на практике
MyBatis на практике
 
My batis
My batisMy batis
My batis
 
Взломать Web-сайт на ASP.NET? Сложно, но можно!
Взломать Web-сайт на ASP.NET? Сложно, но можно!Взломать Web-сайт на ASP.NET? Сложно, но можно!
Взломать Web-сайт на ASP.NET? Сложно, но можно!
 
Пластилиновый код: как перестать кодить и начать жить
Пластилиновый код: как перестать кодить и начать житьПластилиновый код: как перестать кодить и начать жить
Пластилиновый код: как перестать кодить и начать жить
 
GAE - плюсы/минусы/подводные камни
GAE - плюсы/минусы/подводные камниGAE - плюсы/минусы/подводные камни
GAE - плюсы/минусы/подводные камни
 
Web весна 2012 лекция 7
Web весна 2012 лекция 7Web весна 2012 лекция 7
Web весна 2012 лекция 7
 
kranonitS20 Сергей Бурма. Django - легко, быстро, эффективно
kranonitS20 Сергей Бурма. Django - легко, быстро, эффективноkranonitS20 Сергей Бурма. Django - легко, быстро, эффективно
kranonitS20 Сергей Бурма. Django - легко, быстро, эффективно
 
PHP Tricks
PHP TricksPHP Tricks
PHP Tricks
 
Web весна 2013 лекция 10
Web весна 2013 лекция 10Web весна 2013 лекция 10
Web весна 2013 лекция 10
 
константин лебедев
константин лебедевконстантин лебедев
константин лебедев
 
View как чистая функция от состояния базы данных - Илья Беда, bro.agency
View как чистая функция от состояния базы данных  - Илья Беда, bro.agencyView как чистая функция от состояния базы данных  - Илья Беда, bro.agency
View как чистая функция от состояния базы данных - Илья Беда, bro.agency
 
Yii2
Yii2Yii2
Yii2
 
Новая eCommerce платформа D7: заказы, холдинг, персональный раздел
Новая eCommerce платформа D7:  заказы, холдинг, персональный разделНовая eCommerce платформа D7:  заказы, холдинг, персональный раздел
Новая eCommerce платформа D7: заказы, холдинг, персональный раздел
 
Js fuckworks
Js fuckworksJs fuckworks
Js fuckworks
 
Архитектура кода нового 2ГИС Web API или куда мы дели MVC
Архитектура кода нового 2ГИС Web API или куда мы дели MVCАрхитектура кода нового 2ГИС Web API или куда мы дели MVC
Архитектура кода нового 2ГИС Web API или куда мы дели MVC
 
UWDC 2013, Yii2
UWDC 2013, Yii2UWDC 2013, Yii2
UWDC 2013, Yii2
 

Mais de Technopark

Лекция 14. Hadoop в Поиске Mail.Ru
Лекция 14. Hadoop в Поиске Mail.RuЛекция 14. Hadoop в Поиске Mail.Ru
Лекция 14. Hadoop в Поиске Mail.RuTechnopark
 
Лекция 13. YARN
Лекция 13. YARNЛекция 13. YARN
Лекция 13. YARNTechnopark
 
Лекция 12. Spark
Лекция 12. SparkЛекция 12. Spark
Лекция 12. SparkTechnopark
 
Лекция 10. Apache Mahout
Лекция 10. Apache MahoutЛекция 10. Apache Mahout
Лекция 10. Apache MahoutTechnopark
 
Лекция 9. ZooKeeper
Лекция 9. ZooKeeperЛекция 9. ZooKeeper
Лекция 9. ZooKeeperTechnopark
 
Лекция 7. Введение в Pig и Hive
Лекция 7. Введение в Pig и HiveЛекция 7. Введение в Pig и Hive
Лекция 7. Введение в Pig и HiveTechnopark
 
Лекция 6. MapReduce в Hadoop (графы)
Лекция 6. MapReduce в Hadoop (графы)Лекция 6. MapReduce в Hadoop (графы)
Лекция 6. MapReduce в Hadoop (графы)Technopark
 
Лекция 5. MapReduce в Hadoop (алгоритмы)
Лекция 5. MapReduce в Hadoop (алгоритмы)Лекция 5. MapReduce в Hadoop (алгоритмы)
Лекция 5. MapReduce в Hadoop (алгоритмы)Technopark
 
Лекция 4. MapReduce в Hadoop (введение)
Лекция 4. MapReduce в Hadoop (введение)Лекция 4. MapReduce в Hadoop (введение)
Лекция 4. MapReduce в Hadoop (введение)Technopark
 
Лекция 3. Распределённая файловая система HDFS
Лекция 3. Распределённая файловая система HDFSЛекция 3. Распределённая файловая система HDFS
Лекция 3. Распределённая файловая система HDFSTechnopark
 
Лекция 2. Основы Hadoop
Лекция 2. Основы HadoopЛекция 2. Основы Hadoop
Лекция 2. Основы HadoopTechnopark
 
Лекция 1. Введение в Big Data и MapReduce
Лекция 1. Введение в Big Data и MapReduceЛекция 1. Введение в Big Data и MapReduce
Лекция 1. Введение в Big Data и MapReduceTechnopark
 
СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL"
СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL"СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL"
СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL"Technopark
 
СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL" Час...
СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL" Час...СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL" Час...
СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL" Час...Technopark
 
СУБД 2013 Лекция №9 "Безопасность баз данных"
СУБД 2013 Лекция №9 "Безопасность баз данных"СУБД 2013 Лекция №9 "Безопасность баз данных"
СУБД 2013 Лекция №9 "Безопасность баз данных"Technopark
 
СУБД 2013 Лекция №8 "Конфигурирование базы данных"
СУБД 2013 Лекция №8 "Конфигурирование базы данных"СУБД 2013 Лекция №8 "Конфигурирование базы данных"
СУБД 2013 Лекция №8 "Конфигурирование базы данных"Technopark
 
СУБД 2013 Лекция №7 "Оптимизация запросов и индексирование"
СУБД 2013 Лекция №7 "Оптимизация запросов и индексирование"СУБД 2013 Лекция №7 "Оптимизация запросов и индексирование"
СУБД 2013 Лекция №7 "Оптимизация запросов и индексирование"Technopark
 
СУБД 2013 Лекция №6 "Профилирование запросов. Сложноструктурированные SQL-зап...
СУБД 2013 Лекция №6 "Профилирование запросов. Сложноструктурированные SQL-зап...СУБД 2013 Лекция №6 "Профилирование запросов. Сложноструктурированные SQL-зап...
СУБД 2013 Лекция №6 "Профилирование запросов. Сложноструктурированные SQL-зап...Technopark
 
СУБД 2013 Лекция №4 "Расширенные возможности работы с базами данных. Триггеры...
СУБД 2013 Лекция №4 "Расширенные возможности работы с базами данных. Триггеры...СУБД 2013 Лекция №4 "Расширенные возможности работы с базами данных. Триггеры...
СУБД 2013 Лекция №4 "Расширенные возможности работы с базами данных. Триггеры...Technopark
 
СУБД 2013 Лекция №3 "Выборка данных (продолжение). Транзакции"
СУБД 2013 Лекция №3 "Выборка данных (продолжение). Транзакции"СУБД 2013 Лекция №3 "Выборка данных (продолжение). Транзакции"
СУБД 2013 Лекция №3 "Выборка данных (продолжение). Транзакции"Technopark
 

Mais de Technopark (20)

Лекция 14. Hadoop в Поиске Mail.Ru
Лекция 14. Hadoop в Поиске Mail.RuЛекция 14. Hadoop в Поиске Mail.Ru
Лекция 14. Hadoop в Поиске Mail.Ru
 
Лекция 13. YARN
Лекция 13. YARNЛекция 13. YARN
Лекция 13. YARN
 
Лекция 12. Spark
Лекция 12. SparkЛекция 12. Spark
Лекция 12. Spark
 
Лекция 10. Apache Mahout
Лекция 10. Apache MahoutЛекция 10. Apache Mahout
Лекция 10. Apache Mahout
 
Лекция 9. ZooKeeper
Лекция 9. ZooKeeperЛекция 9. ZooKeeper
Лекция 9. ZooKeeper
 
Лекция 7. Введение в Pig и Hive
Лекция 7. Введение в Pig и HiveЛекция 7. Введение в Pig и Hive
Лекция 7. Введение в Pig и Hive
 
Лекция 6. MapReduce в Hadoop (графы)
Лекция 6. MapReduce в Hadoop (графы)Лекция 6. MapReduce в Hadoop (графы)
Лекция 6. MapReduce в Hadoop (графы)
 
Лекция 5. MapReduce в Hadoop (алгоритмы)
Лекция 5. MapReduce в Hadoop (алгоритмы)Лекция 5. MapReduce в Hadoop (алгоритмы)
Лекция 5. MapReduce в Hadoop (алгоритмы)
 
Лекция 4. MapReduce в Hadoop (введение)
Лекция 4. MapReduce в Hadoop (введение)Лекция 4. MapReduce в Hadoop (введение)
Лекция 4. MapReduce в Hadoop (введение)
 
Лекция 3. Распределённая файловая система HDFS
Лекция 3. Распределённая файловая система HDFSЛекция 3. Распределённая файловая система HDFS
Лекция 3. Распределённая файловая система HDFS
 
Лекция 2. Основы Hadoop
Лекция 2. Основы HadoopЛекция 2. Основы Hadoop
Лекция 2. Основы Hadoop
 
Лекция 1. Введение в Big Data и MapReduce
Лекция 1. Введение в Big Data и MapReduceЛекция 1. Введение в Big Data и MapReduce
Лекция 1. Введение в Big Data и MapReduce
 
СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL"
СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL"СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL"
СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL"
 
СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL" Час...
СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL" Час...СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL" Час...
СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL" Час...
 
СУБД 2013 Лекция №9 "Безопасность баз данных"
СУБД 2013 Лекция №9 "Безопасность баз данных"СУБД 2013 Лекция №9 "Безопасность баз данных"
СУБД 2013 Лекция №9 "Безопасность баз данных"
 
СУБД 2013 Лекция №8 "Конфигурирование базы данных"
СУБД 2013 Лекция №8 "Конфигурирование базы данных"СУБД 2013 Лекция №8 "Конфигурирование базы данных"
СУБД 2013 Лекция №8 "Конфигурирование базы данных"
 
СУБД 2013 Лекция №7 "Оптимизация запросов и индексирование"
СУБД 2013 Лекция №7 "Оптимизация запросов и индексирование"СУБД 2013 Лекция №7 "Оптимизация запросов и индексирование"
СУБД 2013 Лекция №7 "Оптимизация запросов и индексирование"
 
СУБД 2013 Лекция №6 "Профилирование запросов. Сложноструктурированные SQL-зап...
СУБД 2013 Лекция №6 "Профилирование запросов. Сложноструктурированные SQL-зап...СУБД 2013 Лекция №6 "Профилирование запросов. Сложноструктурированные SQL-зап...
СУБД 2013 Лекция №6 "Профилирование запросов. Сложноструктурированные SQL-зап...
 
СУБД 2013 Лекция №4 "Расширенные возможности работы с базами данных. Триггеры...
СУБД 2013 Лекция №4 "Расширенные возможности работы с базами данных. Триггеры...СУБД 2013 Лекция №4 "Расширенные возможности работы с базами данных. Триггеры...
СУБД 2013 Лекция №4 "Расширенные возможности работы с базами данных. Триггеры...
 
СУБД 2013 Лекция №3 "Выборка данных (продолжение). Транзакции"
СУБД 2013 Лекция №3 "Выборка данных (продолжение). Транзакции"СУБД 2013 Лекция №3 "Выборка данных (продолжение). Транзакции"
СУБД 2013 Лекция №3 "Выборка данных (продолжение). Транзакции"
 

Web весна 2013 лекция 4

  • 2. Что мы научимся делать? ● Обрабатывать GET и POST запросы ● Выводить HTML при помощи шаблонов ● Хранить данные в СУБД Типичные задачи ● Отображение списка объектов ● Изменение (редактирование) объектов ● Wizards: последовательности страниц
  • 3. Языки и интерфейсы Статические (+/-): ● СС++ модули к Web серверам. ● Java – Servlets, ApplicationServers Динамически (+/-): ● Perl – CGI, mod_perl, PSGI ● PHP – mod_php, FastCGI (FPM) ● Ruby – rack, свой сервер (mongrel) ● Python – WSGI, свой сервер (Tornado) ● JavaScript – свой сервер (NodeJS)
  • 4. CGI
  • 5. CGI Запрос: ● Параметры запроса – environ ● Тело запроса – stdin ● URI запроса – QUERY_STRING или argv[1] Ответ: ● Тело ответа (с заголовками) - stdout ● Ошибки выполнения - stderr ● HTTP код – через псевдозаголовок Status
  • 6. CGI – окружение Переменные окружения REQUEST_METHOD – метод (GET, POST, …) REQUEST_URI – строка запроса QUERY_STRING - строка параметров REMOTE_ADDR – ip адрес клиента SCRIPT_NAME – имя текущего скрипта HTTP_COOKIE – заголовок Cookie: HTTP_REFERER – заголовок Referer:
  • 7. CGI скрипт #!/usr/bin/python2.7 import os import sys print print print print "Content-type: text/html" "Status: 200" "" "<h1>Hello, world!</h1>" for k, v in os.environ.items(): print "%s = %s<br>" % (k, v) print >> sys.stderr, "Nice to meet you"
  • 8. nph - CGI скрипт #!/usr/bin/python2.7 print print print print "HTTP/1.0 301 Found" "Location: http://go.mail.ru/" "Set-Cookie: name=value" "" Как сервер определяет nph скрипт ? ● По имени файла nph- ● По первой строчке вывода скрипта В чем отличие от обычных CGI ?
  • 10. GET параметры Гиперссылка <a href=”/hello.cgi?name=me&greeting=hello”/>Hello!</a> Переменная окружения QUERY_STRING=name=me&greeting=hello CGI скрипт get_params = {} qs = os.environ['QUERY_STRING'] for pair in qs.split('&'): key, value = pair.split('=') get_params[key] = value
  • 11. POST параметры Форма <form method=”post” action=”/hello.cgi”> <input name=”name” value=”me”/> <input name=”greeting” value=”hi”/> <input type=”submit”/> </form> Стандартный поток ввода STDIN name=me&greeting=hello CGI скрипт qs = sys.stdin.read() ...
  • 12. Файлы и не-ASCII multipart/form-data <form method=”post” action=”/hello.cgi” enctype=”multipart/form-data”> <input name=”name” value=”me”/> <input name=”pic” type=”file”/> <input type=”submit”/> </form> URI percent encoding <a href=”/hello.cgi?name=%D0%B8%D0%BC%D1%8F”>привет</a>
  • 13. Библиотеки CGI #!/usr/bin/python2.7 import cgi import cgitb cgitb.enable() form = cgi.FieldStorage() if “greeting” not in form: raise BaseException(“can't work”) greeting = form[“greeting”] names = form.getlist(“name”) pic = forms[“pic”].file.read()
  • 14. Обработка форм 1) Валидация (regex, code) if not re.match('[a-z]+', form[“name”]): raise BaseException(“panic”) 2) Очистка story = re.sub('<[^>]+>', ' ', form[“story”]) 3) Экранирование story = form[“story”] re.sub('<', '&lt;', story) re.sub('>', '&gt', story)
  • 17. СУБД: SQL INSERT INTO users (name, age) VALUES ('petr', 10), ('masha', 25); UPDATE users SET age = 10 WHERE name = 'petr'; DELETE FROM users WHERE name = 'masha'; SELECT * FROM users WHERE age > 10; SELECT * FROM users WHERE name = 'masha'; SELECT max(age) FROM users;
  • 18. SQL в python import MySQLdb db = MySQLdb.connect(**options) cursor = db.cursor() cursor.execute(“update users set age = age+1 ” ”where name = ?”, form[“name”]) context = {} cursor.execute(“select * from users”) context['friends'] = cursor.fetchall() cursor.execute(“select * from users where name = ?”, form[“name”]) context['user'] = cursor.fetchone() db.close()
  • 20. Конфигурация 1) hardcode. Настройки зашиты в код приложения 2) script. Настройки представляют собой скрипт на целевом ЯП 3) YAML, XML, ini, Config::Apache 4) Переменные, разделение на несколько файлов
  • 22. Шаблонизаторы print “<html><body><h1>” “%s</h1></body></html>” % name VS context = { 'user' : get_user(form['name']), 'friends' : get_friends(form['name']) } print render('tpl/home.html', context)
  • 23. Шаблоны <body> <h1>{{ user.name }}</h1> {% if user.sex == 'male' %} <h2>{{ user.age }}</h2> {% endif %} {% for f in friends %} <a href=”mailto:{{ f.email }}”>{{ f.name }}</a> <p>{{ f.about|linebreaks }}</p> {% endfor %} </body>
  • 25. Подшаблоны {% include 'inc/header.html' %} <table><tr> <td>{% include 'inc/left.html' %}</td> <td> CONTENT </td> <td>{% include 'inc/right.html' %}</td> </tr></table> {% include 'inc/footer.html' %}
  • 26. Наследование (layouts) <!-- base.html --> <div>{% block header %} HEADER {% endblock %}</div> <table><tr> <td>LEFT</td> <td>{% block content %} CONTENT {% endblock %}</td> <td>RIGHT</td> </tr></table> <div>{% block footer %} FOOTER {% endblock %}</div>
  • 27. Наследование (layouts) <!-- page.html –-> {% extends 'base.html' %} {% block header %} Custom header {% endblock %} {% block content %} <h1>{{ user.name }}</h1> <div>{{ block.super }}</div> {% endblock %}
  • 29. Листинг объектов 1) Параметры: фильтрация, сортировка, номер страницы 2) /images/?order=created&page=3&limit=10 3) Результат работы скрипта: список объектов для данной страницы и paginator 4) paginator – представляет положение в списке страниц
  • 30. Листинг объектов #!/usr/bin/python import cgi import psycopg2 import settings db = psycopg2.connect(**settings.db) cursor = db.cursor() form = cgi.FieldStorage() order = form.getfirst('order', 'created') if order not in ('created', 'size'): raise BaseException('oops') page = int(form.getfirst('page', 1)) limit = int(form.getfirst('limit', 10)) sql = 'select * from img order by %s limit %d offset %d' % (order, limit, limit * (page – 1)) cursor.execute(sql)
  • 31. Листинг объектов context = {} context['images'] = cursor.fetchall() cursor.execute('select count(*) as cnt from images') total = cursor.fetchone()[0]['cnt'] context['pager'] = calc_paginator(total, page, limit) db.close() print print print print “Status: 200” “Content-Type: text/html” “” render('/images.html', context)
  • 32. Paginator Аргументы: total, page, limit Результат: { 'total': 100, 'page': 5, 'limit': 10, 'next_page': 6, 'prev_page': 4, 'next_page10': 10, 'prev_page10': 1, 'first_page':1, 'last_page': 10, 'pages' : [3, 4, 5, 6, 7] }
  • 34. Изменение объекта 1) Два режима работы: отображение формы и обновление объекта 2) Разделение по методу HTTP (GET | POST). Кеширование запросов 3) Использование спец. параметра (action) 4) Отображение ошибок и результата действия
  • 35. Изменение объекта #!/usr/bin/python import cgi; import psycopg2; import settings; import os db = psycopg2.connect(**settings.db) cursor = db.cursor() form = cgi.FieldStorage() if os.environ['HTTP_METHOD'] == 'POST”: try: cursor.execute('update users set name = ? where id = ?', form['name'], form['id']) redirect('/cgi-bin/object?id=%s&res=updated' % form['id']) catch BaseException, e: redirect('/cgi-bin/object?id=%s&fail=fail' % form['id']) else: context = {} cursor.execute('select * from users where id = ?', form['id']) context['object'] = cursor.fetchone() render('object.html', context)
  • 36. Изменение объекта <form method=”POST” action=”/cgi-bin/object”> {% if res %} <p style=”color: green”>Объект обновлен:{{ res }}</p> {% endif %} {% if fail %} <p style=”color: red”>Ошибка: {{ fail }}</p> {% endif %} <input type=”hidden” name=”id” value=”{{ object.id }}”> <input type=”text” name=”name” value=”{{ object.name }}”> <input type=”submit”> </form>
  • 37. Best Practice 1) Разделять методы GET – получение, POST – обновление данных 2) Сообщать об ошибках и успехе 3) Коды возврата при ошибке и успехе 4) Проверять данные пользователя а) на сервере – безопасность программы б) на клиенте – удобство пользователя 5) Выделять неправильно введеные поля
  • 39. Wizard 1) Statefull vs Stateless. 2) Как передать данные между страницами? выбор товара → информация о клиенте → место доставки → подтверждение 3) Варианты: - через URL - через скрытые поля - через Cookie - через сессии
  • 40. Скрытые поля <!-- page2.html → <form method=”POST” action=”/page3.html”> <input type=”hidden” name=”item_id” value=”1”> <input type=”hidden” name=”ammount” value=”4”> <input type=”text” name=”name” value=””> <input type=”text” name=”phone” value=””> <input type=”submit”> </form>
  • 41. Cookie и Сессии Cookie: Set-Cookie: name=val; path=/; domain=domain.ru; expires=Tue, 20 Mar 2012 11:52:54 GMT Cookie: name=val;name2=val2;is_visited=2011-13-15 Сессии: 1) Ключ сессии – в cookie 2) Данные – на сервере (memcached, database, files)
  • 42. Cookie в Python Установка: import Cookie cookie = Cookie.SimpleCookie() cookie['name'] = 'val' cookie['name']['path'] = '/path' Получение: import Cookie cookie = Cookie.SimpleCookie() cookie.load('a=b;c=d') for name in cookie: print '%s => %s' % (name, cookie[name])
  • 43. Достоинства CGI 1) простая концепция “скриптов” 2) стандарт – поддержка на любом хостинге 3) последовательное исполнение
  • 44. Недостатки CGI 1) смешение кода и HTML → шаблонизаторы 2) повторение логики → вынесение кода в библиотеки 3) pretty urls → RewriteEngine 4) производительность (fork, exec, parse, db.connect) → кеширование кода (FastCGI, mod_perl etc)
  • 45. WSGI – pep 3333 def application(environ, start_response): start_response('200 OK', [ ('Content-Type', 'text/plain') ]) yield 'Hello Worldn' def application(environ, start_response): start_response('200 OK', [ ('Content-Type', 'text/plain')]) return [ 'Hello Worldn' ]