<!DOCTYPE html> | |
<!DOCTYPE html PUBLIC «-//W3C//DTD XHTML 1.0 Strict//EN» «http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd»> | |
<!DOCTYPE HTML PUBLIC «-//W3C//DTD HTML 4.01 Transitional//EN» «http://www.w3.org/TR/html4/loose.dtd»> | |
<!—[if lt IE 8]><html lang=»ru»><![endif]—> | |
<!—[if IE 8]><html lang=»ru»><![endif]—> | |
<!—[if IE 9]><html lang=»ru»><![endif]—> | |
<!—[if (gt IE 9)|!(IE)]><!—><html lang=»ru»><!—><![endif]—> | |
<head> | |
<meta http-equiv=»Content-Type» content=»text/html; charset=UTF-8″> | |
<meta charset=»utf-8″> | |
<meta http-equiv=»X-UA-Compatible» content=»IE=edge»> | |
<meta name=»viewport» content=»width=device-width, initial-scale=1. 0, shrink-to-fit=no»> | |
<!— <link rel=»stylesheet» href=»css/reset.css»> —> | |
<!— нормализация дефолтных стилей браузеров —> | |
<link rel=»stylesheet» href=»css/normalize.css»> | |
<!— основные стили —> | |
<link rel=»stylesheet» href=»css/main.css»> | |
<script src=»js/jquery-1.11.3.min.js»></script> | |
<!— проверка поддержки свойств в разных браузерах —> | |
<script src=»js/modernizr. custom.js»></script> | |
<!— поддержка html5-тегов, css3-селекторов, медиа-запросов в IE<=8 —> | |
<!—[if lt IE 9]> | |
<script src=»js/html5shiv.min.js»></script> | |
<script src=»js/respond.min.js»></script> | |
<script src=»js/nwmatcher-1.2.5.js»></script> | |
<script src=»js/selectivizr-min.js»></script> | |
<![endif]—> | |
<!— основные скрипты —> | |
<script src=»js/scripts. js»></script> | |
<meta name=»description» content=»Your description»> | |
<meta name=»author» content=»Author Name»> | |
<title>Page Title</title> | |
</head> | |
<body> | |
<div></div> | |
</body> | |
</html> |
CGI: пишем простой сайт на Python. Часть 3: Пример приложения
Мы уже научились обрабатывать формы и устанавливать cookies. Сегодня же мы посмотрим, что может из этого получиться.
Чтобы работать с пользовательскими данными, нужно где-то эти данные сохранять. Самый простой (но далеко не самый изящный и безопасный) — хранение данных в файлах. Более продвинутый способ — хранение в базе данных. Мы остановимся на первом способе, как на самом простом.
Собственно, ничего нового здесь объясняться не будет. Работу с файлами вы уже знаете, обрабатывать формы уже умеете.
Сегодня мы напишем прототип приложения типа «твиттер». Данные в файлах будем хранить в json.
Создадим 2 файла: один будет отвечать за обработку данных, вводимых пользователем, второй — вспомогательный модуль, который упростит код первого.
cgi-bin/wall.py:
#!/usr/bin/env python3 # -*- coding: utf-8 -*- import cgi import html import http.cookies import os from _wall import Wall wall = Wall() cookie = http.cookies.SimpleCookie(os.environ.get("HTTP_COOKIE")) session = cookie.get("session") if session is not None: session = session.value user = wall.find_cookie(session) # Ищем пользователя по переданной куке form = cgi. FieldStorage() action = form.getfirst("action", "") if action == "publish": text = form.getfirst("text", "") text = html.escape(text) if text and user is not None: wall.publish(user, text) elif action == "login": login = form.getfirst("login", "") login = html.escape(login) password = form.getfirst("password", "") password = html.escape(password) if wall.find(login, password): cookie = wall.set_cookie(login) print('Set-cookie: session={}'.format(cookie)) elif wall.find(login): pass # А надо бы предупреждение выдать else: wall.register(login, password) cookie = wall.set_cookie(login) print('Set-cookie: session={}'.format(cookie)) pattern = ''' <!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <title>Стена</title> </head> <body> Форма логина и регистрации. При вводе несуществующего имени зарегистрируется новый пользователь. <form action="/cgi-bin/wall.py"> Логин: <input type="text" name="login"> Пароль: <input type="password" name="password"> <input type="hidden" name="action" value="login"> <input type="submit"> </form> {posts} {publish} </body> </html> ''' if user is not None: pub = ''' <form action="/cgi-bin/wall.py"> <textarea name="text"></textarea> <input type="hidden" name="action" value="publish"> <input type="submit"> </form> ''' else: pub = '' print('Content-type: text/html\n') print(pattern.format(posts=wall.html_list(), publish=pub))
Здесь мы используем форматирование строк для формирования страницы (кстати, это первый шаг на пути к созданию собственного шаблонизатора).
Не забудьте дать этому файлу права на выполнение (второму файлу эти права не нужны).
cgi-bin/_wall.py (здесь определены функции publish, login и другие):
#!/usr/bin/env python3 # -*- coding: utf-8 -*- import json import random import time class Wall: USERS = 'cgi-bin/users. json' WALL = 'cgi-bin/wall.json' COOKIES = 'cgi-bin/cookies.json' def __init__(self): """Создаём начальные файлы, если они не созданы""" try: with open(self.USERS, 'r', encoding='utf-8'): pass except FileNotFoundError: with open(self.USERS, 'w', encoding='utf-8') as f: json.dump({}, f) try: with open(self.WALL, 'r', encoding='utf-8'): pass except FileNotFoundError: with open(self.WALL, 'w', encoding='utf-8') as f: json.dump({"posts": []}, f) try: with open(self.COOKIES, 'r', encoding='utf-8'): pass except FileNotFoundError: with open(self.COOKIES, 'w', encoding='utf-8') as f: json.dump({}, f) def register(self, user, password): """Регистриует пользователя. Возвращает True при успешной регистрации""" if self.find(user): return False # Такой пользователь существует with open(self.USERS, 'r', encoding='utf-8') as f: users = json.load(f) users[user] = password with open(self.USERS, 'w', encoding='utf-8') as f: json.dump(users, f) return True def set_cookie(self, user): """Записывает куку в файл. Возвращает созданную куку.""" with open(self.COOKIES, 'r', encoding='utf-8') as f: cookies = json.load(f) cookie = str(time.time()) + str(random.randrange(10**14)) # Генерируем уникальную куку для пользователя cookies[cookie] = user with open(self.COOKIES, 'w', encoding='utf-8') as f: json.dump(cookies, f) return cookie def find_cookie(self, cookie): """По куке находит имя пользователя""" with open(self.COOKIES, 'r', encoding='utf-8') as f: cookies = json.load(f) return cookies.get(cookie) def find(self, user, password=None): """Ищет пользователя по имени или по имени и паролю""" with open(self. USERS, 'r', encoding='utf-8') as f: users = json.load(f) if user in users and (password is None or password == users[user]): return True return False def publish(self, user, text): """Публикует текст""" with open(self.WALL, 'r', encoding='utf-8') as f: wall = json.load(f) wall['posts'].append({'user': user, 'text': text}) with open(self.WALL, 'w', encoding='utf-8') as f: json.dump(wall, f) def html_list(self): """Список постов для отображения на странице""" with open(self.WALL, 'r', encoding='utf-8') as f: wall = json.load(f) posts = [] for post in wall['posts']: content = post['user'] + ' : ' + post['text'] posts.append(content) return '<br>'.join(posts)
Разумеется, в нашем простом «твиттере» очень много недостатков: не выводятся предупреждения пользователю, регистрация при несуществующем имени, пароли хранятся в открытом виде, использованные куки не удаляются, и многие другие. Кто хочет, может усовершенствовать.
Но есть и преимущество: поскольку у нас теперь 2 разных файла (почти независимых), то можно поменять систему хранения данных (например, база данных вместо файлов), вообще не затрагивая wall.py.
Напоследок покажу, как это работает:
Сначала зарегистрировались, теперь нужно ещё раз ввести логин-пароль, чтобы войти.
Можно писать.
В следующей (возможно последней) части я покажу, как это всё можно опубликовать в сети интернет.
Для вставки кода на Python в комментарий заключайте его в теги <pre><code>Ваш код</code></pre>
Discover Basic HTML Code Examples
TL;DR — HTML-примеры представляют собой базовые фрагменты кода, демонстрирующие использование определенных функций.
Содержание
- 1. Пример базового кода
- 1.1. Декларация
- 1.2. Описание HTML: Пример
- 1.3. Заголовок и тело HTML: в чем разница?
- 1. 4. Использование заголовков HTML
- 1.5. Определение абзацев HTML
- 1.6. Предоставление HTML-ссылок
- 1.7. Добавление HTML-изображений
- 2. Пример HTML: полезные советы
Пример базового кода
Для начала посмотрим, как может выглядеть простой HTML-документ:
Пример
<тело>Заголовок
тело>
Попробуйте вживую. Учитесь на Udacity
Примечание: это очень простой документ с несколькими основными тегами HTML. Пока он полностью функционален, на нем нет никаких украшений или дополнительной информации.
Анализ примеров HTML — отличное упражнение для начинающих. Однако даже самые простые не будут иметь особого смысла, если у вас нет базового понимания тегов, используемых для определения элементов. В следующих разделах мы проанализируем основные элементы кода, показанные в этом примере, а также еще несколько относительно распространенных.
Объявление
Объявление помогает браузеру правильно понять и отобразить ваш документ. Нам это нужно, потому что существует более одного возможного типа веб-документа. Объявление Doctype не чувствительно к регистру:
Пример
Описание HTML: Пример
Элемент определяет HTML-документ. По сути, в то время как
определяет всю страницу,
добавляет к ней функциональность:
Пример
<голова>Название веб-сайта голова> <тело>Заголовок для содержимого ниже
Текст текст текст
тело>
Попробуйте вживую. Учитесь на Udacity
HTML Head и Body: в чем разница?
Элемент
используется для хранения метаданных, которые не видны пользователю. Это самая важная информация конкретного документа. Метаданные могут быть заголовком, сценариями или подобной информацией:Пример
Название документа
Попробуйте вживую Учитесь на Udacity
Элемент
Пример
Заголовок страницы
Попробуйте живое обучение на Udacity
Элемент
Пример
Заголовок
Абзац
тело>
Попробуйте It Live Learn On Udacity
Pros
- Упрощенный дизайн (без ненужной информации)
- Высококачественные курсы (даже бесплатные) 9008
Mail Features. Программы наностепеней ЭКСКЛЮЗИВ: СКИДКА 75% Профи Основные функции As 12.99 $ 9000 3 As 12.99 $ 9000 9013 9008 As Moad As 12.99 $ 9000 Pros Основные характеристики СКИДКА 75% Заголовки упрощают навигацию по содержанию. Он дает читателю первичную информацию о содержании той или иной части документа. Чтобы объявить заголовок, поместите его название внутри тегов Использование заголовков HTML
—
. Чем меньше номер заголовка, тем он больше и важнее:
Пример
Текст заголовка — Уровень 1. Самый важный заголовок
Текст заголовка — уровень 2
Текст заголовка — уровень 3
Текст заголовка — уровень 4
Текст заголовка — уровень 5
Текст заголовка — Уровень 6. Наименее важный заголовок
Попробуйте живое обучение на Udacity
Определение абзацев HTML
Чтобы установить место для абзаца, вам потребуется использовать элемент
. Этот элемент создан специально для текста и ни для чего другого. См. пример простого HTML-кода ниже:
Пример
Это абзац.
Это тоже абзац.
Это еще один абзац.
Попробуйте в прямом эфире. Учитесь на Udacity
Предоставление HTML-ссылок
Ссылки перенаправляют вас с текущей страницы на другую. Чтобы создать его, вам нужно будет использовать элемент и прикрепить к нему атрибут href
:
Пример
ссылка на внешний сайт
Попробуйте вживую. Учитесь на Udacity
Добавление HTML-изображений
Чтобы добавить изображение, вам понадобится тег ( img означает изображение ). Вам также нужно будет включить атрибут src
, чтобы ваш браузер мог понять, откуда взять изображение. Взгляните на приведенный ниже пример HTML-кода:
Пример
Попробуйте вживую Учитесь на Udacity
Вы также можете использовать атрибуты ширина
и высота
для определения размеров изображения. Используя alt
, вы можете предоставить альтернативный текст для отображения, если изображение не может быть загружено. Программы чтения с экрана, которые делают содержимое доступным для слепых или слабовидящих пользователей, также могут использовать его для представления идеи изображения.