Рубрики
Без рубрики

Построить простое приложение Crud с колбой и Python

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

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

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

Через этот пост вы узнаете и используете следующие инструменты:

  • Колбу – Мой любимый веб-каркас Python. Это маленький, минимальный и простой.
  • Flask-Sqlalchemy – Чрезвычайно популярный ORM для колбы. Это позволяет вам взаимодействовать с серверами реляционных баз данных, таких как Postgres, MySQL, SQLite и т. Д. В этом уроке мы будем использовать SQLite в качестве нашей базы данных, но любой из остальных был бы одинаково хорошо работать без изменений кода.
  • Flask-OIDC – библиотека подключения OpenID для колбе. OpenID Connect является открытым протоколом, который обрабатывает аутентификацию пользователя и авторизацию. Это «современный» способ обрабатывать аутентификацию в Интернете.
  • Окта – Служба бесплатной работы API, которая действует как сервер авторизации OpenID Connect. ОКТА будет хранить учетные записи пользователя для вашего приложения и позволит обрабатывать регистрацию пользователя, вход и т. Д. Простым способом.
  • Python-Slugify – Простая библиотека Python, которая генерирует удобные URL-адреса. Мы будем использовать это, чтобы конвертировать заголовки пост блога в URL-адреса, которые хорошо выглядят.

Если вы хотите пропустить урокул и проверить полностью построенный проект, вы можете пойти Посмотреть это на Github Отказ

Инициализируйте аутентификацию для вашего приложения Flask + Python с Okta

OKTA – это бесплатная служба API API, которая хранит учетные записи пользователей и создают обработку аутентификации пользователя, авторизацию, социальный логин, сброс пароля и т. Д. – простым. ОКТА использует открытые стандарты, такие как OpenID Connect, чтобы сделать интеграцию бесшовные.

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

Чтобы начать, вам сначала нужно создать бесплатную учетную запись Developer OKTA: https://developer.okta.com/signup/ . После того, как вы создали свой аккаунт и вошли в систему, выполните следующие действия Configure Okta, а затем вы будете готовы написать какой-нибудь код!

Шаг 1: Храните свой url org

Первое, что вам нужно сделать, это скопировать Org url с верхней правильной части вашей панели инструментов Okta. Этот URL будет использоваться для маршрута до вашего сервера авторизации, общаться с ним и многое другое. Вам понадобится это значение позже, так что не забывайте его.

Шаг 2: Создание приложения OpenID Connect

Okta позволяет вам хранить и управлять пользователями для нескольких приложений, которые вы можете создавать. Это означает, что прежде чем мы сможем пойти дальше, вам необходимо создать новое приложение Connect OpenID для этого проекта.

Приложения в OpenID Connect имеют имя пользователя и пароль (упоминаются как идентификатор клиента и секрет клиента), которые позволяют вашему серверу авторизации распознавать, какое приложение разговаривает с ним в любой момент времени.

Чтобы создать новое приложение, просмотрите к Приложения Вкладка и нажмите Добавить приложение Отказ

Далее нажмите Веб Опция платформы (поскольку этот проект – это веб-приложение).

На странице настроек введите следующие значения:

  • Имя : Простое приложение для колбы
  • База УРИС : http://localhost:5000
  • Войти Redirect Uris : http://localhost:5000/oidc/callback

Вы можете оставить все остальные значения без изменений.

Теперь, когда ваше приложение было создано, скопируйте ID клиента и Секрет клиента Значения на следующей странице вам понадобится позже, когда мы начнем запись кода.

Шаг 3: Создайте токен аутентификации

Чтобы получить доступ к APIT APIT и сможете управлять своими учетными записями пользователей с большим количеством гранулярности, вам также нужно создать токен аутентификации Okta. Это ключ API, который будет использоваться позже при взаимодействии с apis apis kakta и позволяет делать такие вещи, как:

  • Создать, обновлять и удалять пользователей
  • Создать, обновлять и Удалить группы
  • Управление настройками приложения
  • И Т. Д.

Чтобы создать токен аутентификации, нажмите на API Вкладка в верхней части страницы, а затем Создать токен кнопка. Дайте свой токен имя, желательно то же имя, что и ваше приложение, то нажмите Создать токен Отказ Как только ваш токен будет создан, скопируйте значение токена, поскольку вам понадобится позже.

Шаг 4: Включить регистрацию пользователя

Последняя часть настройки, необходимая для завершения, – это включить функцию регистрации пользователей для сервера авторизации. Как правило, серверы авторизации поддерживают только вход в систему, выйти и прочее. Но сервер авторизации Okta также поддерживает регистрацию самообслуживания, так что пользователи могут создавать учетные записи, войти в них, сбросить пароли и в основном делать все, не пишенные для него какой-либо код.

На вашей приборной панели Okta вы заметите маленькую кнопку, помеченную <> Разработчик Консоль В верхнем левом углу вашей страницы. Наведите курсор на эту кнопку и выберите Классический интерфейс Опция меню, которая появляется.

Далее наведите курсор на Каталог Вкладка в верхней части страницы, затем выберите Регистрация самообслуживания пункт меню. На этой странице нажмите « » Включить регистрацию кнопка.

