Тарифы Услуги Сим-карты

Создание реактивных аналитических веб-приложений с использованием Python и библиотеки Dash

Я занимаюсь некоторой работой на python, но это все для автономных приложений. Мне любопытно узнать, поддерживает ли какое-либо ответвление python в веб-разработке?

Будет ли кто-то также предлагать хороший учебник или веб-сайт, откуда я могу забрать некоторые основы веб-разработки с помощью python?

9 Solutions collect form web for “Использование python для разработки веб-приложения”

Теперь, когда все сказали Django , я могу добавить свои два цента: я бы сказал, что вы можете узнать больше, сначала посмотрев на разные компоненты, прежде чем использовать Django. Для веб-разработки с Python вам часто нужны 3 компонента:

    Что-то, что заботится о HTTP-материале (например, CherryPy)

    Язык шаблонов для создания ваших веб-страниц. Мако очень pythonic и работает с Cherrpy.

    Если вы получаете данные из базы данных, ORM пригодится. Пример SQLAlchemy .

Все ссылки выше имеют хорошие учебные пособия. Для многих случаев использования в реальном времени Django будет лучшим решением, чем такой стек, поскольку он легко интегрирует эту функциональность (и многое другое). И если вам нужна CMS, Django – ваш лучший выбор, кроме Zope. Тем не менее, чтобы получить хорошее представление о том, что происходит, может быть лучше стека слабо связанных программ. Джанго скрывает много деталей.

Отредактировано 3 года спустя : Не используйте mod_python, используйте mod_wsgi. Flask и Werkzeug – хорошие рамки. Нужно знать, что происходит, полезно, но это не требование. Это было бы глупо.

Не просматривайте Django, пока вы не поймете, что Django делает от вашего имени. для тебя. Напишите некоторые базовые приложения, используя mod_python и объект запроса. Я только начал изучать Python для веб-разработки с помощью mod_python, и это было здорово.

mod_python также использует диспетчер в site-packages / mod_python / publisher.py. У вас есть ganders, чтобы увидеть, как запросы могут обрабатываться простым способом.

Возможно, вам потребуется добавить немного конфига в конфигурационный файл Apache, чтобы получить mod_python и запустить его, но сайт mod_python объясняет это хорошо.

AddHandler mod_python .py PythonHandler mod_python.publisher PythonDebug On

И ты далеко!

использовать (как тупо базовый пример):

Def foo(req): req.write("Hello World")

в /path/to/python/files/bar.py предполагается, что /path/to является вашим корнем сайта.

И тогда вы можете сделать

Http://www.mysite.com/python/files/bar/foo

увидеть «Hello World». Кроме того, что-то, что меня сбило с толку, – это диспетчер, использующий хромовый метод для разработки типа контента, поэтому для принудительного использования HTML:

Req.content_type = "text/html"

Удачи

После того, как вы хорошо поймете, как Python взаимодействует с mod_python и Apache, используйте фреймворк, который делает для вас все скучные вещи. До вас, хотя, только моя рекомендация

Если вы действительно не хотите вникать в рамки – и вы должны, я от всей души рекомендую Django или Pylons – по-прежнему нужно идти по дороге CGI. Это совершенно устаревшая технология, не говоря уже о медленных и неэффективных.

Существует стандартный способ создания веб-приложений Python, и он называется WSGI . Если вы хотите свернуть свое собственное веб-приложение с нуля, это абсолютно путь.

Тем не менее, если вы только начинаете, действительно вам стоит пойти с одной из фреймворков.

Python Wiki: веб-фреймворки для Python

Если вы решите использовать Django , официальный учебник станет отличным местом для начала. Книга Джанго также бесплатна.

Есть несколько вариантов для веб-разработки. По моему опыту, ваш выбор снова будет зависеть от вашего приложения. Я использовал django и web.py в производстве, и я собираюсь развернуть приложение на основе пилонов.

Django скрывает множество вариантов (поставляется с ORM и шаблонами). Документация обширна и хорошо написана. Для django доступно много многоразовых приложений, но вы, вероятно, потратите немного времени на их интеграцию. Одна вещь, упомянутая на djangocon 08, заключалась в том, что в джанго есть классные вещи, к которым нельзя легко получить доступ в проектах, не связанных с джанго.

web.py впечатлил меня своей простой простотой. Прежде чем я это узнал, я написал небольшое приложение (78 строк квази-вики).

пилоны чувствуют себя как в середине обоих. Я могу использовать sqlalchemy и jinja , и все это приятный опыт для начала.

Поиск Django.

Python может использоваться для веб-разработки, но не существует специального языкового расширения или чего-либо еще на языке, который будет обрабатывать все поколения HTML или работает как PHP.

В значительной степени он запускается через какой-то интерпретатор на веб-сервере (CGI, mod_python и т. Д.).

Существует много веб-фреймворков для python, но единственное, что я использовал, это Django , и мне это очень нравится.

Если у вас есть несколько часов, сделайте учебник, я обещаю вам, вам понравится 🙂

Как отмечали другие, одним из наиболее заметных «ответвлений» питона, как вы их называете, будет Django . Это довольно мощная структура, которая позволяет быстро и надежно создавать веб-приложения. Первое, что нужно посмотреть, это их обзор, который дает некоторое представление о том, что Django делает в качестве основы.

Пройдя через их учебник, я много рассказывал об известном шаблоне проектирования Model-View-Controler и о том, как он может использоваться в контексте веб-разработки. Я нашел отличный способ начать писать приложение, которое работало и училось, улучшив его.

В статье хотелось бы поднять вопросы отличия использования Python для web-зазработки по сравнению с оной на PHP. Надеюсь, статья не приведет к холиварам, так как она вовсе не о том, какой язык лучше или хуже, а исключительно о технических особенностях Python.

Немного о самих языках

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

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

Исходя из вышеописанных особенностей вытекают и различия в обработке ошибок в web-приложениях. В PHP существует целый зоопарк типов ошибок (errors, exceptions), далеко не каждую из которых можно перехватить, хотя это (невозможность перехвата) и не имеет большого значения, так как приложение живет ровно столько, сколько обрабатывается один запрос. Неперехваченная ошибка просто приводит к досрочному выходу из обработчика, и удалению приложения из памяти. Новый запрос будет обрабатываться новым «чистым» приложением. В Python же приложение постоянно находится в памяти, обрабатывая множество запросов без «перезагрузки». Таким образом поддерживать правильное предсказуемое состояние приложения крайне важно. Все ошибки используют стандартный механизм исключений и могут быть перехвачены (разве что за исключением SyntaxError). Неперехваченная ошибка приведет к завершению приложения, которое понадобится перезапускать извне.

Существует множество способов «приготовить» PHP и Python для веба. Далее я остановлюсь на двух наиболее мне знакомых (и кажется наиболее популярных) - PHP + FastCGI (php-fpm) и Python + WSGI (uWSGI). Конечно же, перед обоими этими связками предполагается наличие фронтенд-сервера (например, Nginx).

Поддержка многопоточности Python

Запуск сервера приложений (например, uWSGI) приводит к загрузке интерпретатора Python в память, а затем загрузке самого web-приложения. Обычно bootstrap-модуль приложения импортирует необходимые ему модули, производит вызовы инициализации и в итоге экспортирует подготовленный callable объект, соответствующий спецификации WSGI. Как известно, при первом импорте Python-модулей, код внутри них исполняется, в том числе создаются и инициализируются значениями переменные. Между двумя последовательными HTTP-запросами состояние интерпретатора не сбрасывается, следовательно сохраняются значения всех переменных уровня модуля.

Напишем простейшее WSGI-приложение, которое наглядно продемонстрирует вышеописанное на примере:

