Пройдите тест, узнайте какой профессии подходите
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы
Введение в создание сайтов на Python
Python — один из самых популярных языков программирования, особенно когда речь идет о веб-разработке. Его простота и мощные библиотеки делают его идеальным выбором для создания сайтов. В этой статье мы рассмотрим, как создать сайт на Python с нуля, используя фреймворк Flask. Flask — это легковесный веб-фреймворк, который позволяет быстро и легко создавать веб-приложения. Он предоставляет минимальный набор инструментов, необходимых для создания веб-приложений, что делает его отличным выбором для новичков.

Установка и настройка окружения
Установка Python
Первым шагом будет установка Python. Вы можете скачать последнюю версию Python с официального сайта python.org. Убедитесь, что вы установили Python 3.x, так как Python 2.x больше не поддерживается. После скачивания установочного файла следуйте инструкциям на экране для завершения установки. Важно убедиться, что вы добавили Python в системный PATH, чтобы иметь возможность запускать его из командной строки.
Установка виртуального окружения
Виртуальное окружение позволяет вам изолировать зависимости вашего проекта от других проектов. Это особенно полезно, если вы работаете над несколькими проектами одновременно. Виртуальные окружения помогают избежать конфликтов между различными версиями библиотек, которые могут использоваться в разных проектах.
После активации виртуального окружения вы увидите, что в командной строке появится префикс (venv)
, указывающий на то, что вы находитесь в изолированном окружении. Это означает, что все установленные библиотеки будут доступны только в этом окружении и не повлияют на другие проекты.
Установка Flask
После активации виртуального окружения, установите Flask с помощью pip. Flask — это микрофреймворк для Python, который позволяет создавать веб-приложения с минимальными усилиями. Он предоставляет инструменты для маршрутизации URL, обработки запросов и ответов, а также для работы с шаблонами.
Создание простого веб-приложения с использованием Flask
Создание файла приложения
Создайте новый файл app.py
в корне вашего проекта. Этот файл будет содержать основной код вашего веб-приложения. В нем мы создадим экземпляр Flask-приложения и определим несколько маршрутов.
Запуск приложения
Запустите ваше приложение, выполнив следующую команду в терминале. Эта команда запустит встроенный сервер разработки Flask, который будет слушать запросы на порту 5000.
Теперь вы можете открыть браузер и перейти по адресу http://127.0.0.1:5000/
, чтобы увидеть ваше первое веб-приложение на Python. Если все сделано правильно, вы увидите сообщение «Hello, World!».
Добавление функциональности и маршрутизации
Создание новых маршрутов
Маршруты определяют, какие URL будут доступны в вашем приложении и какие функции будут вызваны при переходе по этим URL. Добавим несколько новых маршрутов в наше приложение. Каждый маршрут будет ассоциирован с определенной функцией, которая будет возвращать ответ на запрос.
Использование шаблонов
Flask поддерживает использование шаблонов для генерации HTML. Шаблоны позволяют отделить логику приложения от представления, что делает код более чистым и поддерживаемым. Создайте папку templates
в корне вашего проекта и добавьте в нее файл index.html
.
Измените функцию home
в app.py
, чтобы она использовала этот шаблон. Для этого импортируйте функцию render_template
из Flask и используйте ее для рендеринга HTML-шаблона.
Теперь, когда вы перейдете по адресу http://127.0.0.1:5000/
, вы увидите содержимое файла index.html
.
Добавление статики и стилей
Для улучшения внешнего вида вашего сайта вы можете добавить статические файлы, такие как CSS и JavaScript. Создайте папку static
в корне вашего проекта и добавьте в нее файл style.css
.
Добавьте ссылку на этот файл в ваш HTML-шаблон.
Теперь ваш сайт будет использовать стили из файла style.css
, что сделает его внешний вид более привлекательным.
Развертывание сайта на хостинг
Выбор хостинга
Для развертывания вашего сайта вам понадобится хостинг. Существует множество вариантов, таких как Heroku, AWS, DigitalOcean и другие. В этой статье мы рассмотрим развертывание на Heroku, так как это один из самых простых и доступных вариантов. Heroku предоставляет бесплатный тарифный план, который идеально подходит для небольших проектов и тестирования.
Установка Heroku CLI
Скачайте и установите Heroku CLI с официального сайта heroku.com. Heroku CLI позволяет управлять вашими приложениями на Heroku из командной строки, что делает процесс развертывания и управления приложениями более удобным.
Подготовка проекта к развертыванию
Создайте файл Procfile
в корне вашего проекта. Этот файл указывает Heroku, как запускать ваше приложение. В случае Flask-приложения это будет команда для запуска Python-скрипта.
Создайте файл requirements.txt
, который будет содержать все зависимости вашего проекта. Этот файл необходим Heroku для установки всех необходимых библиотек.
Развертывание на Heroku
Выполните следующие команды в терминале для развертывания вашего приложения на Heroku. Сначала войдите в Heroku, используя команду heroku login
, и следуйте инструкциям на экране для авторизации.
Теперь ваш сайт доступен в интернете! 🎉 Вы можете поделиться ссылкой на ваш сайт с друзьями и коллегами.
Заключение
Эта статья охватывает основные шаги по созданию и развертыванию простого сайта на Python с использованием Flask. Мы рассмотрели установку и настройку окружения, создание простого веб-приложения, добавление маршрутов и шаблонов, а также развертывание на Heroku. Надеюсь, она была полезной для вас. Удачи в ваших начинаниях!
Читайте также
Flask – компактный фреймворк для быстрой разработки веб-приложений. Он предоставляет минимальную необходимую функциональность и не навязывает никаких строгих правил в отношении структуры и архитектуры приложения (как это делает Django).
Flask универсален – на его основе можно создавать сложные приложения и API, и в то же время он идеально подходит для разработки небольших проектов. Самый большой плюс Flask – на нем очень просто реализовать генератор статических сайтов.
Основные преимущества Flask:
- Минималистичность. Flask отличается небольшим размером – в нем есть все самое необходимое и нет ничего лишнего.
- Гибкость. Фреймворк не диктует определенных правил и позволяет разработчику сохранить полный контроль над структурой приложения.
- Простота в использовании. Он имеет несколько встроенных функций, которые позволяют сразу начать создавать полноценные веб-приложения, даже если у вас нет опыта в веб-разработке на Python. Например, у Flask есть встроенный сервер, поддержка сессий, обработчик форм, шаблонизатор.
- Интеграция с дополнительными библиотеками. Фреймворк очень просто интегрируется с многочисленными библиотеками, которые расширяют его функциональность. Это позволяет создать гибкий, масштабируемый проект для любой сферы.
- Простота тестирования. У Flask есть встроенный тестовый клиент, который максимально упрощает тестирование и отладку.
Установка
Flask лучше всего устанавливать в виртуальное окружение – это позволяет избежать появления ошибок, связанных с конфликтами версий различных библиотек и модулей. Выполните в cmd:
python -m venv fproject\venv
Перейдите в только что созданную директорию:
cd fproject
Активируйте окружение:
venv\scripts\activate
И установите Flask:
pip install flask
Активировать виртуальное окружение нужно перед каждым
сеансом работы с Flask.
🐍🎓 Библиотека собеса по Python
🐍🧩 Библиотека задач по Python
Напишем приложение, которое будет выводить традиционное
приветствие Hello, World! в браузере. Сохраните
этот код в файле app.py в
директории fproject:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return 'Hello, World!'
if __name__ == '__main__':
app.run()
Этот код создает объект приложения Flask с помощью класса Flask и присваивает его переменной app. Декоратор @app.route('/')
устанавливает маршрут для
главной страницы нашего приложения, а метод def hello()
определяет, что будет отображаться на этой странице.
if
проверяет,
__name__ == '__main__':
запускается ли данный файл как самостоятельное приложение, или импортируется как модуль. В
нашем случае он запускается как независимое приложение, поэтому вызывается метод app.run(), который запускает веб-сервер Flask.
Запустите приложение в командой строке:
(venv) C:\Users\User\fproject>app.py
Откройте адрес http://localhost:5000/
в браузере:
Flask по умолчанию использует порт 5000. При желании его можно
изменить на более привычный 8000:
app.run(port=8000)
Кроме того, можно включить режим отладки – тогда все
возникающие ошибки будут отображаться на странице браузера, а при внесении
любых изменений в файлы проекта сервер будет автоматически перезагружаться:
app.run(debug=True)
Для остановки сервера нажмите Ctrl+C.
Маршруты в Flask
Маршруты – это URL-адреса, по которым пользователи могут открывать определенные
страницы (разделы) веб-приложения. Маршруты в Flask определяются с помощью декоратора
@app.route()
. Для каждого маршрута можно
написать отдельную функцию представления, которая будет выполнять какие-то действия при переходе по определенному адресу. Рассмотрим пример:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def home():
return 'Это главная страница.'
@app.route('/about')
def about():
return 'Здесь будет информация об авторе сайта.'
@app.route('/blog')
def blog():
return 'Это блог с заметками о работе и увлечениях.'
if __name__ == '__main__':
app.run()
Сохраните код, запустите приложение, последовательно
откройте адреса:
- http://localhost:5000/
- http://localhost:5000/about
- http://localhost:5000/blog
Переменные в маршрутах
В URL можно передавать различные значения. Запустите этот
код и перейдите по адресу, например, http://localhost:5000/user/EvilAdmin
from flask import Flask
app = Flask(__name__)
@app.route('/user/<username>')
def user_profile(username):
return f"Это профиль пользователя {username}"
if __name__ == '__main__':
app.run()
Имя пользователя, переданное в качестве переменной, будет
показано на странице:
А так можно передать в маршруте целое число:
from flask import Flask
app = Flask(__name__)
@app.route('/user/<int:user_id>')
def user_profile(user_id):
return f"Это профиль пользователя с ID {user_id}"
if __name__ == '__main__':
app.run()
Перейдите по адресу, например, http://localhost:5000/user/5:
Ваш путь в IT начинается с Python
Онлайн-курс «Основы программирования на Python» от Proglib academy предлагает 32 практических урока с персональной обратной связью от экспертов, где вы создадите 4 реальных проекта для портфолио и получите все необходимые навыки для старта карьеры в IT.
GET- и POST-запросы
GET и POST – это HTTP-запросы, которые используются для
отправки данных между клиентом и сервером.
GET-запрос применяют для получения данных от сервера. При
выполнении GET-запроса клиент отправляет запрос на сервер, а сервер возвращает
запрошенную информацию в ответ. GET-запросы могут содержать параметры в URL-адресе,
которые используются для передачи дополнительных данных.
POST-запрос используют для отправки данных на сервер. При
выполнении POST-запроса клиент отправляет данные на сервер, а сервер их обрабатывает. POST-запросы обычно применяют для отправки форм, с данными из которых нужно что-то сделать на бэкенде.
Рассмотрим простейший пример обработки формы авторизации.
Базы данных для хранения учетных записей у нас пока нет, поэтому в приведенном
ниже коде мы пропустим всю функциональность для проверки корректности логина и
пароля (мы рассмотрим этот вопрос позже, в одном из заданий):
from flask import Flask, request, render_template
app = Flask(__name__)
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
username = request.form['username']
password = request.form['password']
# проверка логина и пароля
return 'Вы вошли в систему!'
else:
return render_template('login.html')
if __name__ == '__main__':
app.run()
Маршрут @app.route('/login', methods=['GET', 'POST'])
обрабатывает и POST, и GET-запросы: в первом случае он отправит
данные на сервер, во втором – просто выведет страницу с формой авторизации.
Для вывода формы на странице сделаем простейший шаблон. Этот
код нужно сохранить в файле login.html, в директории templates (в этой папке Flask по
умолчанию ищет шаблоны):
{% extends 'base.html' %}
{% block content %}
<div class="container">
<div class="row justify-content-center mt-5">
<div class="col-md-6">
<div class="card">
<div class="card-header">
<h1 class="text-center">Вход на сайт</h1>
</div>
<div class="card-body">
{% with messages = get_flashed_messages() %}
{% if messages %}
<div class="alert alert-danger">
<ul>
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
</div>
{% endif %}
{% endwith %}
<form method="post">
<div class="mb-3">
<label for="username" class="form-label">Логин:</label>
<input type="text" class="form-control" id="username" name="username" required>
</div>
<div class="mb-3">
<label for="password" class="form-label">Пароль:</label>
<input type="password" class="form-control" id="password" name="password" required>
</div>
<div class="text-center">
<button type="submit" class="btn btn-primary">Войти</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
Никакие CSS
стили к шаблону не подключены, поэтому он выглядит не слишком привлекательно.
Но шаблон работает, а форма получает логин и пароль:
Шаблонизатор Jinja2
Шаблоны в Flask
используются для динамического формирования веб-страниц. Шаблоны представляют
собой HTML страницы, в
которые можно передавать любые данные с бэкенда. К шаблонам можно подключать
любые CSS-фреймворки
типа Bootstrap и Tailwind,
и любые JS-скрипты.
Поведением шаблонов управляет шаблонизатор Jinja2 – он предоставляет
функциональность для создания условий, циклов, макросов, наследования и блоков.
Главные преимущества шаблонизатора:
- Может проводить различные операции с контентом самостоятельно, не обращаясь к бэкенду.
- Обеспечивает наследование дизайна и стилей от базового шаблона.
Наследование работает так:
- Базовый шаблон, который обычно называется base.html, содержит общую разметку для сайта.
- В base.html подключаются локальные и CDN-фреймворки (CSS, JS), задаются фоновые изображения и фавикон.
- Дочерние шаблоны наследуют этот базовый шаблон и дополняют его своим собственным контентом.
Продемонстрируем наследование на примере. Сохраните в папке templates два файла. Это
содержимое файла base.html – в нем
подключается CSS-фреймворк
Bootstrap, кастомные
стили custom.css из
статической папки static,
иконки Font Awesome:
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>{% block title %}{% endblock %}</title>
<!-- Bootstrap стили -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet">
<!-- иконки fontawesome -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<!-- кастомные стили -->
<link rel="stylesheet" href="{{ url_for('static', filename='custom.css') }}">
</head>
<body>
<!-- навигация -->
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container">
<a class="navbar-brand" href="#">Мой личный сайт</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse"
data-bs-target="#navbarNav" aria-controls="navbarNav"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse justify-content-end"
id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" href="#">Главная</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Обо мне</a>
</li>
</ul>
</div>
</div>
</nav>
<!-- контент дочерних шаблонов -->
<div class="container my-3">
{% block content %}
{% endblock %}
</div>
</body>
</html>
Шаблон base.html также содержит верхнее меню для навигации по сайту – это меню будут наследовать все дочерние шаблоны. Вот пример дочернего шаблона about.html:
{% extends 'base.html' %}
{% block title %}Мое резюме{% endblock %}
{% block content %}
<div class="container my-5">
<h1 class="text-center mb-4">Мое резюме</h1>
<div class="row">
<div class="col-md-6">
<h2>Образование</h2>
<h4>Московский политехнический институт</h4>
<p class="mb-0">Бакалавр Computer Science</p>
<p class="text-muted">2016 - 2020</p>
</div>
<div class="col-md-6">
<h2>Опыт работы</h2>
<h4>Web Developer - XYZ компания</h4>
<p class="mb-0">2019 - н.в.</p>
<p class="text-muted">- Разработка и поддержка веб-приложений</p>
<p class="text-muted">- Работа с Python, Django, HTML/CSS, JavaScript, MySQL</p>
</div>
</div>
<div class="row mt-5">
<div class="col-md-6">
<h2>Навыки</h2>
<ul class="list-group">
<li class="list-group-item border-0 py-1"><i class="fa fa-cog"></i> Python</li>
<li class="list-group-item border-0 py-1"><i class="fa fa-cog"></i> Django</li>
<li class="list-group-item border-0 py-1"><i class="fa fa-cog"></i> HTML/CSS</li>
<li class="list-group-item border-0 py-1"><i class="fa fa-cog"></i> JavaScript</li>
</ul>
</div>
<div class="col-md-6">
<h2>Проекты</h2>
<h4>Сайт для продажи автомобилей</h4>
<p class="text-muted mb-0">- Разработка сайта с использованием Django</p>
<p class="text-muted">- Интеграция с API маркетплейса для получения данных об автомобилях</p>
<h4>Игровой блог</h4>
<p class="text-muted mb-0">- Разработка блога с использованием Django</p>
<p class="text-muted">- Возможность создавать учeтные записи пользователей и писать комментарии</p>
</div>
</div>
<div class="row mt-5">
<div class="col-md-6">
<h2>Контакты</h2>
<p class="mb-0"><i class="fa fa-phone"></i> Телефон: +990123456789</p>
<p class="mb-0"><i class="fa fa-envelope"></i> Email: example@example.com</p>
<p class="mb-0"><i class="fa fa-github"> GitHub: <a href="https://github.com/example"></i>example</a></p>
</div>
<div class="col-md-6">
<h2>Языки</h2>
<ul class="list-group">
<li class="list-group-item border-0 py-1"><i class="fa fa-check-circle"></i> Английский (C1)</li>
<li class="list-group-item border-0 py-1"><i class="fa fa-check-circle"></i> Немецкий (B2)</li>
<li class="list-group-item border-0 py-1"><i class="fa fa-check-circle"></i> Русский (родной)</li>
</ul>
</div>
</div>
</div>
{% endblock %}
Фон страницы шаблонизатор берет из файла static/customs.css:
body {
background-color: #e5e5e5;
}
А код для вывода страницы выглядит так:
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/about')
def about():
return render_template('about.html')
if __name__ == '__main__':
app.run(debug=True)
Запустите приложение, откройте адрес http://localhost:5000/about:
Работа с базой данных
Для работы с базами данных в Flask удобно использовать ORM SQLAlchemy.
Как уже упоминалось в предыдущей главе о SQLite, ORM играет роль своеобразной прослойки между приложением и СУБД SQLite, и позволяет работать
с базами без использования языка SQL. Надо заметить, что работать с базами данных в SQLAlchemy
немного сложнее, чем в Django ORM,
но гораздо проще, чем в чистом Python.
Начнем с установки SQLAlchemy в виртуальное окружение:
pip install flask-sqlalchemy
В SQLAlchemy основой для создания таблиц в базе данных
служат модели (специальные классы). Поля классов определяют структуру таблицы, которая будет
использоваться для хранения информации в базе данных. В полях классов можно
задавать типы данных, которые соответствуют типам данных в БД,
например, String для хранения строк, Integer для целых чисел, Float для
плавающих чисел и т.д.
SQLAlchemy, как и другие ORM, очень упрощает создание связей между таблицами. В
приведенном ниже примере используется связь один ко многим (ForeignKey),
поскольку у одного исполнителя может быть несколько альбомов, а в одном альбоме
всегда будет несколько треков:
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
class Artist(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(100), nullable=False)
class Album(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(100), nullable=False)
year = db.Column(db.String(4), nullable=False)
artist_id = db.Column(db.Integer, db.ForeignKey('artist.id'), nullable=False)
artist = db.relationship('Artist', backref=db.backref('albums', lazy=True))
class Song(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(100), nullable=False)
length = db.Column(db.String(4), nullable=False)
track_number = db.Column(db.Integer, nullable=False)
album_id = db.Column(db.Integer, db.ForeignKey('album.id'), nullable=False)
album = db.relationship('Album', backref=db.backref('songs', lazy=True))
Сохраните этот код в файле models.py – мы будем импортировать модели из него в главный файл приложения app.py и в скрипт create_db.py, который создает базу данных и заполняет ее тестовой информацией.
Код для create_db.py будет следующим:
from flask import Flask
from models import Artist, Album, Song, db
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///music.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db.init_app(app)
if __name__ == '__main__':
with app.app_context():
db.create_all()
# создаем тестовых исполнителей
artist1 = Artist(name='The Rolling Stones')
artist2 = Artist(name='Jefferson Airplane')
artist3 = Artist(name='Nine Inch Nails')
artist4 = Artist(name='Tool')
db.session.add_all([artist1, artist2, artist3, artist4])
db.session.commit()
# создаем тестовые альбомы
album1 = Album(title='Aftermath', year='1966', artist=artist1)
album2 = Album(title='Beggars Banquet', year='1968', artist=artist1)
album3 = Album(title='Surrealistic Pillow', year='1967', artist=artist2)
album4 = Album(title='Broken', year='1992', artist=artist3)
album5 = Album(title='The Fragile', year='1999', artist=artist3)
album6 = Album(title='Lateralus', year='2001', artist=artist4)
album7 = Album(title='AEnima', year='1996', artist=artist4)
album8 = Album(title='10,000 Days', year='2006', artist=artist4)
# создаем тестовые песни
song1 = Song(title='Paint it Black', length='4:20', track_number=1, album=album1)
song2 = Song(title='Sympathy For The Devil', length='3:53', track_number=2, album=album1)
song3 = Song(title='White Rabbit', length='3:42', track_number=5, album=album3)
song4 = Song(title='Wish', length='3:46', track_number=6, album=album4)
song5 = Song(title='Starfuckers, Inc.', length='5:00', track_number=1, album=album5)
song6 = Song(title='Schism', length='6:46', track_number=7, album=album6)
song7 = Song(title='Eulogy', length='8:29', track_number=3, album=album7)
song8 = Song(title='Vicarious', length='7:07', track_number=5, album=album8)
db.session.add_all([album1, album2, album3, album4, album5, album6, album7, album8, song1, song2, song3, song4, song5, song6, song7, song8])
db.session.commit()
Этот код наглядно демонстрирует, как именно создаются
записи, и какие между ними существуют связи. Чтобы создать и заполнить базу,
запустите файл в активированном виртуальном окружении:
(venv) C:\Users\User\fproject>create_db.py
В реальных приложениях базу данных удобнее заполнять,
например, с помощью модуля csv – мы рассмотрим этот метод ниже, в одном из заданий.
Главный файл приложения app.py
выглядит так:
from flask import Flask, render_template
from models import Artist, Album, Song, db
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///music.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
# связываем приложение и экземпляр SQLAlchemy
db.init_app(app)
@app.route('/songs')
def songs():
songs_list = Song.query.all()
return render_template('songs.html', songs=songs_list)
if __name__ == '__main__':
app.run(debug=True)
Шаблон songs.html использует
тот же самый базовый base.html, что и предыдущий
пример:
{% extends 'base.html' %}
{% block title %}
Мои любимые песни
{% endblock %}
{% block content %}
<h1 class="mb-5">Мои любимые песни</h1>
<div class="card-columns">
<div class="row">
{% for song in songs %}
<div class="col-md-3">
<div class="card mb-3">
<div class="card-header fw-bold">{{ song.title }}</div>
<div class="card-body">
<p class="badge bg-primary text-wrap">{{ song.album.artist.name }}</p>
<p class="card-text">Альбом:
<strong>{{ song.album.title }}</strong></p>
<p class="card-text">Длина: {{ song.length }} минут</p>
<p class="card-text">Номер трека: {{ song.track_number }}</p>
<p class="card-text">Дата релиза: {{ song.album.year }}</p>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
{% endblock %}
После создания шаблона можно запустить приложение:
Практика
Задание 1
Напишите Flask-приложение,
которое выводит в шаблон index.html приветствие для
пользователя. Приветствие зависит от времени суток:
- С 6:00 до 12:00 – «Доброе утро»
- С 12:00 до 18:00 – «Добрый день»
- С 18:00 до 24:00 – «Добрый вечер»
- С 00:00 до 6:00 – «Доброй ночи»
Пример:
Решение:
Код для app.py выглядит
так:
from flask import Flask, render_template
import datetime
app = Flask(__name__)
@app.route('/')
def index():
now = datetime.datetime.now()
if now.hour >= 6 and now.hour < 12:
greeting = 'Доброе утро'
elif now.hour >= 12 and now.hour < 18:
greeting = 'Добрый день'
elif now.hour >= 18 and now.hour < 24:
greeting = 'Добрый вечер'
else:
greeting = 'Доброй ночи'
return render_template('index.html', greeting=greeting)
if __name__ == '__main__':
app.run(debug=True)
Для вывода приветствия используются шаблоны base.html и
index.html.
Задание 2
Напишите Flask-приложение, которое с помощью шаблона выводит пронумерованный список дел.
Пример:
Решение:
Это код приложения app.py:
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def task_list():
tasks = ["Выгулять собаку", "Погладить рубашку", "Зайти в супермаркет",
"Убрать на кухне", "Дописать статью", "Позвонить тимлиду"]
return render_template('task_list.html', tasks=tasks)
if __name__ == '__main__':
app.run()
Нумерацию в Jinja2
легко реализовать с помощью loop.index
:
<!DOCTYPE html>
<html>
<head>
<title>Мой список важных дел</title>
<style>
ul.no-bullets {
list-style-type: none;
}
</style>
</head>
<body>
<h1>Список дел на сегодня:</h1>
<ul class="no-bullets">
{% for task in tasks %}
<li>{{loop.index}}. {{ task }}</li>
{% endfor %}
</ul>
</body>
</html>
Задание 3
Напишите app.py и
шаблон welcome.html, которые выводят
различный контент для пользователей с разными правами доступа:
- Админ имеет полный доступ.
- Модератор может редактировать записи и комментарии.
- Рядовой пользователь может создавать записи от своего имени и просматривать френдленту.
Пример:
Решение:
В приложении app.py можно
определить только маршрут, вся функциональность по определению уровней доступа
находится в шаблоне:
<!DOCTYPE html>
<html>
<head>
<title>Личный кабинет</title>
</head>
<body>
{% if user_level == 'admin' %}
<h1>Привет, админ!</h1>
<p>У тебя есть доступ ко всем настройкам.</p>
<a href="#">Редактирование профилей</a>
<a href="#">Создание учетных записей</a>
<a href="#">Публикация статей</a>
{% elif user_level == 'moderator' %}
<h1>Привет, модератор!</h1>
<p>У тебе есть доступ к редактированию записей.</p>
<a href="#">Редактирование записей</a>
<a href="#">Модерация комментариев</a>
{% else %}
<h1>Привет, пользователь!</h1>
<p>У тебя нет доступа к редактированию контента и настроек.</p>
<a href="#">Новая запись</a>
<a href="#">Записи друзей</a>
{% endif %}
</body>
</html>
Задание 4
Напишите скрипт для создания и заполнения базы данных SQLite данными о книгах из
файла books.json, а также app.py и
шаблоны, которые выводят:
- Карточки с информацией о книгах.
- Карточку отдельной книги.
Пример:
Решение:
Напишем модель
Book и скрипт,
который создает и заполняет базу из json-файла. Затем создадим app.py с
двумя маршрутами – для вывода всех
книг, и для вывода отдельной
книги:
Задание 5
Для онлайн-магазина нужно написать модуль, который поможет
сотрудникам сделать инвентаризацию. Приложение состоит из базы данных, в
которой таблицы связаны сложными отношениями:
- Каждый производитель (Manufacturer) поставляет несколько типов товаров (Category) – ноутбуки, наушники, смартфоны и так далее.
- Одну и ту же категорию товаров могут производить несколько компаний.
- В каждой категории может быть множество товаров (Item).
Нужно реализовать вывод всех товаров по поставщикам и по
категориям. Все данные о товарах находятся в файле info.csv.
Пример:
Решение:
Файл models.py, описывающий структуру
базы данных, выглядит так:
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
manufacturer_items = db.Table('manufacturer_items',
db.Column('manufacturer_id', db.Integer, db.ForeignKey('manufacturer.id'), primary_key=True),
db.Column('item_id', db.Integer, db.ForeignKey('item.id'), primary_key=True)
)
class Manufacturer(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50), nullable=False)
items = db.relationship('Item', secondary=manufacturer_items, backref=db.backref('manufacturers', lazy=True))
def __repr__(self):
return '<Manufacturer %r>' % self.name
class Category(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50), nullable=False)
items = db.relationship('Item', backref='category')
def __repr__(self):
return '<Category %r>' % self.name
class Item(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50), nullable=False)
description = db.Column(db.String(255), nullable=False)
price = db.Column(db.Float, nullable=False)
quantity = db.Column(db.Integer, nullable=False, default=0)
category_id = db.Column(db.Integer, db.ForeignKey('category.id'), nullable=False)
def __repr__(self):
return '<Item %r>' % self.
Для заполнения базы данными из файла info.csv напишем скрипт.
Приложение использует 4 шаблона:
- base.html
- index.html
- categories.html
- items.html
За вывод всех товаров определенного производителя в
отдельной категории отвечает эта функция:
@app.route('/<manufacturer>/<category>')
def show_items(manufacturer, category):
items = Item.query.join(Item.manufacturers).join(Item.category).\
filter(Manufacturer.name == manufacturer).\
filter(Category.name == category).all()
return render_template('items.html', manufacturer=manufacturer, category=category, items=items)
Задание 6
Для супермаркета нужно написать веб-приложение, которое
выводит список товаров на складе и позволяет добавлять новые.
Пример:
Решение:
Приложение состоит из файлов app.py, create_db.py и models.py.
Для добавления новых товаров используется шаблон add.html и
маршрут/функция add:
Задание 7
Для ветеринарной клиники нужно написать модуль учета
пациентов. В приложении должны быть функции добавления, редактирования и
удаления карточек.
Пример:
Решение:
Начнем с создания базы данных на основе моделей.
Функции add_patient,
edit_patient, delete_patient реализованы в приложении app.py.
Шаблоны add.html и
edit.html обеспечивают
добавление и редактирование карточек:
Задание 8
Напишите модуль аутентификации для Flask-приложения. Необходимо
реализовать:
- регистрацию;
- проверку учетных данных при входе;
- перенаправление на страницу профиля.
Пример:
Решение:
Проект включает в себя файлы app.py, create_db.py и models.py. Кроме того, модуль
использует шаблоны:
- base.html
- index.html
- login.html
- profile.html
- register.html
После регистрации и входа пользователь перенаправляется на страницу
своего профиля:
Задание 9
Напишите веб-приложение для хранения заметок. Необходимо
реализовать набор CRUD
операций – вывод, добавление, редактирование и удаление заметок. При создании
базы данных следует учесть, что заметка может относиться только к одной
категории, а в категории может быть множество заметок. На главной странице
выводятся все заметки, причем текст ограничивается первыми 300 символами.
Нажатие на ссылку «Далее» открывает страницу с полным текстом заметки.
Пример:
Решение:
База данных для приложения создается с помощью скрипта create_db.py на основе моделей.
CRUD операции
описаны в app.py. При нажатии на
название категории шаблон и маршрут category
выводят все заметки, относящиеся
к данной теме.
Задание 10
Напишите Flask приложение для
ведения блога. Каждая запись может иметь несколько тегов, но должна относиться
к одной категории. Как и в предыдущем задании, нужно реализовать просмотр отдельных
записей, добавление, редактирование и удаление постов. При выводе всех записей,
а также записей по категориям и тегам посты должны отображаться в порядке
убывания даты, т.е. самые новые находятся сверху.
Пример:
Решение:
Прежде всего разработаем
модели Tag, Category и
Post, а затем создадим
на их основе базу данных при помощи скрипта.
Приложение использует следующие шаблоны:
- base.html
- category.html
- delete_post.html
- edit_post.html
- index.html
- new_post.html
- post.html
- tag.html
CRUD операции реализованы в главном файле приложения app.py. Чтобы самые свежие
записи выводились первыми, в models.py мы
определили метод newest_first
. При нажатии на ссылку «Читать»
выводится полный текст записи:
Подведем итоги
Мы рассмотрели основные приемы разработки простых
веб-приложений на основе фреймворка Flask:
- Создание маршрутов и функций представления.
- Получение и обработку данных с фронтенда.
- CRUD операции.
- Основные возможности шаблонизатора Jinja2.
При создании приложений Flask для получения данных с фронтенда обычно используются формы WTF Forms.
В этой статье при решении заданий намеренно использовались HTML-формы – так процесс передачи и
обработки данных выглядит максимально понятно.
В следующей статье будем изучать NumPy.
Содержание самоучителя
- Особенности, сферы применения, установка, онлайн IDE
- Все, что нужно для изучения Python с нуля – книги, сайты, каналы и курсы
- Типы данных: преобразование и базовые операции
- Методы работы со строками
- Методы работы со списками и списковыми включениями
- Методы работы со словарями и генераторами словарей
- Методы работы с кортежами
- Методы работы со множествами
- Особенности цикла for
- Условный цикл while
- Функции с позиционными и именованными аргументами
- Анонимные функции
- Рекурсивные функции
- Функции высшего порядка, замыкания и декораторы
- Методы работы с файлами и файловой системой
- Регулярные выражения
- Основы скрапинга и парсинга
- Основы ООП: инкапсуляция и наследование
- Основы ООП: абстракция и полиморфизм
- Графический интерфейс на Tkinter
- Основы разработки игр на Pygame
- Основы работы с SQLite
- Основы веб-разработки на Flask
- Основы работы с NumPy
- Основы анализа данных с Pandas
***
Материалы по теме
- 🐍🥤 Flask за час. Часть 1: создаем адаптивный сайт для GitHub Pages
- 🐍📚 Создаем аналог LiveLib.ru на Flask. Часть 1: основы работы с SQLAlchemy
- 🐍⛩️🥤 Руководство для начинающих по шаблонам Jinja в Flask
Язык Python — это лёгкая дорога в программирование. А Flask помогает проложить путь в веб-разработку и научиться писать сайты с помощью Python. Получается, он такой же лёгкий, как и Python? Да, но есть нюансы.
В этой статье мы расскажем, что собой представляет фреймворк Flask, чем он лучше других и когда стоит выбрать именно его. А параллельно напишем свой первый небольшой сайт, где даже сможем публиковать посты.
Всё, что нужно знать о Flask в Python:
- Что это такое
- Чем он лучше других фреймворков
- Как установить Flask
- Как написать простой сайт
- Как создать блог
- Что нужно запомнить
Flask — это легковесный веб-фреймворк для языка Python, который предоставляет минимальный набор инструментов для создания веб-приложений. На нём можно сделать и лендинг, и многостраничный сайт с кучей плагинов и сервисов. Не фреймворк, а мечта!
У Flask много преимуществ, которые выделяют его среди других фреймворков:
- простой синтаксис — это всё-таки Python;
- удобные шаблоны — можно быстро создавать прототипы веб-приложений;
- куча инструментов для гибкой настройки сайтов под любые нужды.
Изображение: Wikimedia Commons
Ещё под Flask написаны сотни расширений и плагинов, которые добавляют дополнительные возможности — разные виды аутентификации, управление базами данных и работу с формами. И всё это — бесплатно и с открытым кодом.
Скачать фреймворк можно на официальном сайте. А если появятся вопросы по установке или настройке, то на помощь всегда придёт огромное сообщество Flask-разработчиков.
Flask входит в топ-15 самых популярных фреймворков для веб-разработки среди опытных программистов. Рядом с ним в рейтинге находятся Django, Express.js, Laravel, Ruby on Rails, Spring и ASP.NET. И, конечно, на Flask написано немало популярных сайтов. Вот лишь несколько примеров:
- Pinterest — одна из крупнейших социальных сетей для обмена изображениями и идеями;
- Netflix — один из крупнейших сервисов видеостриминга в мире;
- Uber — сервис вызова такси и автомобильного транспорта;
- Reddit — один из самых популярных новостных UGC-агрегаторов;
- Twilio — платформа для разработки приложений для обмена сообщениями.
В общем, его используют везде: и в малом, и в крупном бизнесе, и на частных предприятиях, и в госучреждениях.
У Flask есть ряд особенностей, за которые его любят веб-разработчики. Давайте их перечислим:
- Минимальный набор инструментов из коробки. Причём они не навязывают какую-то архитектуру или жёсткую структуру проектов. Разработчики сами решают, как и что они будут создавать.
- Гибкость. Работая с Flask, программист может выбирать только необходимые встроенные инструменты и подключать дополнительные внешние, не перегружая проект лишними модулями.
- Расширяемость. У Flask много расширений и плагинов, которые помогают быстро добавить новую функциональность. Например, авторизацию, управление базами данных и работу с формами.
- Простота. У Flask простой синтаксис, что делает изучение этого фреймворка более простым, а также позволяет быстрее создавать прототипы веб-приложений.
- Поддержка сообщества. Flask запустили в 2010 году, и почти по любому связанному с ним вопросу в интернете уже есть ответы.
В общем, Flask как будто бы создан для новичков. Он несложен, в нём есть все необходимые базовые функции и возможности для расширения. Но при этом Flask может показаться слабеньким фреймворком, непригодным для крупных проектов. Кстати, это тоже можно исправить сторонними плагинами и библиотеками.
Чтобы освоить азы Flask, в этой статье мы создадим небольшой сайт-блог и объясним главные концепции фреймворка в деле. Начнём с установки.
Чтобы установить Flask, сначала нужно установить Python. Приступим.
Flask требует наличия Python версии 3.5 или выше. Если у вас нет Python, его можно загрузить с официального сайта Python. Подробную инструкцию можно посмотреть в нашем гайде по установке Python для всех операционных систем.
Если вы скачиваете официальную версию Python или пакет Anaconda, у вас автоматически установится PIP. Это менеджер пакетов для Python, который позволяет управлять сторонними библиотеками. Нам он понадобится, чтобы установить Flask.
Чтобы проверить, есть ли у вас PIP, введите в консоли:
pip --version
или
python3 -m pip --version
В ответ на экран выведется версия PIP. Если ничего не происходит, значит, PIP у вас не установлен. Исправим это:
python -m ensurepip --default-pip
Снова проверим, появился ли в системе менеджер пакетов. Если всё равно что-то не получается, попробуйте найти решение проблемы на Stack Overflow — или обратитесь к астрологу
Теперь поставим сам Flask. Делается это очень просто:
pip install Flask
Начнётся процесс загрузки Flask, после которого он будет готов к использованию. Если вам нужна конкретная версия Flask, установить её можно, указав её номер с помощью дополнительного параметра ==<version>.
pip install Flask==<version>
Например, мы можем установить версию 2.0.1:
pip install Flask==2.0.1
Чтобы проверить, работает ли Flask, введём следующую команду:
pip show flask
или создадим Python-файл и впишем туда такую строку:
import flask
Теперь запустим интерпретатор и убедимся, что программа исполняется без ошибок.
Приступим к коду. Для начала нам понадобится основа для приложения. Создадим новый файл с именем app.py. Это и будет наше Flask-приложение.
На первом этапе импортируем класс Flask из библиотеки Flask:
from flask import Flask
Затем создадим экземпляр класса Flask:
app = Flask(__name__)
Здесь мы передаем аргумент __name__ конструктору класса, этот аргумент скажет Flask, где находится наше приложение. Так Flask сможет определить местоположение шаблонов и статических файлов, о которых речь пойдёт дальше. Если вы ещё не особо знакомы с классами в Python, советуем прочитать нашу статью об объектно-ориентированном программировании на Python.
Весь бэкенд строится на маршрутах — или URL-адресах. Они помогают задавать удобную структуру и понятное поведение веб-приложениям.
Для пользователя маршруты — это отдельные «вкладки» на сайте. Например, если зайти на сайт Skillbox, откроется его главная страница www.skillbox.ru. А если кликнуть на любой курс, мы перейдём на другую страницу сайта с другим URL-адресом, таким как www.skillbox.ru/course/profession-python. Видим, что к адресу нашего сайта добавился текст: /course/profession-python/. Эта «приписка» и перенесла нас на другую страницу с другим содержимым. Получается, маршруты позволяют создавать разные страницы с разным наполнением в рамках одного сайта.
Чтобы задать маршрут во Flask, нужно написать следующее:
@app.route('/') def hello_world(): return 'Hello, World!'
Так мы создали URL-адрес главной страницы сайта. Например, для Skillbox главной страницей будет www.skillbox.ru. Тут мы мысленно можем дописать слеш: www.skillbox.ru/.
Сам маршрут задаётся в строке @app.route(‘/’). Внутрь круглых скобочек мы по ходу статьи будем вписывать разные маршруты, а пока нам хватит стандартного.
Внутрь маршрута мы поместили функцию hello_world(), которая будет выполняться при обращении к корневому URL, или главной странице нашего сайта (ведь наш маршрут ведёт именно на неё). Функция возвращает строку Hello, World! в браузере.
Теперь нам нужно запустить приложение:
if __name__ == '__main__': app.run()
Этот код гарантирует, что сервер Flask будет запущен только в том случае, если файл app.py был запущен напрямую, а не импортирован как модуль.
Сохраняем файл app.py и запускаем его с помощью команды в консоли:
python app.py
После запуска вы должны увидеть сообщение о том, что сервер Flask был запущен:
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
Чтобы взглянуть на работу нашего приложения, нужно перейти по адресу, который был указан в консоли — http://127.0.0.1:5000/. Вот что мы там увидим:
Ликуем — у нас всё получилось, сайт работает. Дальше будем усложнять наше приложение и начнём создавать блог.
Чтобы создать блог, одним простым приложением уже не обойтись, придётся научиться использовать HTML-шаблоны и подключать базу данных.
В дальнейшем мы будем использовать наш базовый код из предыдущего раздела. Полностью он выглядит так:
app.py
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello, World!'
if __name__ == '__main__':
app.run()
HTML-шаблоны — это файлы, которые задают структуру и содержимое страниц сайта. Шаблоны упрощают жизнь программистам — им не приходится десятки раз писать один и тот же HTML-код, ведь его можно просто взять и… шаблонизировать.
Ещё немного об HTML-шаблонах
HTML-шаблоны позволяют создавать динамические веб-страницы с помощью заготовленных блоков, которые мы можем настраивать и использовать повторно. Шаблоны помогают избежать дублирования кода и облегчают поддержку приложения, так как мы можем легко изменять отображение страниц, не затрагивая внутреннюю логику. Например, в нашем медиа о программировании оформление всех статей очень похоже: структура, внешние по отношению к статье элементы и тому подобное — это возможно как раз благодаря шаблонам.
Например, можно использовать один и тот же базовый шаблон для всех страниц сайта и переопределять блоки контента для каждой страницы. В таком случае, если нам понадобится изменить дизайн всего сайта, мы можем изменить только базовый шаблон, а все страницы обновятся автоматически, без дополнительных усилий.
Если вы не знаете, как писать HTML-код, советуем прочитать нашу статью об HTML. А теперь создадим HTML-шаблоны: выделим под них папку templates и добавим в неё файл base.html со следующим содержимым:
<!DOCTYPE html> <html> <head> <title>{% block title %}{% endblock %}</title> </head> <body> {% block content %}{% endblock %} </body> </html>
Этот шаблон будет отправной точкой для всех остальных HTML-страниц. В нём мы прописали заголовок:
<head> <title>{% block title %}{% endblock %}</title> </head>
и основной контент (тело) страницы:
<body> {% block content %}{% endblock %} </body>
Вы, наверное, уже обратили внимание на странные элементы, а точнее теги {% block %} и {% endblock %}. Они как раз нужны, чтобы динамически добавлять туда новые элементы: другие HTML-блоки, JavaScript-код и тому подобное.
Теперь давайте создадим второй шаблон и назовём его index.html. Он будет наследовать элементы базового шаблона:
{% extends "base.html" %} {% block title %}Home{% endblock %} {% block content %} <h1>Welcome to my website!</h1> <p>This is the homepage.</p> {% endblock %}
Этот шаблон переопределяет заголовок страницы и определяет контент, который будет отображаться на домашней странице: заголовок страницы Home и немного текста.
Пришло время воспользоваться шаблонами. Изменим файл app.py и импортируем функцию render_template из библиотеки Flask, которая позволяет работать с шаблонами:
from flask import Flask, render_template
Изменим маршрут главной страницы и используем в нём новую функцию, чтобы отобразить шаблон index.html:
@app.route('/') def index(): return render_template('index.html')
Сохраним изменения в файлах app.py, index.html и base.html, а затем снова запустим наше приложение:
python app.py
Открываем браузер и переходим по адресу http://127.0.0.1:5000/. У нас отобразится содержимое шаблона index.html:
Чтобы вести блог, нужно куда-то сохранять все посты, картинки, видео и тому подобное. Куда-то — это в базу данных. Баз данных существует немало, мы даже написали про них отдельную статью. Но если коротко — база данных нужна, чтобы удобно хранить, обрабатывать и сохранять данные.
Мы будем использовать базу данных SQLite, потому что она занимает совсем немного места, легка в освоении и вообще клёвая. А главный плюс — её не нужно скачивать отдельно, потому что она сразу есть в Python.
Займёмся привычным делом — импортируем модуль SQLite3:
import sqlite3
Теперь мы можем создать функцию, которая будет подключать нас к базе данных и возвращать объект подключения:
def get_db_connection(): conn = sqlite3.connect('database.db') conn.row_factory = sqlite3.Row return conn
Эта функция создаст подключение к базе данных database.db и установит режим получения результатов запросов в виде словаря Row, что позволит обращаться к столбцам базы данных по их именам.
Другими словами — наши данные будут храниться в виде таблицы, где каждая строка — уникальный пост, а каждый столбец (или ячейка) — информация об этом посте, например, сам текст, количество лайков, автор и так далее.
Но ещё нам понадобится функция, которая будет закрывать подключение к базе данных:
def close_db_connection(conn):
conn.close()
Теперь мы можем использовать эти функции для выполнения запросов к базе данных внутри нашего приложения. Обновим функцию index(), чтобы она получала все записи из таблицы posts:
@app.route('/') def index(): conn = get_db_connection() posts = conn.execute('SELECT * FROM posts').fetchall() conn.close() return render_template('index.html', posts=posts)
Здесь мы получаем подключение к базе данных с помощью функции get_db_connection(), выполняем запрос к таблице posts и получаем все записи, используя метод fetchall(). Затем мы закрываем подключение с помощью функции close_db_connection() и передаём полученные записи в шаблон index.html с помощью функции render_template().
Но перед тем как использовать базу данных, её нужно инициализировать и создать таблицу posts.
У нашего учебного поста будет три поля с данными: уникальный идентификатор (ID), заголовок и текст поста. Назовём их соответственно — id, title и content:
def init_db(): conn = get_db_connection() conn.execute('CREATE TABLE IF NOT EXISTS posts (id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT NOT NULL, content TEXT NOT NULL)') conn.close()
Функция execute() создаст нам таблицу posts с полями id, title и content. У каждого из этих полей будет собственный тип данных: целое число, строка и строка соответственно.
Мы задали полю id специальный параметр AUTOINCREMENT, чтобы при добавлении нового поста его айдишник автоматически увеличивался на 1. А параметр PRIMARY KEY нужен для уточнения, что строки в таблице уникальные и не пустые.
Инициализировать базу данных нужно в самом начале. Во Flask мы можем сделать это перед первым запросов к базе данных с помощью следующего кода:
@app.before_first_request
def before_first_request():
init_db()
Здесь мы используем декоратор @app.before_first_request, который указывает, что функция before_first_request() вызывается перед тем, как запустится рендер шаблонов.
Готово — наше приложение подключено к базе данных SQLite, а мы можем переходить дальше. Но сперва убедимся, что всё работает. Сохраняем изменения и запускаем приложение:
python app.py
Если перейти по адресу http://127.0.0.1:5000/, то может показаться, что ничего не изменилось. Но если посмотреть в папку с файлами, то можно увидеть там новый файл — database.db. Это и есть наша база данных.
Настало время сделать новый и прекрасный шаблон — для постов. Он будет простым: заголовок, текст и ссылка на главную страницу. Создадим в папке templates файл post.html и добавим следующий код:
<!DOCTYPE html> <html> <head> <title>{{ post.title }}</title> </head> <body> <h1>{{ post.title }}</h1> <p>{{ post.content }}</p> <a href="{{ url_for('index') }}">Back to index</a> </body> </html>
В момент рендеринга в эту HTML-страницу мы будем передавать пост, который достали из базы данных. У этого поста будут заголовок (title) и основной текст (content), а всё вместе будет лежать внутри объекта post.
Пока всё просто, но обратите внимание на новую функцию — url_for(). Она позволяет перейти на другой маршрут и отрисовать другую HTML-страницу. В нашем случае, если мы нажмём на ссылку Back to index, запустится функция index(), которая перенаправит нас на главную страницу (маршрут /) и отрисует шаблон index.html.
Теперь нам нужно сделать новый маршрут под один из постов в файле app.py:
@app.route('/<int:post_id>') def get_post(post_id): conn = get_db_connection() post = conn.execute('SELECT * FROM posts WHERE id = ?', (post_id,)).fetchone() conn.close() return render_template('post.html', post=post)
Тут уже всё немного сложнее, но обо всём по порядку:
- @app.route(‘/<int:post_id>’) — задаём новый маршрут. Он будет выглядеть так: www.oursite.com/1. Единица будет указывать на индекс поста из базы данных. <int:post_id> — это ещё одно указание на то, что индекс поста должен быть целым числом (int), а не, например, строкой.
- get_post(post_id) — передаём айдишник поста, который как раз и «встанет» в URL-адрес и добавится к запросу к базе данных.
- post = conn.execute (‘SELECT * FROM posts WHERE id =? ‘, (post_id,)).fetchone() — запрашиваем из базы данных пост по нашему айдишнику и берём одну строку функцией fetchone().
- return render_template (‘post.html’, post=post) — рендерим HTML-шаблон и передаём туда полученный пост.
Давайте убедимся, что всё работает корректно и страница отрисовывается. Временно напишем «костыль» и вручную добавим пост (исключительно для проверки):
@app.route('/<int:post_id>') def get_post(post_id): conn = get_db_connection() conn.execute('INSERT INTO posts (title, content) VALUES ("Random Title", "Lorem ipsum dolor sit amet consectetur adipiscing elit")') post = conn.execute('SELECT * FROM posts WHERE id = ?', (post_id,)).fetchone() conn.close() return render_template('post.html', post=post)
Наш «костыль» — это четвёртая строка. Здесь мы сами вставляем новую строку в базу данных с помощью запроса INSERT. Теперь перейдём по адресу http://127.0.0.1:5000/1:
Круто — всё отрисовалось, кнопка «Назад» работает! Идём дальше и не забываем удалить «костыль».
Дополним файл index.html и создадим список, в котором будут находиться все посты из базы данных:
<!DOCTYPE html> <html> <head> <title>Blog</title> </head> <body> <h1>Blog</h1> <ul> {% for post in posts %} <li><a href="{{ url_for('get_post', post_id=post['id']) }}">{{ post['title'] }}</a></li> {% endfor %} </ul> </body> </html>
Главный движ у нас происходит в теге <ul>: мы идём по всем элементам списка posts и для каждого создаём заголовок со ссылкой на пост. При нажатии на ссылку вызывается функция url_for(), а ей передаётся функция-рендер get_post() и ID поста.
Ещё мы немного декорировали заголовок самой страницы. Можете сравнить с прошлой версией.
Если перезапустить приложение, то мы не увидим новых постов, потому что их просто нет в базе данных. Но можно опять заполнить всё вручную. Изменим функцию index():
@app.route('/') def index(): conn = get_db_connection() conn.execute('INSERT INTO posts (title, content) VALUES ("Why I love Flask", "This is so cool!!!")') conn.execute('INSERT INTO posts (title, content) VALUES ("Cats >> Dogs", "It was a joke because they are all so adorable.")') posts = conn.execute('SELECT * FROM posts').fetchall() conn.close() return render_template('index.html', posts=posts)
Видим результат:
Правда, если перейти по ссылке, то ничего не отобразится, но и это мы со временем исправим.
Отображение постов работает, осталось добавить возможность создавать новые посты. Для этого создадим новый HTML-шаблон и метод для рендеринга.
В папке templates создаём новый файл add_post.html:
{% extends 'base.html' %} {% block content %} <h1>Add New Post</h1> {% with messages = get_flashed_messages() %} {% if messages %} <ul class="flashes"> {% for message in messages %} <li>{{ message }}</li> {% endfor %} </ul> {% endif %} {% endwith %} <form method="post"> <label for="title">Title</label><br> <input type="text" id="title" name="title"><br> <label for="content">Content</label><br> <textarea id="content" name="content"></textarea><br> <input type="submit" value="Submit"> </form> {% endblock %}
Он будет наследовать файл base.html, а внутри содержать форму, где пользователь указывает заголовок и тело поста. Если он вдруг введёт некорректные данные, то мы покажем ему сообщение об ошибке с помощью флеш-сообщений (когда некорректно заполненное поле подсвечивается красным и у вас нет возможности отправить заполненную форму).
Теперь добавим новый маршрут в файл app.py:
@app.route('/new', methods=['GET', 'POST']) def new_post(): if request.method == 'POST': title = request.form['title'] content = request.form['content'] conn = get_db_connection() conn.execute('INSERT INTO posts (title, content) VALUES (?, ?)', (title, content)) conn.commit() conn.close() return redirect(url_for('index')) return render_template('add_post.html')
Этот маршрут обрабатывает GET- и POST-запросы по адресу /new. Если запрос выполняется методом GET, то функция просто отображает форму для ввода данных с помощью шаблона add_post.html. А если запрос выполняется методом POST, мы достаём заголовок и тело поста из формы, а затем добавляем их в базу данных. В конце — редиректим (то есть перенаправляем) пользователя обратно на главную.
Подробнее об HTTP-запросах вы можете прочитать в нашей статье.
Чтобы все эти функции работали, мы также должны их импортировать в начале файла:
from flask import Flask, render_template, request, redirect, url_for
Теперь давайте сохраним свои наработки и запустим приложение:
python app.py
Переходим по адресу http://127.0.0.1:5000/ и видим, что опять ничего не изменилось:
Попробуем перейти по адресу http://127.0.0.1:5000/new:
Ура! Мы видим нашу форму! Давайте впишем туда что-нибудь и нажмём Submit:
Нас перекинуло на главную страницу — и на ней находится наш новый пост. Ура! Всё наконец-то работает!
К тому же теперь мы можем перейти по ссылке и посмотреть пост целиком:
Но всё ещё есть проблема — нужно добавить кнопку Add new post, чтобы каждый раз не добавлять пост, вбивая в адресную строку наш URL. Для этого нам нужно добавить всего одну строчку в файл index.html:
<!DOCTYPE html> <html> <head> <title>Blog</title> </head> <body> <h1>Blog</h1> <a href="{{ url_for('new_post') }}"><button>Add New Post</button></a> <ul> {% for post in posts %} <li><a href="{{ url_for('get_post', post_id=post['id']) }}">{{ post['title'] }}</a></li> {% endfor %} </ul> </body> </html>
Мы создали кнопку, нажав которую, мы перейдём на страницу со ссылкой для создания нового поста. Проверяем:
Кликаем — переходим куда нужно:
Добавили новый пост:
Наше приложение приобрело следующую структуру:
Blog Flask/ |-- templates/ | |-- index.html | |-- base.html | |-- post.html | |-- add_post.html |-- app.py |-- database.db
В папке templates хранятся HTML-шаблоны: index.html, add_post.html, post.html и base.html. Файл app.py содержит основной код приложения Flask, в котором определены маршруты и функции для работы с базой данных. А файл database.db — это база данных SQLite.
Полный код каждого файла можно посмотреть ниже:
index.html:
<!DOCTYPE html>
<html>
<head>
<title>Blog</title>
</head>
<body>
<h1>Blog</h1>
<a href="{{ url_for('new_post') }}"><button>Add New Post</button></a>
<ul>
{% for post in posts %}
<li><a href="{{ url_for('get_post', post_id=post['id']) }}">{{ post['title'] }}</a></li>
{% endfor %}
</ul>
</body>
</html>
base.html:
<!DOCTYPE html>
<html>
<head>
<title>{% block title %}{% endblock %}</title>
</head>
<body>
{% block content %}{% endblock %}
</body>
</html>
post.html:
<!DOCTYPE html>
<html>
<head>
<title>{{ post.title }}</title>
</head>
<body>
<h1>{{ post.title }}</h1>
<p>{{ post.content }}</p>
<a href="{{ url_for('index') }}">Back to index</a>
</body>
</html>
add_post.html:
{% extends 'base.html' %}
{% block content %}
<h1>Add New Post</h1>
{% with messages = get_flashed_messages() %}
{% if messages %}
<ul class="flashes">
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
<form method="post">
<label for="title">Title</label><br>
<input type="text" id="title" name="title"><br>
<label for="content">Content</label><br>
<textarea id="content" name="content"></textarea><br>
<input type="submit" value="Submit">
</form>
{% endblock %}
app.py:
from flask import Flask, render_template, request, redirect, url_for
import sqlite3
app = Flask(__name__)
def get_db_connection():
conn = sqlite3.connect('database.db')
conn.row_factory = sqlite3.Row
return conn
def close_db_connection(conn):
conn.close()
def init_db():
conn = get_db_connection()
conn.execute('CREATE TABLE IF NOT EXISTS posts (id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT NOT NULL, content TEXT NOT NULL)')
conn.close()
@app.route('/')
def index():
conn = get_db_connection()
posts = conn.execute('SELECT * FROM posts').fetchall()
conn.close()
return render_template('index.html', posts=posts)
@app.route('/<int:post_id>')
def get_post(post_id):
conn = get_db_connection()
post = conn.execute('SELECT * FROM posts WHERE id = ?', (post_id,)).fetchone()
conn.close()
return render_template('post.html', post=post)
@app.route('/new', methods=['GET', 'POST'])
def new_post():
if request.method == 'POST':
title = request.form['title']
content = request.form['content']
conn = get_db_connection()
conn.execute('INSERT INTO posts (title, content) VALUES (?, ?)', (title, content))
conn.commit()
conn.close()
return redirect(url_for('index'))
return render_template('add_post.html')
@app.before_first_request
def before_first_request():
init_db()
if __name__ == '__main__':
app.run()
Наш блог полностью готов к работе. В него можно добавлять новые функции (например, редактирование постов или систему авторизации), а также применять CSS-стили, чтобы он выглядел красивее. Но главное — мы заложили основу для бэкенда и разобрались, как это сделать на Flask.
Вот некоторые важные вещи, которые стоит помнить при работе с фреймворком Flask:
- Flask — это микрофреймворк для создания веб-приложений на языке Python.
- Flask использует декораторы для связывания функций с URL-адресами и методами HTTP.
- Чтобы удобно отображать HTML-страницы, можно использовать шаблоны, которые упрощают разработку.
- Flask не имеет встроенной поддержки баз данных, но к нему всегда можно подключить сторонние — например, SQLite.
- Flask использует объект request для доступа к данным, отправленным пользователем через формы и URL-адреса.
- Flask использует флеш-сообщения для отображения сообщений об ошибках или на веб-странице.
Введение
Создание собственного сайта на Python может показаться сложной задачей, но с правильным подходом и инструментами каждый разработчик сможет освоить этот процесс. Python предлагает мощные и гибкие инструменты для веб-разработки, что делает его отличным выбором как для новичков, так и для опытных разработчиков. В этой статье мы рассмотрим ключевые шаги создания сайта на Python, начиная с подготовки окружения и заканчивая деплоем приложения. Вы узнаете о наиболее популярных фреймворках, таких как Django и Flask, и получите примеры кода, которые помогут вам создать первый веб-сайт.
Подготовка к разработке
1.1 Выбор фреймворка
Когда речь идет о веб-разработке на Python, на ум сразу приходят два основных фреймворка — Django и Flask.
-
Django:
-
Преимущества: Встроенная административная панель, ORM, аутентификация пользователей из коробки.
-
Недостатки: Может казаться «тяжелым» для небольших проектов, высокая кривой обучения.
-
Flask:
-
Преимущества: Легкость и минимализм, гибкость в выборе инструментов и библиотек.
-
Недостатки: Требует больше ручной работы для реализации базовых функций.
1.2 Установка необходимых инструментов
Перед началом работы необходимо установить Python и pip (менеджер пакетов). Убедитесь, что у вас установлена последняя версия Python.
$ sudo apt update
$ sudo apt install python3 python3-pip
1.3 Создание виртуального окружения
Использование виртуального окружения позволяет изолировать зависимости проекта.
$ python3 -m venv myenv
$ source myenv/bin/activate # Для Windows используйте myenv\Scripts\activate
Создание базовой структуры проекта
2.1 Настройка проекта
Каждый проект имеет свою структуру каталогов. В примере ниже показана базовая структура.
my_project/
├── app/
│ ├── static/
│ ├── templates/
│ ├── __init__.py
│ └── routes.py
├── venv/
├── config.py
└── run.py
2.2 Создание первых маршрутов
Пример простого маршрута на Flask:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def home():
return "Hello, World!"
if __name__ == '__main__':
app.run(debug=True)
2.3 Добавление статических файлов и шаблонов
Статические файлы (CSS и JavaScript) и HTML-шаблоны должны располагаться в соответствующих каталогах.
<!-- templates/index.html -->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Hello, Flask!</title>
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
</head>
<body>
<h1>Hello, Flask!</h1>
</body>
</html>
Работа с базой данных
3.1 Выбор СУБД
Среди популярных СУБД для Python можно выделить SQLite и PostgreSQL.
3.2 Настройка ORM
SQLAlchemy — одна из самых популярных ORM в мире Python.
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
Base = declarative_base()
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String)
DATABASE_URL = "sqlite:///./test.db"
engine = create_engine(DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base.metadata.create_all(bind=engine)
3.3 Создание и выполнение запросов
from sqlalchemy.orm import Session
from pathlib import Path
# Наполнение базы данных
def add_user_to_db(name: str):
with Session(bind=engine) as session:
new_user = User(name=name)
session.add(new_user)
session.commit()
add_user_to_db("John Doe")
Разработка пользовательского интерфейса
4.1 Создание форм
Для создания формы можно использовать HTML и библиотеки, такие как WTForms.
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField
from wtforms.validators import DataRequired
class NameForm(FlaskForm):
name = StringField('Name', validators=[DataRequired()])
submit = SubmitField('Submit')
4.2 Валидация данных
Пример настройки валидации формы:
class RegistrationForm(FlaskForm):
username = StringField('Username', validators=[DataRequired()])
password = PasswordField('Password', validators=[DataRequired()])
submit = SubmitField('Register')
4.3 Обработка действий пользователя
Пример обработки формы:
@app.route('/register', methods=['GET', 'POST'])
def register():
form = RegistrationForm()
if form.validate_on_submit():
flash(f'Account created for {form.username.data}!', 'success')
return redirect(url_for('home'))
return render_template('register.html', title='Register', form=form)
Тестирование и отладка
5.1 Автоматическое тестирование
Использование unittest для написания тестов:
import unittest
from app import app
class BasicTestCase(unittest.TestCase):
def test_home(self):
tester = app.test_client(self)
response = tester.get('/')
self.assertEqual(response.status_code, 200)
if __name__ == '__main__':
unittest.main()
5.2 Логирование ошибок
Использование встроенного модуля logging:
import logging
logging.basicConfig(filename='error.log', level=logging.ERROR)
@app.errorhandler(500)
def internal_error(error):
logging.error('Server Error: %s', (error))
return "500 error", 500
Деплой приложения
6.1 Подготовка к деплою
Перед деплоем необходимо убедиться, что все зависимости установлены, и приложение настроено для работы в продакшене.
6.2 Выбор хостинга
Некоторые популярные хосты для Python-приложений включают Heroku, AWS и DigitalOcean.
6.3 Настройка веб-сервера
Пример настройки Nginx для работы с Flask:
server {
listen 80;
server_name mysite.com;
location / {
include proxy_params;
proxy_pass http://unix:/path/to/yourapp.sock;
}
}
Заключение
Создание веб-сайта на Python — это захватывающее приключение, которое комбинирует в себе множество аспектов программирования. Мы рассмотрели основы настройки проекта, создание маршрутов и работу с базой данных, а также представили ключевые этапы работы с пользовательским интерфейсом и деплоем. Следующим шагом может быть изучение более сложных тем, таких как безопасность приложения, масштабирование и оптимизация. Удачи в вашем путешествии по миру веб-разработки на Python!
Приложение: Полезные ресурсы
- Документация Flask
- Документация Django
- Документация SQLAlchemy
- Книга «Flask Web Development» Мигеля Гринберга
- Книга «Django for Beginners» Уильяма Винсона
Овладейте указанными ресурсами, и вами не будет предела веб-разработки на Python.
Как создать сайт на Python: Полный гайд по Flask и Django
Создание собственного сайта — мечта многих начинающих программистов. Сегодня сделать это проще, чем когда-либо, особенно с помощью языка программирования Python. Благодаря мощным фреймворкам, таким как Flask и Django, вы можете создать как простую визитку, так и сложный веб-портал с административной панелью, базой данных и пользовательскими сессиями.
В этом руководстве разберёмся, как написать сайт на Python с нуля, используя Flask и Django. Вы узнаете, когда лучше использовать каждый из этих фреймворков и получите пошаговые инструкции по их установке и настройке.
Почему стоит выбрать Python для создания сайта?
-
Простота синтаксиса и высокий уровень абстракции.
-
Огромное сообщество и множество готовых решений.
-
Поддержка современных технологий: REST API, WebSockets, машинное обучение.
-
Наличие мощных фреймворков — Flask и Django.
Создание сайта с помощью Flask
📌 Что такое Flask?
Flask — это лёгкий и гибкий микрофреймворк для создания веб-приложений. Он идеально подходит для небольших проектов, прототипов и учебных целей.
✅ Шаг 1. Установка Flask
✅ Шаг 2. Простой сайт на Flask
Создайте файл app.py
:
Запустите сервер командой:
Перейдите в браузер и откройте http://127.0.0.1:5000 — сайт готов!
✅ Работа с Flask Session (Сессиями)
Сессии позволяют сохранять данные между запросами пользователя.
Создание сайта с помощью Django
📌 Что такое Django?
Django — это полноценный фреймворк для разработки сложных веб-приложений. Он включает в себя всё необходимое: ORM для работы с базами данных, систему маршрутизации, административную панель, поддержку сессий и пользователей.
✅ Шаг 1. Установка Django
✅ Шаг 2. Создание проекта
Запуск сервера:
Перейдите в браузер по адресу http://127.0.0.1:8000. Вы увидите стартовую страницу Django.
✅ Шаг 3. Создание приложения
Зарегистрируйте приложение в mysite/settings.py
:
Создайте представление в blog/views.py
:
Настройте маршруты в mysite/urls.py
:
Перейдите по адресу http://127.0.0.1:8000 и увидите страницу с текстом «Добро пожаловать в блог!».
✅ Как запустить сервер Django на продакшене?
-
Используйте команду:
-
Для реального развертывания применяются инструменты Gunicorn, Nginx и Docker.
Flask или Django — что выбрать?
Критерий | Flask | Django |
---|---|---|
Сложность | Лёгкий старт | Более сложный |
Гибкость | Высокая | Жёсткая структура |
Размер проекта | Маленькие, средние | Средние, крупные |
Наличие админки | Нет (нужно писать) | Есть из коробки |
📌 Итог:
-
Flask подходит для стартапов, небольших проектов и обучения.
-
Django — для крупных проектов, интернет-магазинов и сложных систем.
FAQ — Часто задаваемые вопросы
❓ 1. Можно ли использовать и Flask, и Django в одном проекте?
Технически возможно, но смысла в этом мало. Обычно выбирают один фреймворк под конкретные задачи.
❓ 2. Что такое Flask Session?
Это механизм для хранения данных между запросами пользователя, например, информации о логине.
❓ 3. Как запустить сервер Django в production-режиме?
Используйте связку Gunicorn и Nginx. Пример команды для Gunicorn:
❓ 4. Что выбрать для создания интернет-магазина?
Рекомендуется Django, так как он обеспечивает быструю разработку сложных систем и имеет готовую административную панель.
❓ 5. Можно ли создать REST API с помощью Flask и Django?
Да, Flask часто используется с библиотекой Flask-RESTful, а в Django применяют Django REST Framework.
❓ 6. Какой фреймворк быстрее работает?
Flask работает быстрее на старте и с малыми нагрузками, но Django оптимальнее для масштабных решений благодаря встроенным инструментам.
Заключение
Теперь вы знаете, как создать сайт на Python с нуля, используя Flask или Django. Flask отлично подходит для быстрого старта и небольших проектов, в то время как Django предоставляет всё необходимое для разработки масштабных и надёжных веб-сервисов.
Выбирайте инструмент в зависимости от ваших целей, и не бойтесь экспериментировать. Создание сайтов на Python — это не только полезно, но и увлекательно!