На странице конфигурации оставьте все настройки в качестве значений по умолчанию, кроме двух:

  • Отключить Пользователь должен подтвердить, что адрес электронной почты будет активирован. флажок Этот параметр удаляет требование для новых пользователей, чтобы подтвердить свой адрес электронной почты, прежде чем иметь возможность получить доступ к вашему веб-приложению.
  • Установите Redirect по умолчанию Опция, нажав на Пользовательский URL Радио коробка и ввод http://localhost: 5000/Приборная панель как значение. Этот параметр сообщает серверу авторизации, где перенаправить пользователей после того, как они успешно создали новую учетную запись на вашем сайте.

После нажатия Сохранить Последнее, что вам нужно, это переключается на консоль разработчиков.

Наведите курсор на Классический интерфейс Кнопка в правом верхнем углу страницы и выберите <> Разработчик Консоль Пункт меню из выпадания.

Установите зависимости Python и Flask

Первое, что вам нужно сделать для инициализации вашего приложения Flask, установлена все необходимые зависимости. Если у вас уже нет Python установлен на вашем компьютере, пожалуйста, перейдите Установите его сейчас Отказ Обязательно используйте последний выпуск Python 3+.

Примечание : Я также настоятельно рекомендую вам ознакомиться с пиронв Когда вы получите некоторое время. Это отличный инструмент, который делает управление зависимостями Python очень простым.

Теперь установите зависимости, необходимые для этого приложения.

pip install Flask==1.0.2
pip install Flask-SQLAlchemy==2.3.2
pip install flask-oidc==1.4.0
pip install python-slugify==1.2.5
pip install okta==0.0.4

Инициализируйте приложение Flask

Теперь, когда установлены зависимости, давайте начнем с создания простого приложения Flask. Мы построим на этот простой «Привет, мир!» Приложение, пока у нас есть все наши функциональные возможности.

Во-первых, создайте новый каталог для вашего проекта.

mkdir simple-flask-app
cd simple-flask-app

Далее создайте каталог внутри вашего проекта, чтобы удерживать код приложения Flask. Эта папка проведет весь исходный код проекта.

mkdir blog

Создать Блог/__init__.py файл и введите следующий код. Этот файл будет удерживать код инициализации приложения Flask.

from flask import Flask

app = Flask( __name__ )

@app.route("/")
def index():
    return "hello, world!"

Откройте терминал и запустите следующий код, чтобы начать свое новое приложение Flask.

FLASK_APP=blog flask run

Как только ваше приложение Flask работает, посетите http://localhost: 5000 В браузере, чтобы увидеть приветствие Hello World!

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

  • Импортировать библиотеку колба
  • Создать объект приложения для колба
  • Определите функцию (называемое представлением), которая работает, когда пользователь запрашивается конкретный URL (в этом случае, URL / )

Неплохо, верно?

Создайте шаблоны колба

Я в первую очередь занесенный разработчик. Я делаю некоторую основную переднюю работу, но это не мой сильный костюм. Из-за этого я люблю трудные вещи из пути сначала, и в моем случае, что жесткие вещи – Шаблон Отказ

При строительстве веб-сайта с колбой вы обычно используете встроенный Jinja2. Яблочный язык.

Вы можете подумать jinja2 как HTML с небольшим количеством дополнительных вещей: переменные, фильтры и некоторые другие инструменты, которые делают строить большие веб-сайты проще. Я нахожу jinja2 простым для работы, и как только вы получите это, я уверен, что вам тоже понравится.

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

mkdir -p blog/static
touch simple-flask-app/blog/static/style.css
mkdir -p blog/templates/blog
touch blog/templates/{403.html,404.html,layout.html}
touch blog/templates/blog/{dashboard.html,edit.html,index.html,post.html}

Теперь вы должны иметь следующую структуру каталогов.

simple-flask-app
└── blog
    ├── __init__.py
    ├── static
    │ └── style.css
    └── templates
        ├── 403.html
        ├── 404.html
        ├── blog
        │ ├── dashboard.html
        │ ├── edit.html
        │ ├── index.html
        │ └── post.html
        └── layout.html

Шаблоны Папка содержит все шаблоны проекта. В этой папке есть несколько шаблонов «верхнего уровня»:

  • layout.html – Этот шаблон является основой для всех других шаблонов. Он содержит все HTML-код Boilerplate и т. Д. что все остальные страницы будут делиться общерыми друг с другом.
  • 403.html – Этот шаблон будет показан пользователю, если они получают ошибку 403
  • 404.html – Этот шаблон будет показан пользователю, если они получают ошибку 404
  • статический/ – Эта папка содержит все статические файлы для сайта (изображения, CSS и т. Д.)
  • Статический/Стиль.css – Этот файл содержит все стили сайта
  • Блог/ – Эта папка удерживает все шаблоны, связанные с блогами
  • Блог/index.html – Домашняя страница блога
  • Блог/Dashboard.html – приборная панель пользователя
  • Блог/edit.html – Страница после редактирования
  • Блог/post.html – страница, которая показывает один пост

Далее скопируйте следующие CSS в Блог/Статический/Стиль.css файл.

footer {
  text-align: center;
  font-style: italic;
  margin-top: 1em;
}

.nav {
  float: right;
}

h2 {
  margin-bottom: 2em;
}

.posts ul {
  list-style-type: none;
}

.posts a {
  font-size: 1.3em;
  text-decoration: underline;
  color: #212529;
}

.posts span {
  font-size: 1.1em;
  float: right;
}

.empty {
  font-size: 2em;
  margin-bottom: 5em;
}

.container {
  padding-top: 2em;
}

.unauthenticated p {
  font-size: 1.3em;
  text-align: center;
}