N = 0 def app(env, start_response): global n n += 1 response = "%.6d" % n start_response("200 OK", [("Content-Type", "text/plain")]) return

Здесь n является переменной модуля и она будет создана со значением 0 при загрузке приложения в память следующей командой:

Uwsgi --socket 127.0.0.1:8080 --protocol http --single-interpreter --processes 1 -w app:app

Само приложение просто выводит на страницу значение переменной n . Для заядлых PHP программистов оно выглядит бессмысленным, так как «должно» каждый раз выводить на страницу строку «000001».

Проведем тест:

Ab -n 500 -c 50 http://127.0.0.1:8080/ curl http://127.0.0.1:8080

В результате мы получим строку «000501» , что подтверждает наше утверждение, о том, что приложение находится загруженным в память uwsgi и сохраняет свое состояние между запросами.

Если запустить uWSGI с параметром --processes 2 и провести тот же тест, то несколько последовательных вызовов curl покажут, что мы имеем уже 2 различные возрастающие последовательности. Так как ab посылает 500 запросов, примерно половина из них приходится на один процесс uWSGI, а остальные - на второй. Ожидаемые значения, возращаемые curl будут примерно «000220» и «000280» . Интерпретатор Python, судя по всему, один на процесс, и мы имеем 2 независимых окружения и реальную параллельную обработку запросов (в случае многоядерного процессора).

Python поддерживает потоки, как часть языка. Классическая реализация (CPython) использует нативные потоки OS, но есть GIL - в один момент времени выполняется только один поток. При этом все равно возможны проблемы race condition, так как даже n += 1 не является атомарной операцией.

Дизассемблируем python код

«Дизассемблируем» наше WSGI-приложение: import dis n = 0 def app(env, start_response): global n n += 1 return if "__main__" == __name__: print(dis.dis(app)) 8 0 LOAD_GLOBAL 0 (n) 3 LOAD_CONST 1 (1) 6 INPLACE_ADD 7 STORE_GLOBAL 0 (n) 10 10 LOAD_GLOBAL 1 (bytes) 13 LOAD_GLOBAL 2 (str) 16 LOAD_GLOBAL 0 (n) 19 CALL_FUNCTION 1 (1 positional, 0 keyword pair) 22 LOAD_CONST 2 ("utf-8") 25 CALL_FUNCTION 2 (2 positional, 0 keyword pair) 28 BUILD_LIST 1 31 RETURN_VALUE

Видно, что инкремент в нашей программе занимает 4 операции. Прерывание GIL может наступить на любой из них.

Увеличение количества потоков при отсуствии ожидания IO в коде обработчиков HTTP-запросов не приводит к ускорению обработки (а скорее даже ее замедляет, так как потоки могут «толкаться», переключая контексты). Реальной параллельности потоки в следствие ограничеия GIL не создают, хоть и являются не green thread"ами, а настоящими потоками OS.

Проведем еще один тест. Запустим uwsgi с 1 процессом, но 10 потоками-обработчиками в нем:

Uwsgi --socket 127.0.0.1:8080 --protocol http --single-interpreter --processes 1 --threads 10 -w app:app

Среды Web-разработки на языке Python, Часть 1

Разработка для Web с помощью Django и Python

Среда Web-разработки Django на языке Python, от установки до законченного Web-сайта

Серия контента:

Проект Django представляет собой настраиваемую пользователем среду разработки. Он берёт начало из Web-сайта одной онлайн-газеты и был выпущен как система с открытым исходным кодом в июле 2005 года. Главные компоненты среды разработки Django следующие:

  • Объектно-реляционное отображение (object-relational mapping) для создания моделей
  • Безупречный интерфейс администратора, специально созданный для конечных пользователей
  • Элегантно спроектированный механизм адресования (URL)
  • Язык шаблонов, для дизайнеров
  • Система кэширования

Эта статья - первая из двух статей о среде Web-разработки на языке Python. Вторая статья представит вам среду разработки TurboGears.

Чтобы использовать и понимать код в данной статье, вам необходимо установить Python и знать, как им пользоваться на начальном уровне. Проверьте, есть ли у вас Python, и какой версии, набрав python -V . Минимальным требованием Django является версия 2.3.5, которая доступна вам на Web-сайте Python (см. ссылку в разделе в конце статьи). Вам также следует хотя бы немного быть знакомым с архитектурой MVC.

Установка Django

В этой статье используется разрабатываемая версия Django для того, чтобы воспользоваться преимуществами последних улучшений, внесённых в среду разработки Django. Я рекомендую вам использовать эту версию до появления версии 0.95. Узнайте о наличии последней версии Django на его Web-сайте (снова см. ссылку в ).

Чтобы скачать и установить Django вам нужно:

Листинг 1. Скачивание и установка Django
~/downloads# svn co http://code.djangoproject.com/svn/django/trunk/ django_src ~/downloads# cd django_src ~/downloads# python setup.py install

Инструмент администрирования Django

После установки Django вам необходим инструмент администрирования Django, а именно django-admin.py, добавленный в переменную окружения path. Листинг 2 показывает некоторые из команд, доступных инструменту администратора:

Листинг 2. Использование инструмента администрирования Django
~/dev$ django-admin.py usage: django-admin.py action actions: adminindex Prints the admin-index template snippet for the given model module name(s). ... snip ... startapp Creates a Django app directory structure for the given app name in the current directory. startproject Creates a Django project directory structure for the given project name in the current directory. validate Validates all installed models. options: -h, --help show this help message and exit --settings=SETTINGS Python path to settings module, e.g. "myproject.settings.main". If this isn"t provided, the DJANGO_SETTINGS_MODULE environment variable will be used. --pythonpath=PYTHONPATH Lets you manually add a directory the Python path, e.g. "/home/djangoprojects/myproject".

Проекты и приложения в Django

Чтобы начать проект Django, используйте команду программы django-admin startproject вот так:

Листинг 3.Создание проекта
~/dev$ django-admin.py startproject djproject

Показанная выше команда создает директорию под названием djproject, которая содержит файлы базовой конфигурации, необходимые для работы проекта Django:

Листинг 4. Содержание директории djproject
__init__.py manage.py settings.py urls.py

В этом проекте вы создадите приложение для отдела занятости, называемое "jobs." Для создания приложения используйте скрипт manage.py , который является специальным для проекта скриптом в django-admin.py, в котором автоматически задаётся файл settings.py:

Листинг 5. Использование manage.py с параметром startapp
~/dev$ cd djproject ~/dev/djproject$ python manage.py startapp jobs

Это создает костяк приложения с одним модулем Python для ваших моделей и другим для ваших видов (view). Директория jobs будет содаржать следующие файлы:

Листинг 6. Содержание директории приложения jobs
__init__.py models.py views.py

Местоположение приложения внутри проекта является чистой условностью, созданной для новых разработчиков в Django, а не требованием. Как только вы начнете перемешивать и сопоставлять приложения в нескольких проектах, вы можете поместить приложения в их собственные пространства имён для модулей и связать их вместе, используя настройки и главные файлы URL. Но пока, следуйте приведенным ниже этапам.

Чтобы Django знал о новом приложении, вам необходимо добавить строку в поле INSTALLED_APPS в файле settings.py. Для этого приложения для отдела занятости нужно добавить строку djproject.jobs:

Листинг 7. Добавление строки к settings.py
INSTALLED_APPS = ("django.contrib.auth", "django.contrib.contenttypes", "django.contrib.sessions", "django.contrib.sites", "djproject.jobs",)

Создание модели

