| <!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 , вы можете предоставить альтернативный текст для отображения, если изображение не может быть загружено. Программы чтения с экрана, которые делают содержимое доступным для слепых или слабовидящих пользователей, также могут использовать его для представления идеи изображения.

0, shrink-to-fit=no»>
custom.js»></script>
js»></script>
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.
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.

4. Использование заголовков HTML