hr.bottom {
  margin-top: 4em;
}

.submit-btn {
  float: right;
}

.alert p {
  font-size: 1.1em;
}

.author {
  font-size: 1.2em;
  margin-top: 2em;
}

.body {
  margin-top: 2em;
  font-size: 1.2em;
}

.edit {
  padding-left: 0;
}

.edit a {
  text-decoration: underline;
  color: #212529;
  font-size: 1.5em;
}

.edit li {
  list-style-type: none;
  line-height: 2.5em;
}

.edit button {
  float: right;
}

.delete {
  margin-left: 1em;
}

.your-posts {
  margin-top: 2em;
}

.hidden {
  display: inline;
}

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

Далее давайте создадим Блог/шаблоны/layout.html шаблон. Этот шаблон содержит многоразовый HTML, что все остальные страницы сайта будут делиться.




  
    
    
    
    
    Blog | {% block title %}{% endblock %}
  
  
    
Blog
{% block body %}{% endblock %}

Большая часть этой страницы является просто стандартным HTML. Вы можете увидеть с быстрым взглядом, что есть головной тег, который включает в себя Bootstrap Библиотека интернет-пользовательской интерфейсы (чтобы заставить все выглядеть приличным), навка, которая покажет на всех страницах сайта и нижнего колонтитула. Кроме того, есть пара ключевых элементов, которые делают этот шаблон особенным. Давайте проанализируем их.



Тег ссылки в верхней части заголовка использует специальную функцию, URL_FOR , чтобы правильно ссылаться на style.csss файл, который вы создали выше. Это встроенная функция колба, которая выделяет, какой URL статические файлы будут поданы на основе вашей колбе. Это намного приятнее, чем если бы вы бы усердствовали что-то вроде /static/style.css Поскольку в любой момент в будущем вы можете изменить настройку колба и переместить все ваши статические файлы на новый URL.

Возможно, вы также заметили специальные теги блога:

Blog | {% block title %}{% endblock %}



{% block body %}{% endblock %}

Эти особенные Блок Теги действуют как заполнитель для будущих ценностей. Поскольку этот шаблон будет повторно повторно повторно на каждой странице нашего сайта, это было бы глупо, если каждая страница сайта должна иметь точное же название или же содержание тела. Работать вокруг этого, вы можете использовать Блок тег, показанный выше. Детские шаблоны смогут вставлять свои собственные названия и контент тела в этот шаблон для создания полной страницы без дублирования кода!

Наконец, посмотрите на код Navbar и Если/else Заявление о нем содержится.

{% if not g.user %}
  Log In / Register
{% else %}
  Dashboard
  Logout
{% endif %}

Это условный блок Jinja2, который работает интуитивно. Если переменная g.user Не существует, то пользователю будет отображаться кнопка на NAVBAR, которая предлагает им войти или зарегистрироваться. В противном случае пользователь будет отображаться на кнопке приборной панели и выхода из системы.

В будущем g.user Переменная будет содержать запись в системе учетной записи пользователя (если кто-то существует), что является то, что эта условная будет проверять. Но об этом позже!

Далее идите вперед и скопируйте следующий код в Блог/шаблоны/403.html файл.

{% extends "layout.html" %}

{% block title %}Insufficient Permissions{% endblock %}

{% block body %}
  

Insufficient Permissions

Mind your own business >:S

{% endblock %}

Это как выглядит детский шаблон. Он использует специальные расширяться тег буквально «продлить» layout.html Шаблон, который вы только что создали.

В этом шаблоне содержание между Блок Метки вставляются в родительский шаблон ( layout.html ), как указано. Этот шаблон, когда визуализируется, теперь будет отображать полную страницу, не требуя дублирования любого кода. Довольно аккуратно!

Далее скопируйте следующий код в Блог/шаблоны/404.html файл. Эта страница будет отображаться пользователю, когда они посещают страницу, которая не найдена.

{% extends "layout.html" %}

{% block title %}Page Not Found{% endblock %}

{% block body %}
  

Page Not Found

Whatever you did, it's not working :(

{% endblock %}

Теперь скопируйте следующий код в Блог/шаблоны/блог/index.html файл. Этот шаблон будет домашней страницей для приложения Blog, который мы создаем. Он будет список сообщений блога, поэтому читатели могут просматривать их.

{% extends "layout.html" %}

{% block title %}Home{% endblock %}

{% block body %}
  

Recent Posts

{% if posts %}
{% else %}

Uh-oh. There are no posts to view.

{% endif %} {% endblock %}

Обратите внимание, что этот шаблон использует для тег в петлю через массив пост Объекты, а затем генерирует ссылки на каждый из сообщений блога, используя пост объектные свойства, например post.author_name , post.title , и т.д. Используя {{...}} Синтаксис позволяет выводить значение переменной в HTML страницы.

Теперь скопируйте следующий код в Блог/шаблоны/блог/Dashboard.html файл. Это будет приборная панель, которую авторы могут использовать для управления своими статьями. Это позволит им создавать статьи, редактировать статьи и удалять статьи.

{% extends "layout.html" %}

{% block title %}Dashboard{% endblock %}

{% block body %}
  

Create a Post

{% if post %}
{% endif %}

Your Posts

{% endblock %}

Давайте продолжим скопируем следующий код в блог/шаблоны/блог/edit.html файл. Этот шаблон будет отображаться пользователю, когда они хотят редактировать одну из их статей.

{% extends "layout.html" %}