У Django есть своя собственная библиотека object-relational mapper (ORM), которая поддерживает динамический доступ к базам данных через объектный интерфейс Python. Интерфейс Python является очень удобным и эффективным, но вы также можете отказаться от него и напрямую использовать SQL при необходимости.

На данный момент ORM предоставляет поддержку для баз данных PostgreSQL, MySQL, SQLite, а также Microsoft® SQL.

Это пример использует SQLite, в качестве интерфейса к базе данных. SQLite является легковесной базой данных, не требующей конфигурации и располагается на диске в виде простого файла. Чтобы использовать SQLite, просто установите библиотеку pysqlite с помощью инструментов установки (setuptools) (см. дополнительную информацию об инструментах установки (setuptools) и, в частности, об инструменте easy_install , который вам необходимо установить отдельно, в разделе ):

easy_install pysqlite

Перед тем, как работать с моделью, сконфигурируйте базу данных в файле настроек. Для SQLite необходимо указывать только движок и имя базы данных.

Листинг 8. Конфигурирование базы данных в settings.py
DATABASE_ENGINE = "sqlite3" DATABASE_NAME = "/path/to/dev/djproject/database.db" DATABASE_USER = "" DATABASE_PASSWORD = "" DATABASE_HOST = "" DATABASE_PORT = ""

Это приложение для отдела занятости будет иметь два типа объектов: Местоположения (Locations) и Работы (Jobs). Местоположение включает в себя поля города, штата (по желанию), а также страны. Работа имеет местоположение, должность, описание и дату публикации.

Листинг 9. Модуль jobs/models.py
from django.db import models class Location(models.Model): city = models.CharField(maxlength=50) state = models.CharField(maxlength=50, null=True, blank=True) country = models.CharField(maxlength=50) def __str__(self): if self.state: return "%s, %s, %s" % (self.city, self.state, self.country) else: return "%s, %s" % (self.city, self.country) class Job(models.Model): pub_date = models.DateField() job_title = models.CharField(maxlength=50) job_description = models.TextField() location = models.ForeignKey(Location) def __str__(self): return "%s (%s)" % (self.job_title, self.location)

Метод __str__ - это специальный метод класса в языке Python, который возвращает строковое представление объекта. Django достаточно широко использует этот метод, когда отображает объекты в инструменте администратора.

Чтобы увидеть схему базы данных для модели, запустите manage.py с командой sql . Схема пока еще не будет задействована.

Листинг 10. Просмотр схемы базы данных с помощью команды manage.py sql
~/dev/djproject$ python manage.py sql jobs BEGIN; CREATE TABLE "jobs_job" ("id" integer NOT NULL PRIMARY KEY, "pub_date" date NOT NULL, "job_title" varchar(50) NOT NULL, "job_description" text NOT NULL, "location_id" integer NOT NULL); CREATE TABLE "jobs_location" ("id" integer NOT NULL PRIMARY KEY, "city" varchar(50) NOT NULL, "state" varchar(50) NULL, "country" varchar(50) NOT NULL); COMMIT;

Для инициализации и установки модели, запустите команду синхронизирования базы данных syncdb:

~/dev/djproject$ python manage.py syncdb

Отметим, что команда syncdb просит вас создать учетную запись суперпользователя. Это происходит потому, что приложение django.contrib.auth, которое предоставляет базовые средства аутентификации пользователя, установлено по умолчанию в ваших настройках INSTALLED_APPS. Имя суперпользователя и пароль будут использоваться для регистрации в инструменте администратора, описанном в следующем разделе. Помните, что это имя и пароль суперпользователя Django, а не системы.

Наборы запросов

Модели Django обращаются к базе данных через изначально установленный Управляющий (Manager) класс, называемый objects . Например, чтобы вывести список всех Работ, вам нужно использовать метод all , принадлежащий менеджеру objects:

Листинг 11. Вывод всех работ (jobs)
>>> from jobs.models import Job >>> for job in Job.objects.all(): ... print job

Управляющий класс также имеет методы фильтрации, называемые filter (фильтрация) и exclude (исключение). Фильтрация получает все объекты, подходящие под условия, тогда как исключение дает все объекты, не подходящие под них. Нижеследующие запросы должны дать такие же результаты ("gte" означает "greater than or equal,"(больше или равно) и "lt" означает "less than")(меньше чем).

Листинг 12. Исключение и фильтрация работ (jobs)
>>> from jobs.models import Job >>> from datetime import datetime >>> q1 = Job.objects.filter(pub_date__gte=datetime(2006, 1, 1)) >>> q2 = Job.objects.exclude(pub_date__lt=datetime(2006, 1, 1))

Методы filter и exclude возвращают объекты QuerySet, которые можно связать в цепочку и которые могут даже представлять соединения. Запрос q4 , приведенный ниже, будет находить работы, начиная с 1-го января 2006 года, в г. Кливленд (Cleveland), штат Огайо:

Листинг 13. Снова исключение и фильтрация работ (jobs)
>>> from jobs.models import Job >>> from datetime import datetime >>> q3 = Job.objects.filter(pub_date__gte=datetime(2006, 1, 1)) >>> q4 = q3.filter(location__city__exact="Cleveland", ... location__state__exact="Ohio")

Это хорошо, что QuerySets ленивы. Это означает, что они не выполняются в базе данных, пока не произошла их оценка, и благодаря чему работают гораздо быстрее, чем мгновенные запросы.

Эта леность является очень практичной в сочетании с рассекающей (slicing) функциональностью языка Python. Вместо того, чтобы запрашивать все записи, а затем отсекать нужные записи, нижеследующий код использует смещение (OFFSET), равное 5, и предел (LIMIT), равный 10, в настоящем запросе SQL, весьма улучшая качество выполнения.

Листинг 14. Python-рассечение
>>> from jobs.models import Job >>> for job in Job.objects.all() ... print job

Примечание: Используйте метод count , чтобы понять, сколько записей находятся в QuerySet. Метод len в Python делает полную оценку, а затем подсчитывает количество рядов, возращенных в виде записей, тогда как метод count делает действительный Подсчет (COUNT) SQL, который гораздо быстрее. И ваш администратор баз данных поблагодарит вас.

Листинг 15. Подсчет записей
>>> from jobs.models import Job >>> print "Count = ", Job.objects.count() # GOOD! >>> print "Count = ", len(Job.objects.all()) # BAD!

Для более подробной информации, см. раздел для ссылки на "Справочник по интерфейсу API базы данных" для Django.

Инструмент администратора

Одно из самых больших достоинств в Django - это отточенный интерфейс администратора. Этот инструмент был создан с учетом конечного пользователя, благодаря чему предоставляет вашим проектам отличное средство для ввода данных.

Инструмент администратора представляет собой приложение, которое идет вместе с Django. Перед тем, как его использовать, его необходимо установить так же, как и приложение jobs . Сперва нужно добавить модуль приложения (django.contrib.admin) в настройки INSTALLED_APPS:

Листинг 16. Изменения в settings.py
INSTALLED_APPS = ("django.contrib.auth", "django.contrib.contenttypes", "django.contrib.sessions", "django.contrib.sites", "djproject.jobs", "django.contrib.admin",)

Чтобы сделать инструмент администратора доступным из адреса (URL) /admin, просто раскройте скобки комментария в строке, в предоставленном вам файле urls.py вашего проекта. В следующем разделе будет рассматриваться конфигурация URL более подробно.

Листинг 17. Использование urls.py, чтобы иструмент администратора стал доступным
from django.conf.urls.defaults import * urlpatterns = patterns("", (r"^admin/", include("django.contrib.admin.urls.admin")),)

Пиложение администратора имеет свою модель базы данных, которую необходимо установить. Снова используйте команду syncdb , чтобы завершить следующее:

python manage.py syncdb

