Блог Синявского
  • Разделы
  • Метки
  • Все статьи

Простое веб приложение средствами Python

1

Все используют разные фреймворки Flask, Django, Bottle. Есть также возможность написать простое веб приложение средствами стандартных библиотек Python, таких как wsgiref и sqlite (Python 2.5+).

Напишем простое приложение что-то вроде TODO листа. С хранением записей в базе sqlite. С возможностью удалять записи.

Создадим исполняемый файл программы main.py

$ nano main.py
#!/bin/python
# coding=utf-8
import os
import sqlite3
from string import Template
import urllib
from wsgiref.simple_server import make_server
import sys
import re
from cgi import escape

# Создаем подключение к базе данных и пересоздаем таблицу
CURRENT_DIR = os.path.dirname(os.path.abspath(__file__))
DATABASE_NAME = 'sqlite.db'
CONNECTION = sqlite3.connect(os.path.join(CURRENT_DIR, DATABASE_NAME))
CONNECTION.cursor().execute('''
DROP TABLE IF EXISTS todo;
''')
CONNECTION.commit()
CONNECTION.cursor().execute('''
CREATE TABLE todo(
   ID INTEGER PRIMARY KEY AUTOINCREMENT,
   COMMENT TEXT NOT NULL
);
''')

# Стандартные ответы об ошибках
def not_found(environ, start_response):
    start_response('404 NOT FOUND', [('Content-Type', 'text/plain')])
    return ['Not Found']


def template_not_found(environ, start_response):
    start_response('404 NOT FOUND', [('Content-Type', 'text/plain')])
    return ['Template not Found']


# список комментариев
def index(environ, start_response, saved=False):
    row = CONNECTION.cursor().execute('''
        SELECT id, comment
        FROM todo;
    ''')
    comments_qs = row.fetchall()
    CONNECTION.commit()

    comments = u''.join([u'<tr><td>%s</td><td>%s</td><td><a href="/delete/%s">Удалить</a></td>' % (
        item[0], item[1], item[0]
    ) for item in comments_qs])
    try:
        with open('templates/index.html') as template_file:
            template = Template(template_file.read())
    except IOError:
        return template_not_found(environ, start_response)

    start_response('200 OK', [('Content-Type', 'text/html')])
    return [template.substitute({
       'comments': comments.encode('utf-8'), 
       'saved': '<div>Ваш комментарий добавлен</div>' if saved else ''
    })]


# форма комментария
def comment(environ, start_response):
    if environ['REQUEST_METHOD'] == 'POST':
        try:
            request_body_size = int(environ['CONTENT_LENGTH'])
            request_body = environ['wsgi.input'].read(request_body_size).split('\n')
        except (TypeError, ValueError):
            request_body = []
        else:
            post_values = dict(item.split('=') for item in request_body)
            post_values['comment'] = urllib.unquote_plus(post_values['comment'])

            row = CONNECTION.cursor().execute('''
                INSERT INTO todo(comment) VALUES("%s");
            ''' % post_values['comment']
            )
        return index(environ, start_response, saved=True)
    else:
        try:
            with open('templates/comment.html') as template_file:
                template = Template(template_file.read())
        except IOError:
            return template_not_found(environ, start_response)

        start_response('200 OK', [('Content-Type', 'text/html')])
        return [template.substitute({})]


# Обработчик удаления комментария
def delete(environ, start_response):
    args = environ['url_args']
    if args:
        print args[0]
        CONNECTION.cursor().execute('''
            DELETE FROM todo WHERE id=%s;
        ''' % args[0])
        CONNECTION.commit()
    return index(environ, start_response)


# Карта
urls = [
    (r'^$', index),
    (r'add/?$', comment),
    (r'delete/(.+)$', delete),
]

# Брокер приложения
def application(environ, start_response):
    path = environ.get('PATH_INFO', '').lstrip('/')
    for regex, callback in urls:
        match = re.search(regex, path)
        if match is not None:
            environ['url_args'] = match.groups()
            return callback(environ, start_response)
    return not_found(environ, start_response)

# Сервер
if __name__ == '__main__':
    srv = make_server('localhost', 8080, application)
    sys.exit(srv.serve_forever())

В этой же папке создадим папку для темплейтов и темплейты:

$ mkdir templates
$ cd templates
$ nano index.html
<html lang="ru">
<head>
    <title>Просмотр комментариев</title>
    <meta http-equiv="content-type" content="text/html; charset=utf-8">
</head>
<body>
$saved
<a href="/add/" title="Добавить комментарий">Добавить комментарий</a>
<table>
    <tr>
        <th>Id</th>
        <th>Комментарий</th>
        <th>Ред.</th>
    </tr>
    $comments
</table>
</body>
</html>
$ nano comment.html
<html lang="ru">
<head>
    <title>Добавление комментария</title>
    <meta http-equiv="content-type" content="text/html; charset=utf-8">
</head>
<body>
<form action="" method="POST">
    <div>
        <label for="comment">Комментарий:</label>
        <textarea name="comment" id="comment" rows="5">Ваш комментарий</textarea>
    </div>
    <button type="submit">Добавить комментарий</button>
</form>
</body>
</html>

Полная версия на github. Приложение можно переписать для себя, оно показывает что для простых задач не нужен фреймворк.



  • ← сюда
  • туда →

comments powered by Disqus

Опубликовано

01.04.2016

Обновление

05.05.2022

Категории

python

Тэги

  • example 16
  • python 30

Всегда на связи

  • Блог Синявского - Ничего не переносить на завтра, это тоже проблема с прокастинацией?
  • © Алексей Синявский, по лицензии CC BY-SA если не указано иное.
  • С использованием Pelican. Тема: Elegant от Talha Mansoor