Создай свой Python веб-фреймворк: руководство

Фреймворк — это набор готовых инструментов, позволяющих создавать проекты быстрее и проще. Он предоставляет основные функции и архитектуру, упрощая процесс разработки и избавляя от необходимости писать всё с нуля. В каждом популярном языке программирования есть свои фреймворки. Python, например, предлагает множество фреймворков, каждый из которых предназначен для определённых целей: Django для веб-разработки, Pygame для игр, PyQt для приложений под ПК и т.д. Работа с фреймворком подобна использованию конструктора: основной каркас уже создан, разработчику остаётся лишь добавлять свой функционал. По сути, фреймворк — это набор готового кода, который можно использовать для построения проектов различного типа.

Создание простого веб-фреймворка на Python

Создадим простой веб-фреймворк на Python, используя только встроенные библиотеки. Мы не будем использовать сторонние библиотеки, чтобы проиллюстрировать базовые принципы.

Начало работы

  1. Импортируем необходимые классы:

    from http.server import HTTPServer, BaseHTTPRequestHandler
    from urllib.parse import urlparse
  2. Создадим функцию для запуска сервера:

    def run_server(server_class=HTTPServer, handler_class=BaseHTTPRequestHandler):
        server_address = ('', 8000)  # Хост и порт
        httpd = server_class(server_address, handler_class)
        print(f"Starting httpd server on {httpd.server_address[0]}:{httpd.server_address[1]}")
        httpd.serve_forever()
  3. Добавим условие для запуска функции при запуске файла:

    if __name__ == "__main__":
        run_server()

Запустив этот код, вы получите работающий сервер. Однако, при переходе по URL вы получите ошибку, так как пока не обрабатываются никакие URL-адреса.

Обработка запросов

Создадим класс, наследующий BaseHTTPRequestHandler, для обработки GET и POST запросов:

class SimpleHTTPRequestHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        parsed_path = urlparse(self.path)
        if parsed_path.path == '/':
            self.send_response(200)
            self.send_header('Content-type', 'text/html')
            self.end_headers()
            with open('index.html', 'rb') as f:
                self.wfile.write(f.read())
        else:
            self.send_response(404)
            self.send_header('Content-type', 'text/html')
            self.end_headers()
            self.wfile.write(b"<h1>404 Not Found</h1>")

    def do_POST(self):
        content_length = int(self.headers['Content-Length'])
        post_data = self.rfile.read(content_length)
        data = parse_qs(post_data.decode('utf-8'))
        print(data) # Вывод данных формы в консоль

        # Обработка данных формы (здесь будет код работы с базой данных)
        self.send_response(302) # Редирект
        self.send_header('Location', '/')
        self.end_headers()

Этот класс обрабатывает GET- и POST-запросы, выводя соответствующий контент или обрабатывая данные формы. Подставляем наш класс в конструктор HTTPServer. Теперь сервер будет обрабатывать несколько страниц и данные форм.

Работа с данными формы и базой данных

Добавим обработку данных формы и взаимодействие с базой данных SQLite:

import sqlite3
from urllib.parse import parse_qs

# ... (предыдущий код) ...

class SimpleHTTPRequestHandler(BaseHTTPRequestHandler):
    # ... (предыдущий код) ...
    def do_POST(self):
        content_length = int(self.headers['Content-Length'])
        post_data = self.rfile.read(content_length)
        data = parse_qs(post_data.decode('utf-8'))
        print(data)

        conn = sqlite3.connect('users.db')
        cursor = conn.cursor()
        cursor.execute('''
            CREATE TABLE IF NOT EXISTS users (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                username TEXT,
                password TEXT
            )
        ''')

        try:
            cursor.execute("INSERT INTO users (username, password) VALUES (?, ?)", (data['username'][0], data['password'][0]))
            conn.commit()
        except (KeyError, sqlite3.IntegrityError) as e:
            print(f"Ошибка добавления пользователя: {e}")

        conn.close()
        self.send_response(302)
        self.send_header('Location', '/')
        self.end_headers()

Теперь данные пользователей будут сохраняться в базе данных SQLite. Обработка ошибок добавлена для повышения устойчивости.

Мы создали простой веб-сайт с обработкой GET и POST запросов, формой регистрации и базой данных SQLite. Этот проект не является полноценным фреймворком, но демонстрирует базовые принципы. Хотя создание проектов без фреймворков возможно, использование готовых фреймворков значительно упрощает и ускоряет разработку, предоставляя уже готовый функционал и архитектуру.

Что будем искать? Например,программа