Чтобы увидеть инструмент администратора, вы можете использовать тест-сервер, которая прилагается к Django.

Листинг 18. Использование тест-сервера, чтобы увидеть инструмент администратора
~/dev/djproject$ python manage.py runserver Validating models... 0 errors found. Django version 0.95 (post-magic-removal), using settings "djproject.settings" Development server is running at http://127.0.0.1:8000/ Quit the server with CONTROL-C (Unix) or CTRL-BREAK (Windows).

Теперь вы можете переместиться в инструмент администратора по адресу http://localhost:8000/admin и зарегистрироваться, используя данные администратора, созданные вами ранее. Вы заметите, что ни одна из ваших моделей не доступна для пользования.

Чтобы открыть доступ к классу через инструмент администратора, создайте для него подкласс Admin (Администратора). Затем вы можете настраивать то, как их можно администрировать добавлением характеристик классов к данному подклассу. Листинг 19 показывает, как добавлять класс Location (Местонахождения) к интсрументу администратора.

Листинг 19. Добасвление класса Location с помощью инструмента администратора
class Location(meta.Model): ... class Admin: list_display = ("city", "state", "country")

Теперь вы можете создавать, обновлять и удалять записи Местонахождения (Location) через интерфейс администратора.

Рисунок 1. Изменение местонахождений с помощью инструмента администратора

Вы можете выводить и сортировать Записи (Records) по городам, штатам и странам, в зависимости от характеристики класса list_display .

Рисунок 2. Вывод местонахождений с помощью инструмента администратора

Инструмент администратора имеет большое количество опций для управления каждым из классов моделей. Листинг 20 показывает несколько примеров, примененных к классу Job:

Листинг 20. Опции для управления классами моделей
class Job(meta.Model): ... class Admin: list_display = ("job_title", "location", "pub_date") ordering = ["-pub_date"] search_fields = ("job_title", "job_description") list_filter = ("location",)

В соответствие с вышеупомянутыми настройками, при выводе записей работ (job) будут использоваться: заголовок работы (job), местонахождения и дата издания. Работы будут располагаться в порядке даты издания, начиная с самого последнего (знак минус означает - в порядке убывания). Пользователи могут найти работы по заголовку и описанию, а администраторы могут фильтровать записи, исходя из их местонахождения.

Рисунок 3. Вывод работ с помощью инструмента администратора

Проектирование своей схемы URL

Система передачи адресов URL в Django использует модули конфигураций регулярных выражений, которые отображают строковые шаблоны URL в методах языка Python, называемые видами . Эта система позволяет совершенно четко отделять адреса URL от кода, что делает их максимально легкими для управления.

Модуль urls.py создается и определяется в качестве начала отсчета конфигурации URL (с помощью значения ROOT_URLCONF в модуле settings.py). Единственное требование для файла конфигурации URL состоит в том, что он должен содержать объект, определяющий шаблоны, называемые urlpatterns .

Приложение управления работой (job) будет начинаться с index-видом и детальным (detail) видом, которые доступны через настоящие отображения URL:

Оба этих вида (index и детальный вид) будут выполнены в модуле, называемом views.py в приложении работ. Выполнение этой конфигурации в файле urls.py проекта будут выглядеть следующим образом:

Листинг 21. Выполнение конфигурации видов в djproject/urls.py
from django.conf.urls.defaults import * urlpatterns = patterns("", (r"^admin/", include("django.contrib.admin.urls.admin")), (r"^jobs/$", "djproject.jobs.views.index"), (r"^jobs/(?P

Отметьте кусочек кода . Это понадобиться позже.

На практике лучше всего - вытаскивать шаблоны URL, специальные для приложений, и помещать их в само приложение. Это отделяет приложение от проекта и позволяет повторно его использовать. Файл конфигурации URL уровня приложений для работ (jobs) будут выглядеть так:

Листинг 22. Файл конфигурации URL уровня приложений, urls.py
from django.conf.urls.defaults import * urlpatterns = patterns("", (r"^$", "djproject.jobs.views.index"), (r"^(?P\d+)/$", "djproject.jobs.views.detail"),)

С тех пор, как методы видов исходят из одного модуля, для настройки djproject.jobs.views в качестве корневого имени модуля можно использовать первый аргумент, и Django использует его для того, чтобы искать методы index и detail:

Листинг 23. jobs/urls.py: поиск index и detail
from django.conf.urls.defaults import * urlpatterns = patterns("djproject.jobs.views", (r"^$", "index"), (r"^(?P\d+)/$", "detail"),)

Чтобы связать в одно целое адреса (URL), перечисленных выше работ (job), назад в проект, необходимо использовать функцию include . Адреса (URL) уровня приложений теперь связаны в разделе /jobs:

Листинг 24. djproject/urls.py: Связывание адресов (URL) обратно в проект
from django.conf.urls.defaults import * urlpatterns = patterns("", (r"^admin/", include("django.contrib.admin.urls.admin")), (r"^jobs/", include("djproject.jobs.urls")),)

Если вы попытаетесь войти на начальную (index) страницу (http://localhost:8000/jobs) на этом этапе, используя тест-сервер, вы получите ошибку, так как вид, который будет называться (djproject.jobs.views.index), еще не существует.

Выполнение видов

Вид представляет собой простой метод языка Python, который принимает объект отклика и отвечает за:

  • Любую бизнес-логику (явно или неявно)
  • Контекстный словарь с данными для шаблона
  • Рендеринг (rendering) шаблона с контекстом
  • Объект отклика, который пропускает отрендеренные (rendered) результаты обратно в среду разработки

В Django вызванный метод языка Python, когда запрашивается URL, называется видом , а страница, закаченная и отрендеренная, видом называется шаблоном . По этой причине, команда разработчиков Django говорила о Django, как о среде разработки с MVT (model-view-template - модель-вид-шаблон). С другой стороны, TurboGears называет свои методы контроллерами , а отрендеренные шаблоны видами , что действительно позволяет использовать аббревиатуру MVC. Разница лишь в использовании слов, но смысл остается тем же.

Самый простейший из возможных видов возвращает объект HttpResponse (http отклик), инициализированный в строковый тип. создайте следующий метод и сделайте из /jobs HTTP-запрос, чтобы проверить, что ваши файлы urls.py и views.py правильно настроены.

Листинг 25. jobs/views.py (v1)
from django.http import HttpResponse def index(request): return HttpResponse("Job Index View")

Следующий код получает последние 10 работ (job), рендерит их через шаблон и возвращает отклик. Это не будет работать без файла шаблона из .

Листинг 26. jobs/views.py (v2)
from django.template import Context, loader from django.http import HttpResponse from jobs.models import Job def index(request): object_list = Job.objects.order_by("-pub_date")[:10] t = loader.get_template("jobs/job_list.html") c = Context({ "object_list": object_list, }) return HttpResponse(t.render(c))

В вышеприведенном коде шаблон назван, как строковый jobs/job_list.html Рендеринг шаблона происходит в контексте списка работ (job), названном object_list . Отрендеренный шаблон строки попадает в конструктор HTTPResponse, который отправляется назад в клиент запроса с помощью среды разработки.

Этапы загрузки шаблона, создающие контекст и возвращающие новый объект отклика, перемещены ниже с помощью удобного метода, называемого render_to_response . Также новым является метод детального (detail) вида, который использует удобный для этого метод get_object_or_404 , чтобы осуществить выборку объекта Job, используя приведенные аргументы. Если объект не найден, то выдается ошибка 404. Эти два метода избавляют программу от большого количества стандартных кодов, используемых в большинстве Web-приложений.

Листинг 27. jobs/views.py (v3)
from django.shortcuts import get_object_or_404, render_to_response from jobs.models import Job def index(request): object_list = Job.objects.order_by("-pub_date")[:10] return render_to_response("jobs/job_list.html", {"object_list": object_list}) def detail(request, object_id): job = get_object_or_404(Job, pk=object_id) return render_to_response("jobs/job_detail.html", {"object": job})

Отметим, что detail берет object_id в качестве аргумента. Этот номер упоминался раньше, после URL-пути /jobs/ к файлу работ (job) urls.py. Он проходит дальше в метод get_object_or_404 в качестве первичного ключа (primary key - pk).

Приведенные выше виды все еще не будут работать, потому что шаблоны, которые они загружают и рендерят (jobs/job_list.html и jobs/job_detail.html) еще не существуют.

Создание шаблонов

Django предоставляет простой язык шаблонов, спроектированный для быстрого рендеринга и простоты использования. Шаблоны Django создаются из простого текста, встроенного в {{ переменные }} и {% тэги %} . Затем происходит замена переменных на значения, которые они несут. Тэги используются в качестве основы логики управления. Шаблоны можно использовать для генерирования любого формата текстов, включая HTML, XML, CSV и простой текст.

Первое, что нужно сделать - это определить местонахождение шаблонов. Для простоты, создайте директорию для шаблонов внутри директории djproject и добавьте его путь в строке TEMPLATE_DIRS файла settings.py:

Листинг 28. Создание директории шаблонов в settings.py
TEMPLATE_DIRS = ("/path/to/devdir/djproject/templates/",)

Шаблоны в Django поддерживают концепцию, называемую наследованием шаблонов , которая позволяет дизайнерам сайтов создавать однородный вид и функциональность без повторения содержания в каждом из шаблонов. Вы можете использовать наследование, определяя документ скелета, или основы, с блочными тэгами. Эти блочные тэги заполняются шаблонами страниц с содержанием. Этот пример показывает скелет кода на HTML с блоками, называемыми title , extrahead и content:

Листинг 29. Документ скелета, templates/base.html
Company Site: {% block title %}Page{% endblock %} {% block extrahead %}{% endblock %} {% block content %}{% endblock %}

Чтобы приложение было отдельно от проекта, используйте вспомагательный файл основы, в качестве основы для всех файлов страниц приложения Job. Для этого примера, поместите CSS приложения в файл основы для упрощения. В реальном приложении, с хорошо сконфигурированным Web-сервером, возьмите данный CSS и поместите его в статичный файл, обслуживаемый Web-сервером.

Листинг 30. Вспомогательный файл основы, templates/jobs/base.html
{% extends "base.html" %} {% block extrahead %} {% endblock %}

Изначально, тест-сервер в Django не обслуживает статичные файлы, потому что эту работу должен выполнять Web-сервер. Если во время разработки вы захотите, чтобы Django работал с картинками, листами стилей и так далее, тогда см. ссылку в о том, как включить эту возможность.

Теперь создайте 2 шаблона страниц для загрузки и рендеринга. Шаблон jobs/job_list.html просто выполняет итерацию через object_list (список объектов), который он получает через контекст, выдаваемый index-видом, а также отображает ссылку на каждую из страниц с подробной информацией о записи.

Листинг 31. Шаблон templates/jobs/job_list.html
{% extends "jobs/base.html" %} {% block title %}Job List{% endblock %} {% block content %}

Job List

    {% for job in object_list %}
  • {{ job.job_title }}
  • {% endfor %}
{% endblock %}

Страница jobs/job_detail.html показывает одну запись, называемую job (работа):

Листинг 32. Страница templates/jobs/job_detail.html
{% extends "jobs/base.html" %} {% block title %}Job Detail{% endblock %} {% block content %}

Job Detail

{{ job.job_title }} - {{ job.location }}
Posted: {{ job.pub_date|date:"d-M-Y" }}
{{ job.job_description }}
{% endblock %}

Язык шаблонов в Django был спроектирован с ограниченными функциональными возможностями. Эта ограниченность позволяет сохранять простоту шаблонов для непрограммистов и ограждает программистов от использования бизнес-логики там, где ее не должно быть, в слое представления. См. ссылку на документацию по языку шаблонов в .

Универсальные виды

Django идет вместе с четырьмя наборами универсальных видов , которые позволяют разработчикам создавать приложения, следующие типичным шаблонам:

  • Страницы со списком/подробностями (как вышеприведенный пример)
  • Дробление записей по дате (полезно для новостных сайтов и блогов)
  • Создание, обновление и удаление - СОУ (Creation, update, and deletion - CRUD) объектов
  • Простой прямой рендеринг шаблонов или простое HTTP-перенаправление

Вместо создания методов стандартных видов, вся бизнес-логика находится в файле urls.py и управляется с помощью методов универсальных видов, поддерживаемых Django.

Листинг 33. Универсальные виды в jobs/urls.py
from django.conf.urls.defaults import * from jobs.models import Job info_dict = { "queryset": Job.objects.all(), } urlpatterns = patterns("django.views.generic.list_detail", (r"^$", "object_list", info_dict), (r"^(?P\d+)/$", "object_detail", info_dict),)

Три важных изменения в данном файле urls.py:

  • Объект отображения info_dict проходит через набор запросов, чтобы был открыт доступ для Jobs.
  • Он использует django.views.generic.list_detail вместо djproject.jobs.views .
  • Действительно вызванные виды - это object_list и object_detail .

Этот проект следует некоторым требованиям, чтобы переход к универсальным видам произошел автоматически:

  • Универсальный детальный (detail) вид ожидает аргумент с именем object_id .
  • Шаблоны следуют наименованию: app_label /model_name _list.html (jobs/job_list.html) app_label /model_name _detail.html (jobs/job_detail.html)
  • Шаблон списка управляет списком с именем object_list .
  • Детальный шаблон управляет объектом с именем object .

Больше опций можно задать через info_dict , включая значение paginate_by , которое определяет число объектов на странице.

Заключение

Следующая статья этого выпуска будет рассматривать TurboGears, другую среду Web-разработки на языке Python, и будет сравнивать его с Django.

  • PHP ,
  • Python
  • Введение

    В статье хотелось бы поднять вопросы отличия использования Python для web-разработки по сравнению с оной на PHP. Надеюсь, статья не приведет к холиварам, так как она вовсе не о том, какой язык лучше или хуже, а исключительно о технических особенностях Python.

    Немного о самих языках

    PHP - веб-ориентированный язык, (в хорошем смысле слова). С низкоуровневой точки зрения приложение на PHP представляет собой скорее набор отдельных скриптов возможно с единой семантической точкой входа.

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

    Исходя из вышеописанных особенностей вытекают и различия в обработке ошибок в web-приложениях. В PHP существует целый зоопарк типов ошибок (errors, exceptions), далеко не каждую из которых можно перехватить, хотя это (невозможность перехвата) и не имеет большого значения, так как приложение живет ровно столько, сколько обрабатывается один запрос. Неперехваченная ошибка просто приводит к досрочному выходу из обработчика, и удалению приложения из памяти. Новый запрос будет обрабатываться новым «чистым» приложением. В Python же приложение постоянно находится в памяти, обрабатывая множество запросов без «перезагрузки». Таким образом поддерживать правильное предсказуемое состояние приложения крайне важно. Все ошибки используют стандартный механизм исключений и могут быть перехвачены (разве что за исключением SyntaxError). Неперехваченная ошибка приведет к завершению приложения, которое понадобится перезапускать извне.

    Существует множество способов «приготовить» PHP и Python для веба. Далее я остановлюсь на двух наиболее мне знакомых (и кажется наиболее популярных) - PHP + FastCGI (php-fpm) и Python + WSGI (uWSGI). Конечно же, перед обоими этими связками предполагается наличие фронтенд-сервера (например, Nginx).

    Поддержка многопоточности Python

    Запуск сервера приложений (например, uWSGI) приводит к загрузке интерпретатора Python в память, а затем загрузке самого web-приложения. Обычно bootstrap-модуль приложения импортирует необходимые ему модули, производит вызовы инициализации и в итоге экспортирует подготовленный callable объект, соответствующий спецификации WSGI. Как известно, при первом импорте Python-модулей, код внутри них исполняется, в том числе создаются и инициализируются значениями переменные. Между двумя последовательными HTTP-запросами состояние интерпретатора не сбрасывается, следовательно сохраняются значения всех переменных уровня модуля.

    Напишем простейшее WSGI-приложение, которое наглядно продемонстрирует вышеописанное на примере:

    N = 0 def app(env, start_response): global n n += 1 response = "%.6d" % n start_response("200 OK", [("Content-Type", "text/plain")]) return
    Здесь n является переменной модуля и она будет создана со значением 0 при загрузке приложения в память следующей командой:

    Uwsgi --socket 127.0.0.1:8080 --protocol http --single-interpreter --processes 1 -w app:app
    Само приложение просто выводит на страницу значение переменной n . Для заядлых PHP программистов оно выглядит бессмысленным, так как «должно» каждый раз выводить на страницу строку «000001».

    Проведем тест:

    Ab -n 500 -c 50 http://127.0.0.1:8080/ curl http://127.0.0.1:8080
    В результате мы получим строку «000501» , что подтверждает наше утверждение, о том, что приложение находится загруженным в память uwsgi и сохраняет свое состояние между запросами.

    Если запустить uWSGI с параметром --processes 2 и провести тот же тест, то несколько последовательных вызовов curl покажут, что мы имеем уже 2 различные возрастающие последовательности. Так как ab посылает 500 запросов, примерно половина из них приходится на один процесс uWSGI, а остальные - на второй. Ожидаемые значения, возращаемые curl будут примерно «000220» и «000280» . Интерпретатор Python, судя по всему, один на процесс, и мы имеем 2 независимых окружения и реальную параллельную обработку запросов (в случае многоядерного процессора).

    Python поддерживает потоки, как часть языка. Классическая реализация (CPython) использует нативные потоки OS, но есть GIL - в один момент времени выполняется только один поток. При этом все равно возможны проблемы race condition, так как даже n += 1 не является атомарной операцией.

    Дизассемблируем python код

    «Дизассемблируем» наше WSGI-приложение:
    import dis n = 0 def app(env, start_response): global n n += 1 return if "__main__" == __name__: print(dis.dis(app))
    8 0 LOAD_GLOBAL 0 (n) 3 LOAD_CONST 1 (1) 6 INPLACE_ADD 7 STORE_GLOBAL 0 (n) 10 10 LOAD_GLOBAL 1 (bytes) 13 LOAD_GLOBAL 2 (str) 16 LOAD_GLOBAL 0 (n) 19 CALL_FUNCTION 1 (1 positional, 0 keyword pair) 22 LOAD_CONST 2 ("utf-8") 25 CALL_FUNCTION 2 (2 positional, 0 keyword pair) 28 BUILD_LIST 1 31 RETURN_VALUE
    Видно, что инкремент в нашей программе занимает 4 операции. Прерывание GIL может наступить на любой из них.


    Увеличение количества потоков при отсуствии ожидания IO в коде обработчиков HTTP-запросов не приводит к ускорению обработки (а скорее даже ее замедляет, так как потоки могут «толкаться», переключая контексты). Реальной параллельности потоки в следствие ограничеия GIL не создают, хоть и являются не green thread"ами, а настоящими потоками OS.

    Проведем еще один тест. Запустим uwsgi с 1 процессом, но 10 потоками-обработчиками в нем:

    Uwsgi --socket 127.0.0.1:8080 --protocol http --single-interpreter --processes 1 --threads 10 -w app:app
    и выполним с помощью ab 5000 запросов к приложению.

    Ab -n 5000 -c 50 http://127.0.0.1:8080/
    Последующие запросы curl 127.0.0.1 :8080 покажут, что мы имеем только одну возрастающую последовательность, значение которой <= 5000 (меньше 5000 оно может быть в случае race condition на инкременте).

    Влияние языка на архитектуру приложения

    Каждый HTTP-запрос обрабатывается в отдельном потоке (справедливо и для процессов, так как процесс имеет минимум 1 поток). При этом каждый поток за время своей жизни (которое в идеальных условиях совпадает со временем жизни всего uwsgi приложения) обрабатывает множество HTTP-запросов, сохраняя свое состояние (т.е. значения переменных уровня модулей) от запроса к запросу. В этом заключается чуть ли не основное отличие от модели обработки HTTP-запросов в PHP, где каждый запрос приходит новое только что проинициализированное окружение и загрузку приложения необходимо выполнять каждый раз заново.

    Типичным подходом в крупных web-приложениях на PHP является использование Dependency Injection Container для управления инициализацией и доступом к уровню сервисов приложения. Наглядным примером является Pimple . На каждый HTTP-запрос первым делом выполняется код инициализации, регистрирующий все доступные сервисы в контейнере. Далее по мере необходимости осуществляется доступ к объектом сервисов (lazy) в контроллерах. Каждый сервис может зависеть от других сервисов, зависимости разрешаются опять же через контейнер в коде инициализации сервиса-агрегата.

    // Определяем сервисы $container["session_storage"] = function ($c) { return new SessionStorage("SESSION_ID"); }; $container["session"] = function ($c) { return new Session($c["session_storage"]); }; // Используем сервисы class MyController { public function __construct() { // get the session object $this->session = $container["session"]; // "тестриуемость" страдает, но не суть } }
    Благодаря контейнеру, можно обеспечить единовременное создание объектов и возвращение уже готовых объектов на каждое последующее обращение к сервису (если необходимо). Но эта магия работает только в рамках одного HTTP-запроса, поэтому сервисы можно без проблем инициализировать специфичными для запроса значениями. Такие значения зачастую - это текущий авторизованный пользователь, сессия текущего пользователя, собственно HTTP-запрос и пр. В конце запроса сервисы все равно будут разрушены, а в начале обработки следующего запроса - созданы и проинициализированы новые. К тому же можно практически не беспокоиться об утечках памяти, если обработка одного HTTP-запроса умещается в отведенные для скрипта лимиты, так как создание сервисов происходит по требованию (lazy) и на один запрос каждый необходимый сервис скорее всего будет создан только в единственном экземпляре.

    Теперь, принимая во внимание вышеописанную поточную модель Python, можно заметить, что использование аналогичного подхода в Python web-приложении не возможно без дополнительных усилий. Если контейнер будет являться переменной уровня модуля (что выглядит вполне логично), все сервисы, которые он содержит, не могут быть проинициализированы специфичными для текущего запроса значениями, так как сервис будет являться разделяемым ресурсом между несколькими потоками, выполяющими обработку нескольких HTTP-запросов псевдо-параллельно. На первый взгляд существует два способа справиться с этой проблемой - сделать объекты сервисов независимыми от текущего HTTP-запроса (зависимыми остануться вызовы методов сервисов, а стековые переменные, используемые в методах, не являются разделяемыми ресурсами) или же сделать контейнер - ресурсом потока, а не процесса (тогда каждый поток будет общаться только со своим независимым набором сервисов, а в один момент времени один поток может обрабатывать только один HTTP-запрос).

    Кажущийся плюс первого подхода - сервисы инициализируются только один раз за все время жизни uwsgi процесса. Возможна также экономия памяти (так как имеем только один набор сервисов на все потоки). С другой стороны обработка конкретного HTTP-запроса требует лишь какого-то (скорее всего небольшого) поднможества всех доступных сервисов. Если же приложение достаточно большое и обладает внушительным количеством сервисов, то после обработки определенного числа HTTP-запросов, подавляющее большинство сервисов окажется проинициализировнными и находящимися в памяти процесса. Выглядит так, что это может оказаться серьезной проблемой.

    Второй подход можно реализовать с использованием

    Dash - библиотека пользовательского интерфейса для создания аналитических веб-приложений. Она будет полезна для тех, кто использует Python для анализа и исследования данных, визуализации, моделирования и отчётности.

    Dash значительно упрощает создание GUI (графических пользовательских интерфейсов) для анализа данных. Вот пример приложения на Dash из 43 строк кода, который связывает выпадающее меню с графиком D3.js. Когда пользователь выбирает значение в выпадающем списке, код динамически экспортирует данные из Google Finance в Pandas DataFrame:

    Код Dash является декларативным и реактивным, что упрощает создание сложных приложений, содержащих множество интерактивных элементов. Вот пример с 5 входными данными, 3 - выходными и с перекрёстной фильтрацией. Это приложение было написано на Python, и в нём всего лишь 160 строк кода:

    Приложение на Dash с несколькими входными и выходными данным.

    Для каждого элемента приложения можно задать собственные параметры размера, расположения, цвета и шрифта. Приложения на Dash создаются и публикуются в Сети, поэтому к ним можно применить всё, на что способен CSS. Ниже иллюстрируется пример тонко настраиваемого интерактивного приложения отчётности на Dash, выполненного в стиле отчёта финансовой организации Goldman Sachs.

    Тонко настраиваемое приложение Dash, созданное в стиле отчёта финансовой организации Goldman Sachs.

    Вам не нужно писать какой-либо код на JavaScript или HTML, когда ваше приложение на Dash запущено в веб-браузере. Dash предоставляет богатый набор интерактивных веб-компонентов.

    Import dash_core_components as dcc dcc.Slider(value=4, min=-10, max=20, step=0.5, labels={-5: "-5 Degrees", 0: "0", 10: "10 Degrees"})

    Пример простого ползунка на Dash

    Dash предоставляет простой реактивный декоратор для привязки вашего кода анализа данных к пользовательскому интерфейсу Dash.

    @dash_app.callback(Output("graph-id", "figure"), ) def your_data_analysis_function(new_slider_value): new_figure = your_compute_figure_function(new_slider_value) return new_figure

    Когда изменяется входной элемент (например, при выборе элемента в выпадающем списке или при передвижении ползунка), декоратор Dash предоставляет вашему коду Python новое входное значение.

    Ваша функция Python может выполнять различные действия с новым входным значением: может фильтровать объект DataFrame библиотеки Pandas, выполнять SQL-запрос, запускать симуляцию, выполнять вычисления или запускать тестирование. Dash рассчитывает, что ваша функция вернёт новое свойство для какого-нибудь элемента пользовательского интерфейса, будь то новый график, новая таблица или новый текст.

    В качестве примера ниже представлено приложение на Dash, которое обновляет текстовый элемент при взаимодействии с графиком. Код приложения фильтрует данные в Pandas DataFrame на основе выбранной точки:

    Приложение ниже отображает метаинформацию о лекарственных веществах при наведении курсора на точки в графике. Код приложения также добавляет строки в таблицу, когда появляются новые компоненты в выпадающем списке.

    Благодаря этим двум разделениям между компонентами Python и реактивными функциональными декораторами, Dash разграничивает все технологии и протоколы, необходимые для создания интерактивного веб-приложения. Dash достаточно прост, чтобы привязать пользовательский интерфейс к коду Python за один вечер.

    Архитектура

    Flask и React.js

    Приложения на Dash - веб-серверы, которые запускают Flask и связывают пакеты JSON через HTTP-запросы. Интерфейс Dash формирует компоненты, используя React.js.

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

    React.js также великолепен, например, мы переписали всю нашу веб-платформу и наш онлайн-редактор диаграмм с помощью React. Но есть кое-что, что действительно радует насчёт React - активный и талантливый состав сообщества разработчиков, который опубликовал тысячи высококачественных компонентов, начиная с выпадающих списков и слайдеров , заканчивая календарями и . И всё это публикуется с открытым исходным кодом!

    Dash использует мощь Flask и React, подстраивая их под работу с Python для специалистов по анализу и обработке данных, которые могут не быть экспертами в области веб-разработки.

    От React.js к компонентам Python

    Компоненты Dash - это классы Python, которые кодируют свойства и значения конкретного компонента React и упорядочиваются как JSON. Dash предоставляет набор инструментов для лёгкой упаковки компонентов React в вид компонентов, которые могут быть использованы в Dash. Этот набор инструментов использует динамическое программирования для автоматического создания классов Python из аннотированного свойства React - propTypes . На выходе классы Python, которые представляют компоненты Dash, являются удобными для пользователя, так как они имеют автоматическую проверку аргументов, строк документации и прочее.

    Вот пример динамически сгенерированной проверки ошибочного аргумента:

    >>> import dash_core_components as dcc >>> dcc.Dropdown(valu=3) Ошибка: неизвестный ключевой аргумент `valu` Допустимые аргументы: id, className, disabled, multi, options, placeholder, value

    Пример динамически создаваемых строк документации:

    >>> help(dcc.Dropdown) class Dropdown(dash.development.base_component.Component) | Компонент выпадающего списка. | Компонент выпадающего списка служит для выбора одного или более | элементов. | значения и названия элементов выпадающего списка определяются в `options` | свойство и выбранный элемент(ы) определяются свойством `value`. | | используйте выпадающий список, только если у вас много вариантов выбора (больше 5), или | когда вы ограничены пространством. В противном случае вы можете использовать переключатели или чекбоксы, | Которые покажут сразу все элементы пользователю. | | Аргументы ключевых слов: | - id (строка; необязательный) | - className (строка; необязательный) | - disabled (логический тип; необязательный): если true, выбор блокируется | - multi (логический тип; необязательный): если true, пользователь может выбрать несколько значений | - options (список; необязательный) | - placeholder (строка; необязательный): серый текст по умолчанию, если ничего не выбрано | - value (строка | список; необязательный): значение поля ввода. Если `multi` false (по умолчанию), | то value - строка, соответствующая своим значениям, | указанным в свойстве `options`. Если `multi` - true, то | можно выбрать сразу несколько значений, а `value` - | массив элементов со значениями, соответствующими в свойстве | `options`. | | Доступные события: "change

    Полный набор HTML-тегов (наподобие div , img , table) также обрабатывается с помощью React, а их классы Python доступны через библиотеку dash_html_component . Основной набор интерактивных компонентов, таких как Dropdown , Graph , Slider , будет поддерживаться командой Dash через dash_core_components . Обе библиотеки используют стандартный набор инструментальных средств React-to-Dash с открытым исходным кодом, который вы могли бы использовать при необходимости написания своей собственной библиотеки компонентов.

    Ваше приложение автоматически не привязывается к библиотеке компонентов Dash. Библиотека компонентов импортируется отдельно от основной библиотеки Dash. С помощью набора инструментальных средств React-to-Dash можно легко записать или перенести компонент React.js в класс Python, который можно использовать в приложении Dash. На официальном сайте вы найдёте руководство по созданию собственных компонентов или можете попросить команду разработчиков Dash написать их для вас.

    Многопользовательские приложения

    Свойства приложения на Dash хранятся в интерфейсе (в браузере). Это позволяет использовать приложения, написанные с использованием Dash, в многопользовательском режиме: может быть открыто несколько независимых друг от друга сессий, в которых действия одних пользователей не будут влиять на данные других пользователей. Код приложения на Dash является функциональным: он может считывать значения из глобальных свойств Python, но не может вносить в них изменения. Этот функциональный подход можно легко обосновать и протестировать - это просто входные и выходные данные без каких-либо побочных эффектов или свойств.

    CSS и стили

    CSS и стили по умолчанию хранятся вне базовой библиотеки, чтобы сохранить принцип модульности и независимого управления версиями и чтобы подтолкнуть разработчиков Dash-приложений настраивать вид своих приложений. Команда Dash разместила руководство по основным стилям.

    Визуализация данных

    Библиотека Dash поставляется с компонентом Graph, который отвечает за отображение диаграмм с помощью Plotly.js. Библиотека Plotly.js отлично подходит к Dash (отличное дополнение), так как она декларативна и имеет открытый исходный код. Кроме того, она поддерживает полный спектр научных, финансовых и деловых диаграмм. Она создана на основе D3.js (для диаграмм типографического качества и экспорта векторных изображений) и WebGL (для высокопроизводительной визуализации).

    В библиотеке Dash элемент Graph использует тот же синтаксис, что и библиотека Plotly.py с открытым исходным кодом, что даёт вам возможность легко переключаться между ними. Компонент Graph подключается к системе событий Plotly.js, позволяя авторам писать приложения, которые реагируют на наведение курсора, щелчки и выбор определённых точек на графиках Plotly.

    Репозитории с открытым исходным кодом

    • документация и руководство по Dash;
    • Plotly.js  -JavaScript- библиотека, используемая Dash.

    Прототипирование

    Dash - это новая библиотека в среде Python, однако концепции и идеи, на которых строится Dash, существуют в течение десятилетий на разных языках и в разных приложениях.

    Если вы разбираетесь в Excel, значит, вам будет проще разобраться и в Dash. Ведь они оба используют «реактивную» модель программирования. В Excel ячейки с выходными данными обновляются автоматически при изменении параметров ячеек с входными данными. Любая ячейка может быть входной или выходной или и тем, и другим. В ячейках с входными данными нет информации о том, какие ячейки с выходными данными зависят от них, что упрощает добавление новых ячеек с выходными данными или позволяет связать несколько ячеек. Вот пример Excel-приложения:

    Можно провести аналогию для Dash. Вместо ячеек у нас есть богатый спектр веб-компонентов, таких как ползунки, поля ввода, выпадающие списки и графики. Вместо написания сценария Excel или VBA мы пишем код Python. Ниже представлено то же самое приложение, но в этот раз оно написано на Dash:

    App.layout = html.Div([ html.Label("Hours per Day"), dcc.Slider(id="hours", value=5, min=0, max=24, step=1), html.Label("Rate"), dcc.Input(id="rate", value=2, type="number"), html.Label("Amount per Day"), html.Div(id="amount"), html.Label("Amount per Week"), html.Div(id="amount-per-week") ]) @app.callback(Output("amount", "children"), ) def compute_amount(hours, rate): return float(hours) * float(rate) @app.callback(Output("amount-per-week", "children"), ) def compute_amount(amount): return float(amount) * 7

    Некоторым разработчикам нравится этот пример, потому что Excel по-прежнему занимает доминирующее положение даже в технических вычислениях и в финансовой математике. Я не думаю, что доминирующее положение Excel - это технический вопрос. В конце концов, есть легионы программистов, которые изучили нюансы Excel, VBA и даже SQL.

    Более того, таблицы Excel легче распространять, чем программы на Python, а ячейки Excel легче редактировать, чем аргументы командной строки.

    Тем не менее, моделирование в Excel имеет известные ограничения: эти таблицы часто становятся слишком большими или уязвимыми, чтобы переводить их на производственный уровень, проводить экспертную оценку или тестировать и поддерживать. Вам ведь знаком случай со знаменитой опечаткой в 2013 году?

    Надеемся, что Dash сделает использование Python в проектах по обработке данных проще. Благодаря одним и тем же функциональным и реактивным принципам, можно так же легко написать приложение на Dash, как написать аналитическую таблицу. Это, безусловно, более мощный и презентабельный инструмент.

    Фреймворк Shiny

    Если вы программируете на R, вам повезло. Shiny - это реактивный фреймворк для создания веб-приложений на чистом R, и это отлично! Вы даже можете создавать интерактивные графики с библиотекой Shiny или Plotly для R . Dash и Shiny похожи, но Dash не стремится быть копией Shiny, так как философии Python и R достаточно различаются, что приводит к необходимости использования разного синтаксиса.

    Интерактивное веб-приложение, созданное с помощью Shiny на языке R.

    Структурирование данных с MATLAB

    Если вы программируете на MATLAB, то вам, возможно, знакома GUIDE - библиотека пользовательского интерфейса для MATLAB. Компания Mathworks была одной из новаторов в области технических вычислений. GUIDE была написана в далёком 2004 году.

    Приложение, созданное с помощью библиотеки GUIDE на MATLAB.

    Если ваши данные структурированы в базе данных, вы могли бы использовать Tableau или любой другой BI-инструмент. Tableau - восхитительный инструмент. Компания установила новый вектор развития в своей отрасли, согласно которому, у конечного пользователя должна быть автономия, чтобы он мог иметь возможность исследовать данные внутри своей организации. Компания также помогла сделать популярнее концепции детализации данных и перекрёстной фильтрации.

    Перекрёстная фильтрация в Tableau.

    Dash также служит дополнением к BI-инструментам, наподобие вышеупомянутых. Они отлично подходят для структурирования данных. Но когда дело доходит до преобразования данных и аналитики, превзойти размах и гибкость языков программирования и сообществ, вроде Python, становится труднее. Dash абстрагируется от множества сложностей в создании пользовательских интерфейсов, позволяя вам сделать это красиво для вашей аналитической базы данных.

    Виджеты Jupyter

    Наконец, пришло время рассказать о виджетах Jupyter. Они обеспечивают действительно приятный фреймворк внутри интерфейса Notebook. Вы можете добавлять ползунки к вашим графикам в Jupyter Notebook.

    Виджеты в Dash похожи на виджеты Jupyter. В Jupyter Notebooks есть возможность добавлять виджеты непосредственно рядом с кодом. В Dash элементы управления хранятся отдельно от вашего кода. Dash больше нацелена на приложения для распространения, чем на распространяемый код и документацию. Вы всегда можете смешивать и сопоставлять инструменты, создавая свои приложения на Dash в среде Jupyter Notebook.

    Команде разработчиков Dash также очень нравится проект nteract , который действительно снижает порог вхождения в Python и Jupyter Notebook, позволяя упаковать Jupyter Notebook в виде настольного приложения.

    Лицензирование и бизнес-модель с открытым исходным кодом

    Стартап поддерживает библиотеки с открытым исходным кодом для Python, R и MATLAB, которые взаимодействуют с plotly.js. Компания также поддерживает веб-приложение для создания диаграмм и подключения их к базам данных (стыковочные библиотеки также распространяются с открытым исходным кодом).

    Если вы используете локальную версию с открытым исходным кодом, в таком случае ограничений нет. Вы можете управлять развёртыванием Dash-приложений самостоятельно через платформы вроде Heroku или Digital Ocean.

    Если вы ищите вдохновение для создания своих пользовательских интерфейсов в области технических вычислений, рекомендуем прочитать статью Брета Виктора

    Вам также может понравиться проект Explorable Explanations , который специализируется на интерактивном обучении.