{% block title %}{{ post.title }}{% endblock %}

{% block body %}
  

Edit Post

{% endblock %}

И, наконец, скопируйте код ниже в Блог/шаблоны/блог/post.html файл. Этот шаблон будет показан пользователю, когда они пытаются просмотреть сообщение в блоге.

{% extends "layout.html" %}

{% block title %}{{ post.title }}{% endblock %}

{% block body %}
  

{{ post.title }}

{{ post.body|safe }}

Written by {{ post.author_name }}

{% endblock %}

И с этим мы сейчас сделали создание шаблонов! Йи!

Теперь вы не можете просто проверить это только (мы не написали ни один код, чтобы сделать этот материал), но не волнуйтесь, мы скоро доберемся.

Создайте модели базы данных для вашего приложения Flask + Python

Следующее, что мы сделаем, это создать необходимые модели базы данных для приложения.

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

Для этого приложения мы будем создавать простой блог. Это означает, что мы в первую очередь будем хранить два части данных: данные учетной записи пользователя и данные по почте блога. Поскольку мы будем использовать OpenID Connect и Okta, чтобы сохранить данные нашей учетной записи пользователя, которые оставляют только в блоге данных для нас для хранения и управления.

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

  • ID поле, поэтому мы можем назначить каждый блог опубликовать уникальный идентификатор в базе данных
  • author_id поле, так что мы можем увидеть, какой автор создал сообщение в блоге
  • А Создано поле, так что мы можем увидеть в какую дату и время было создано блог
  • А Название поле, так что мы можем увидеть, что название каждого поста в блоге
  • А Тело Поле, поэтому мы можем увидеть, какое содержание каждого поста в блоге (это будет HTML)
  • А Slug Поле, поэтому мы можем определить, какой URL отображать каждый пост блога как (например, пост блога под названием «Мой любимый пост» может быть доступен на URL https://ourblog.com/my-favorite-post так что «мой-любимый-пост» будет слизником)

Теперь, когда мы знаем, какие элементы данных имеют решающее значение для хранения, давайте настроим Flask-sqlalchemy (библиотека ORM, которую мы будем использовать для управления базой данных), а также нашей модели базы данных.

Инициализировать Flask-Sqlalchemy

Чтобы подключить нашу базу данных, первый шаг – это работает работает Flask-SqlAlchemy.

Создайте новый файл, Блог/db.py и скопируйте в следующем коде. Этот файл проведет все нашу базу данных, связанный с кодом.

from datetime import datetime

from click import command, echo
from flask_sqlalchemy import SQLAlchemy
from flask.cli import with_appcontext

# Initialize SQLAlchemy with no settings
db = SQLAlchemy()

@command("init-db")
@with_appcontext
def init_db_command():
    """Initialize the database."""
    db.create_all()
    echo("Initialized the database.")

def init_app(app):
    """Initialize the Flask app for database usage."""
    db.init_app(app)
    app.cli.add_command(init_db_command)

Давайте посмотрим на то, что здесь происходит.

Во-первых, мы создаем дБ Глобальный объект. Это то, что будет использоваться для создания моделей в базе данных позже и управлять нашими отношениями с базой данных. Когда мы инициализируем дБ Объект, мы инициализируем расширение FLASK-SQLALCHEMY, не давая ему никаких настроек или конфигурации. Мы скоро доберемся до этого.

Далее init_db_command функция. Это специальная команда, которую вы сможете запустить в командной строке, когда вы вводите следующие.

FLASK_APP=blog flask init-db

Эта команда работает специальный метод SQLALCHEMY PROMENT COMPARE create_all , что инициализирует любые таблицы базы данных и указанные конфигурации. Прямо сейчас это ничего не сделает, но, как только мы определим модели базы данных в данный момент, это станет полезным.

init_db_command Функция построена с использованием Нажмите Библиотека, которая судет с колбой. Нажмите очень популярную библиотеку для создания командной строки приложений, как этот.

Далее init_app функция. Это предназначено для запуска из основного кода инициализации приложений, и он будет правильно настроить расширение Flask-SQLAlchemy, а также подключить init_db_command Функция в приложение правильно.

Теперь, когда наш код базы данных был написан, скопируйте следующий код в Блог/__init__.py Файл, перезаписать то, что было там раньше.

from os.path import dirname, join

from flask import Flask

from . import db

app = Flask( __name__ )
app.config.from_mapping(
    SQLALCHEMY_DATABASE_URI="sqlite:///" + join(dirname(dirname( __file__ )), "database.sqlite"),
)

db.init_app(app)

Что мы здесь делаем, в «главной» части нашей заявки, импортируя вновь созданную модель базы данных, которую мы построили минуту назад ( Blog/db.py ), указывая некоторые данные конфигурации приложений (чтобы рассказать колбу -SQLALCHEMY, какую базу данных мы используем), и, наконец, вызывая специальные db.init_app () Функция, которую мы определены в Блог/db.py Файл, который инициализирует Flask-Sqlalchemy правильно.

Для почти всех колбовых приложений вы на некоторое точке должны указать некоторую информацию о конфигурации, которая используется расширениями или вспомогательными библиотеками. То, как вы делаете это через app.config.from_mapping Вызов выше. Этот метод позволяет определить данные конфигурации и настройки, которые можно поделиться через приложение Flask.

В этом случае мы определяем настройку, которую требует Flask-SQLALCHEMY, Sqlalchemy_database_uri , в котором в основном рассказывается о том, какой тип базы данных мы используем и как к нему получить доступ. В этом случае мы собираемся хранить базу данных SQLite в файле под названием База данных .sqlite В корне нашей папки проекта.

Для этого приложения для блога мы будем использовать База данных SQLite Отказ SQLite – это невероятно популярная база данных, которая хранит все его данные в одном файле на диске. Это делает его идеальным для создания портативных приложений. Если вы строете что-то, что требует высокого уровня пропускной способности и обработки данных, SQLite не может быть лучшей подходящей … Но только для всего остального, это не только просто – это очень удобно, так как вам даже не нужен сервер базы данных!

Теперь, если вы вернетесь назад и повторно запустите приложение Flask, вы заметите, что он должен работать нормально. Единственная проблема в том, что мы все еще не достигли ничего, кроме инициализации базы данных.

Создайте модели базы данных SQLALCHEMY

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

Откройте Блог/db.py И вставьте следующий код, перезаписи, что было там раньше.

from datetime import datetime

from click import command, echo
from flask_sqlalchemy import SQLAlchemy
from flask.cli import with_appcontext

# Initialize SQLAlchemy with no settings
db = SQLAlchemy()

class Post(db.Model):
    """A blog post."""
    id = db.Column(db.Integer, primary_key=True)
    author_id = db.Column(db.Text, nullable=False)
    created = db.Column(db.DateTime, default=datetime.utcnow)
    title = db.Column(db.Text, nullable=False)
    body = db.Column(db.Text, nullable=False)
    slug = db.Column(db.Text, nullable=False, unique=True)

@command("init-db")
@with_appcontext
def init_db_command():
    """Initialize the database."""
    db.create_all()
    echo("Initialized the database.")

def init_app(app):
    """Initialize the Flask app for database usage."""
    db.init_app(app)
    app.cli.add_command(init_db_command)

То, что мы добавили здесь, это новый Пост класс. Это модель базы данных, которая рассказывает SQLalchemy, какие данные мы храним (пост блога), и какие поля он содержит. Для этого мы используем типичные типичные типы столбцов реляционных баз данных (целое число, текст, DateTime и т. Д.). Если вы не знакомы с SQL, вы можете проверить это Коллекция фантастической академии Khan по этому вопросу.

Теперь, когда модель базы данных была определена, все, что нам нужно сделать, это инициализировать базу данных, поэтому мы можем начать запись и чтение данных от нее. Чтобы сделать это, давайте будем использовать новый init-db Команда мы создали ранее.

FLASK_APP=blog flask init-db

Если вы посмотрите в корне папки проекта, теперь вы увидите файл под названием База данных .sqlite Отказ Именно здесь все ваши данные приложения теперь будут храниться!

Настройте регистрацию пользователя, вход пользователя и т. Д. В колбе

Ваша база данных теперь готова к действию, но у вас все еще есть проблема: как вы позволяете пользователям войти в свой веб-сайт, создавать учетные записи и т. Д.? Ответ прост: OpenID Connect и Окта Действительно

Шаг 1: Создать файл конфигурации Connect Connect Connect Connect

Создать новый файл с именем client_secrets.json В корневой папке вашего проекта и вставьте следующий код.

{
  "web": {
    "client_id": "{{ OKTA_CLIENT_ID }}",
    "client_secret": "{{ OKTA_CLIENT_SECRET }}",
    "auth_uri": "{{ OKTA_ORG_URL }}/oauth2/default/v1/authorize",
    "token_uri": "{{ OKTA_ORG_URL }}/oauth2/default/v1/token",
    "issuer": "{{ OKTA_ORG_URL }}/oauth2/default",
    "userinfo_uri": "{{ OKTA_ORG_URL }}/oauth2/default/userinfo",
    "redirect_uris": [
      "http://localhost:5000/oidc/callback"
    ]
  }
}

Обязательно замените переменные заполнителя вашей реальной информацией ока.

Заменить {{Okta_org_url}} С URL org на вашей приборной панели Pageereplace {{Okta_client_id}} С идентификатором клиента на вашем приложении Pageereplace {{Okta_client_secret}} С секретом клиента на странице вашего приложения

Этот файл будет использоваться библиотекой Flask-OIDC, которую мы будем настроить в данный момент. Эти настройки по существу рассказывают библиотеку OpenID CONNECT, что приложение OpenID Connect, которое вы используете для аутентификации, а также какова конечные точки API сервера авторизации.

УРУС выше указывают на ваши недавно созданные ресурсы OKTA, так что библиотека колбы сможет правильно поговорить с ней.

Шаг 2: Настройте Flask-OIDC

Откройте Блог/__init__.py и вставить в следующий код.

from os.path import dirname, join

from flask import Flask, g

from . import auth, db

app = Flask( __name__ )
app.config.from_mapping(
    SECRET_KEY={{ LONG_RANDOM_STRING }},
    OIDC_CLIENT_SECRETS=join(dirname(dirname( __file__ )), "client_secrets.json"),
    OIDC_COOKIE_SECURE=False,
    OIDC_CALLBACK_ROUTE="/oidc/callback",
    OIDC_SCOPES=["openid", "email", "profile"],
    OIDC_ID_TOKEN_COOKIE_NAME="oidc_token",
    SQLALCHEMY_DATABASE_URI="sqlite:///" + join(dirname(dirname( __file__ )), "database.sqlite"),
)

auth.oidc.init_app(app)
db.init_app(app)

app.register_blueprint(auth.bp)

@app.before_request
def before_request():
    """
    Load a user object into `g.user` before each request.
    """
    if auth.oidc.user_loggedin:
        g.user = auth.okta_client.get_user(auth.oidc.user_getfield("sub"))
    else:
        g.user = None

Что мы здесь делаем, указывает настройки для библиотеки Flask-OIDC:

  • Oidc_client_secrets Настройка сообщает Flak-OIDC, где находится ваш файл конфигурации OpenID Connect (тот, который вы создали в предыдущем разделе).
  • Oidc_cookie_secure Настройка позволяет проверить вход пользователя и регистрацию в разработке без использования SSL. Если вы собираетесь запустить свой сайт публично, вы удалите эту опцию и используете SSL на вашем сайте.
  • OIDC_CALLBACK_ROUTE Настройка сообщает Flask-OIDC, какой URL на вашем сайте будет обрабатывать вход пользователя. Это стандартная часть потоков подключения OpenID. Это не имеет возможности для этой статьи, но если вы хотите узнать больше, прочитайте наш OpenID Connect Primer Отказ
  • OIDC_SCOPES Настройка сообщает Flask-OIDC, какие данные запросить о пользователе, когда они входятся в систему. В этом случае мы запрашиваем базовую информацию о пользователе (электронную почту, имя и т. Д.).
  • Secret_key настройка должна быть установлена на долго случайная строка. Это используется для обеспечения вашей колб-сессий (куки), чтобы никто не мог вмешиваться с ними. Убедитесь, что эта переменная остается частной. Это никогда не должно быть публично выставлено.

После того, как данные конфигурации были созданы, мы также используем (в настоящее время) undefined auth Модуль (который мы доберемся до на мгновение), чтобы инициализировать библиотеку Flask-OIDC.

Затем мы регистрируем план (который будет обсуждаться в следующем разделе).

Наконец, мы определяем специальную функцию под названием до_request Отказ Эта функция будет работать автоматически перед каждым запросом пользователя (следовательно, The @ app.before_request декоратор), и загрузите объект пользователя, это доступно.

Вот как это работает.

  • Как только пользователь вошел в систему, используя OpenID Connect, у них будет сеанс, созданный и сохраненный в файле cookie на стороне сервера
  • Если auth.oidc.user_loggedin Код проверит, существует ли это файл cookie и действителен. Если это так, то мы будем использовать Библиотека Окта Питона Чтобы получить учетную запись пользователя как Пользователь объект, с которым мы можем легко работать, и назначить его специальной переменной g.user Отказ
  • Если пользователь не вошел в систему, то g.user будет установлен на Нет Отказ

Специальный g.user Значение – это то, что мы можем использовать для хранения важных данных наших потребностей приложений, например, текущий пользователь, например. Эта переменная доступна для нас для использования в шаблонах, боковом сервере и т. Д. что делает это очень полезным.

Шаг 3: Создайте просмотр входа в систему пользователя и выхода в колбе

Создайте новый файл, Блог/auth.py и вставить в следующий код. Этот файл проведет всю нашу нашу код, связанный с аутентификацией.

from os import environ

from flask import Blueprint, redirect, url_for
from flask_oidc import OpenIDConnect
from okta import UsersClient

bp = Blueprint("auth", __name__ , url_prefix="/")
oidc = OpenIDConnect()
okta_client = UsersClient("{{ OKTA_ORG_URL }}", "{{ OKTA_AUTH_TOKEN }}")

@bp.route("/login")
@oidc.require_login
def login():
    """
    Force the user to login, then redirect them to the dashboard.
    """
    return redirect(url_for("blog.dashboard"))

@bp.route("/logout")
def logout():
    """
    Log the user out of their account.
    """
    oidc.logout()
    return redirect(url_for("blog.index"))

Обязательно замените Okta_org_url и Okta_auth_token с соответствующими значениями Окта.

Что делает этот файл:

  • Определить специальное auth Чертеж. Чертежи в колбе Есть способы модульного кода, чтобы сделать его многоразовым в больших системах. Каждый план имеет имя, префикс URL (в этом случае, в этом случае, который, однако, не актуален), и это собственное объект мини-приложения.
  • Определить okta_client объект. Это позволяет нам говорить с ACTA API для получения пользовательских данных. Хотя это не является строго необходимым, это позволяет нам легче работать с нашими пользователями.
  • Определить Вход Вид для обработки функций входа пользователя. Что эти функции View делают это: когда посещение пользователей /авторизоваться Если пользователь уже вошел в систему (через @ oidc.require_Login декоратор), они будут перенаправлены на страницу приборной панели через Перенаправить (...) Функциональный вызов. Если пользователь не вошел в систему, @ oidc.require_login Декоратор будет перенаправлять пользователь на сервер авторизации Okta и предложит им либо создать новую учетную запись (регистрация пользователя), либо войти в существующую учетную запись.
  • Определить выйти Вид на обработку функциональности выхода из системы. Если пользователь посещает /Выход из системы URL, их сеанс cookie будет удален (через oidc.logout () call), и они будут перенаправлены на домашнюю страницу сайта.

Поздравляем, вы теперь полностью интегрировали регистрацию пользователя, логин и управление пользователями в свое приложение! Неплохо, верно?

Определите просмотры в блоге в колбе

До сих пор мы создали шаблоны интерфейса, создали модели базы данных и проводную аутентификацию пользователя. Одна вещь, которую мы не сделали, однако, определяют ядро поведение Для нашего применения: взгляды!

В колбе представления являются функциями, работающими, когда пользователь посещает определенный URL. Если пользователь посещает /приборная доска Например, колба должна знать, какую функцию запустить и что делать для отображения страницы приборной панели для пользователя.

Теперь, когда мы выяснили все остальное, давайте построим взгляды!

Во-первых, однако, нам нужно обновить наш код инициализации приложения, поэтому наш в ближайшее время будет создан вид в блоге! Открыть Блог/__ init__.py и скопируйте в следующем коде.

from os.path import dirname, join

from flask import Flask, g

from . import auth, blog, db

app = Flask( __name__ )
app.config.from_mapping(
    SECRET_KEY='LONG_RANDOM_STRING',
    OIDC_CLIENT_SECRETS=join(dirname(dirname( __file__ )), "client_secrets.json"),
    OIDC_COOKIE_SECURE=False,
    OIDC_CALLBACK_ROUTE="/oidc/callback",
    OIDC_SCOPES=["openid", "email", "profile"],
    OIDC_ID_TOKEN_COOKIE_NAME="oidc_token",
    SQLALCHEMY_DATABASE_URI="sqlite:///" + join(dirname(dirname( __file__ )), "database.sqlite"),
)

auth.oidc.init_app(app)
db.init_app(app)

app.register_blueprint(auth.bp)
app.register_blueprint(blog.bp)

@app.before_request
def before_request():
    """
    Load a user object into `g.user` before each request.
    """
    if auth.oidc.user_loggedin:
        g.user = auth.okta_client.get_user(auth.oidc.user_getfield("sub"))
    else:
        g.user = None

@app.errorhandler(404)
def page_not_found(e):
    """Render a 404 page."""
    return render_template("404.html"), 404

@app.errorhandler(403)
def insufficient_permissions(e):
    """Render a 403 page."""
    return render_template("403.html"), 403

Мы здесь не сильно изменились, кроме импорта Блог Модуль и зарегистрируйте его как план. Мы также определили две дополнительные функции: тот, который будет запущен, если пользователь посещает несуществующую страницу (A 404), или если пользователь посещает страницу, у них нет разрешения на доступ (A 403).

Далее создайте файл Блог/blog.py и вставить в следующий код.

from flask import Blueprint, abort, g, render_template, redirect, request, url_for
from slugify import slugify

from .auth import oidc, okta_client
from .db import Post, db

bp = Blueprint("blog", __name__ , url_prefix="/")

def get_posts(author_id):
    """
    Return all of the posts a given user created, ordered by date.
    """
    return Post.query.filter_by(author_id=author_id).order_by(Post.created.desc())

@bp.route("/")
def index():
    """
    Render the homepage.
    """
    posts = Post.query.order_by(Post.created.desc())
    posts_final = []

    for post in posts:
        u = okta_client.get_user(post.author_id)
        post.author_name = u.profile.firstName + " " + u.profile.lastName
        posts_final.append(post)

    return render_template("blog/index.html", posts=posts_final)

@bp.route("/dashboard", methods=["GET", "POST"])
@oidc.require_login
def dashboard():
    """
    Render the dashboard page.
    """
    if request.method == "GET":
        return render_template("blog/dashboard.html", posts=get_posts(g.user.id))

    post = Post(
        title=request.form.get("title"),
        body=request.form.get("body"),
        author_id = g.user.id,
        slug = slugify(request.form.get("title"))
    )

    db.session.add(post)
    db.session.commit()

    return render_template("blog/dashboard.html", posts=get_posts(g.user.id))

@bp.route("/")
def view_post(slug):
    """View a post."""
    post = Post.query.filter_by(slug=slug).first()
    if not post:
        abort(404)

    u = okta_client.get_user(post.author_id)
    post.author_name = u.profile.firstName + " " + u.profile.lastName

    return render_template("blog/post.html", post=post)

@bp.route("//edit", methods=["GET", "POST"])
def edit_post(slug):
    """Edit a post."""
    post = Post.query.filter_by(slug=slug).first()

    if not post:
        abort(404)

    if post.author_id != g.user.id:
        abort(403)

    post.author_name = g.user.profile.firstName + " " + g.user.profile.lastName
    if request.method == "GET":
        return render_template("blog/edit.html", post=post)

    post.title = request.form.get("title")
    post.body = request.form.get("body")
    post.slug = slugify(request.form.get("title"))

    db.session.commit()
    return redirect(url_for(".view_post", slug=post.slug))

@bp.route("//delete", methods=["POST"])
def delete_post(slug):
    """Delete a post."""
    post = Post.query.filter_by(slug=slug).first()

    if not post:
        abort(404)

    if post.author_id != g.user.id:
        abort(403)

    db.session.delete(post)
    db.session.commit()

    return redirect(url_for(".dashboard"))

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

Функция помощника Get_Posts

def get_posts(author_id):
    """
    Return all of the posts a given user created, ordered by date.
    """
    return Post.query.filter_by(author_id=author_id).order_by(Post.created.desc())

Эта функция разработана как помощник. Что это делает, это запросить базу данных, ищете любые сообщения, написанные специальным автором, и возвращает их в порядок убывания по дате.

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

Индекс представление

@bp.route("/")
def index():
    """
    Render the homepage.
    """
    posts = Post.query.order_by(Post.created.desc())
    posts_final = []

    for post in posts:
        u = okta_client.get_user(post.author_id)
        post.author_name = u.profile.firstName + " " + u.profile.lastName
        posts_final.append(post)

    return render_template("blog/index.html", posts=posts_final)

Эта функция просмотра является домашней страницей сайта. Эта функция будет работать каждый раз, когда пользователь посещает / Ур Что это делает:

  • Получите список всех сообщений в блоге на сайте, заказанные по дате по убыванию
  • Петли через каждый пост и извлекивают идентификатор автора
  • Использует библиотеку Okta Python для получения соответствующего имени и фамилии соответствующего пользователя (это позволит нам отобразить информацию авторской информации для читателей блога)
  • Оказывает Блог/index.html Шаблон мы создали гораздо раньше, что отображает список всех сообщений в блоге, а кто их написал

Вид приборной панели

@bp.route("/dashboard", methods=["GET", "POST"])
@oidc.require_login
def dashboard():
    """
    Render the dashboard page.
    """
    if request.method == "GET":
        return render_template("blog/dashboard.html", posts=get_posts(g.user.id))

    post = Post(
        title=request.form.get("title"),
        body=request.form.get("body"),
        author_id = g.user.id,
        slug = slugify(request.form.get("title"))
    )

    db.session.add(post)
    db.session.commit()

    return render_template("blog/dashboard.html", posts=get_posts(g.user.id))

Эта функция просмотра – это страница приборной панели пользователя. Эта функция будет работать каждый раз, когда пользователь посещает /Приборная панель Ур Что это делает:

  • Если пользователь просматривает приборную панель, она просто отображается Блог/Dashboard.html Шаблон, который мы определили ранее. Этот шаблон показывает пользователь список их ранее созданных сообщений блога, а также позволяет пользователю создавать новые сообщения в блоге, если они хотят, заполнив форму.
  • Если пользователь отправляет форму (попытка создать новый пост), этот представление создаст новый Пост Объект и сохранить его в базу данных. По пути он будет использовать библиотеку Python-Slugify, упомянутую ранее, чтобы преобразовать заголовок пост в формат, удобный для URL.

View_post View.

@bp.route("/")
def view_post(slug):
    """View a post."""
    post = Post.query.filter_by(slug=slug).first()
    if not post:
        abort(404)

    u = okta_client.get_user(post.author_id)
    post.author_name = u.profile.firstName + " " + u.profile.lastName

    return render_template("blog/post.html", post=post)

Эта функция просмотра отображает страницу пост. Эта функция будет работать каждый раз, когда пользователь посещает /<Некоторые блог-слизмент - здесь> Ур Что это делает:

  • Посмотрите в базу данных для поста в блоге со слизкой, указанным в URL. Если можно найти, он сделает эту страницу и показать блог пользователю.
  • Если не найдено совпадение поста в блоге, пользователь увидит страницу 404 и ничего более

В поле зрения Edit_Post.

@bp.route("//edit", methods=["GET", "POST"])
def edit_post(slug):
    """Edit a post."""
    post = Post.query.filter_by(slug=slug).first()

    if not post:
        abort(404)

    if post.author_id != g.user.id:
        abort(403)

    post.author_name = g.user.profile.firstName + " " + g.user.profile.lastName
    if request.method == "GET":
        return render_template("blog/edit.html", post=post)

    post.title = request.form.get("title")
    post.body = request.form.get("body")
    post.slug = slugify(request.form.get("title"))

    db.session.commit()
    return redirect(url_for(".view_post", slug=post.slug))

Эта функция просмотра позволяет пользователям редактировать пост. Эта функция будет работать каждый раз, когда пользователь посещает //Редактировать Ур Что это делает:

  • Посмотрите в базу данных для поста в блоге со слизкой, указанным в URL. Если можно найти, он обновит сообщение соответственно (при условии, что у пользователя есть правильные разрешения). Если у пользователя нет правильных разрешений, они будут показаны на странице 403.
  • Если не найдено совпадение поста в блоге, пользователь увидит страницу 404 и ничего более

Просмотр DELETE_POST.

@bp.route("//delete", methods=["POST"])
def delete_post(slug):
    """Delete a post."""
    post = Post.query.filter_by(slug=slug).first()

    if not post:
        abort(404)

    if post.author_id != g.user.id:
        abort(403)

    db.session.delete(post)
    db.session.commit()

    return redirect(url_for(".dashboard"))

Эта функция просмотра позволяет пользователям удалять пост. Эта функция будет работать каждый раз, когда пользователь посещает //delete Ур Что это делает:

  • Посмотрите в базу данных для поста в блоге со слизкой, указанным в URL. Если можно найти, он удалит сообщение из базы данных (при условии, что у пользователя есть правильные разрешения). Если у пользователя нет правильных разрешений, они будут показаны на странице 403.
  • Если не найдено совпадение поста в блоге, пользователь увидит страницу 404 и ничего более

И это все!

Проверьте свой новый приложение Flask + Python

Теперь, когда ваше приложение полностью построено, пройдите проверку! Откройте http://localhost:5000 Создайте учетную запись, войти в систему и т. Д.

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

Если вы заинтересованы в том, чтобы узнать больше о веб-аутентификации и безопасности, вы также можете проверить некоторые из Наши другие статьи или Следуйте за нами В Twitter – мы много пишем о интересных темах веб-разработки.

Вот три из моих фаворитов:

Оригинал: “https://dev.to/oktadev/build-a-simple-crud-app-with-flask-and-python-16p1”