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

Как создать приложение Todo с помощью Python Flask, Heroku и CSS Tailwind

Узнайте, как создать приложение Todo с помощью Python Flask, Heroku и CSS Tailwind

Автор оригинала: Ousseynou Diop.

Вступление

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

В этом руководстве мы создадим приложение Todo с нуля с помощью Tailwind утилитарного CSS-фреймворка для быстрого создания пользовательских дизайнов.

Требования

Чтобы следовать за мной, убедитесь, что вы:

  • python3
  • pip3
  • pipenv
  • Попутный ветер CDN

Настройка приложения

Создайте новую папку и установите необходимые инструменты.

Создайте новую папку

$ mkdir flask_tailwind_todo_app
$ cd flask_tailwind_todo_app/
...

Создайте виртуальную среду с помощью piper nv

$ pipenv shell
...
Creating a virtualenv for this project…
Using /usr/bin/python3 (3.7.5) to create virtualenv…
⠋Already using interpreter /usr/bin/python3
Using base prefix '/usr'
New python executable in /home/username/.local/share/virtualenvs/flask_tailwind_todo_app-4wPj_lFD/bin/python3
Also creating executable in /home/username/.local/share/virtualenvs/flask_tailwind_todo_app-4wPj_lFD/bin/python
Installing setuptools, pip, wheel...
done.

Virtualenv location: /home/username/.local/share/virtualenvs/flask_tailwind_todo_app-4wPj_lFD
Creating a Pipfile for this project…
Spawning environment shell (/usr/bin/zsh). Use 'exit' to leave.
. /home/username/.local/share/virtualenvs/flask_tailwind_todo_app-4wPj_lFD/bin/activate
username@username-Latitude-7480 ~/projects/xarala/source-code/flask_tailwind_todo_app
╰─$ . /home/username/.local/share/virtualenvs/flask_tailwind_todo_app-4wPj_lFD/bin/activate
(flask_tailwind_todo_app-4wPj_lFD) username@username-Latitude-7480 ~/projects/xarala/source-code/flask_tailwind_todo_app
╰─$

Эта команда создаст новую виртуальную среду и активирует ее.

Вы можете узнать больше о Piper nv в этом посте

Установите колбу , sqlalchemy и gunicorn

$ pipenv install flask flask-sqlalchemy gunicorn

Это позволит установить Flask, Sqlalchemy и gunicorn в нашей виртуальной среде.

Создайте наше первое приложение для колб

Создайте новый файл внутри flask_tailwind_todo_app каталог

$ touch app.py

Добавь

from flask import Flask

app = Flask(__name__)


@app.route("/")
def home():
   return "Hello Flask"


if __name__ == "__main__":
   app.run(debug=True)


Откройте терминал и запустите

$ python app.py

Вы увидите что-то вроде этого

* Serving Flask app "app" (lazy loading)
* Environment: production
  WARNING: This is a development server. Do not use it in a production deployment.
  Use a production WSGI server instead.
* Debug mode: on
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 278-921-051

Перейти к http://127.0.0.1:5000/ каков результат ?

Если все будет работать нормально, вы увидите Hello Flask Давайте сделаем его отличным, отрисовав шаблон

Шаблоны рендеринга

from flask import Flask, render_template

app = Flask(__name__)


@app.route("/")
def home():
   return render_template("home.html")


if __name__ == "__main__":
   app.run(debug=True)

Если вы запустите перезагрузку браузера, вы увидите такую ошибку jinja2.exceptions.TemplateNotFound

Давайте исправим это, создав папку templates

Внутри шаблоны создание папки home.html файл и добавьте этот код.




  
    
    
    Flask Todo App with Tailwind
  
  
    

Hello Flask

Перезагрузите браузер, что вы видите ? Давайте добавим немного css с попутным ветром, в этом уроке я буду использовать версию CDN .

Не используйте CDN , если вы хотите иметь все функции Tailwind .




  
    
    
    
    Flask Todo App with Tailwind
  
  
    

Hello Flask

Мы будем использовать шаблон из Компонентов Tailwind вот исходный код

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

Статические файлы

Создать base.html файл и переместить все содержимое home.html в него

Создать || base.html || файл и переместить все содержимое || home.html || в него




  
    
    
    
    
    
      {% if title %}
      {{ title }}
      {% else %} Flask Todo App with Tailwind
      {% endif %}
    
  
  
    
{% block content %} {% endblock content %}

Создать || base.html || файл и переместить все содержимое || home.html || в него

{% extends "base.html" %} {% block content %}

Flask Todo List

Add another component to Tailwind Components

{% endblock content %}

Все здесь статично, давайте добавим динамические данные…

Работа с базой данных (CRUD)

Мы будем использовать SQLite в качестве адаптера базы данных

from flask import Flask, render_template
from flask_sqlalchemy import SQLAlchemy  # add
from datetime import datetime  # add

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///todo.db'  # add
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False  # add
db = SQLAlchemy(app)  # add

# add


class Task(db.Model):
   id = db.Column(db.Integer, primary_key=True)
   name = db.Column(db.String(80), nullable=False)
   created_at = db.Column(db.DateTime, nullable=False,
                          default=datetime.now)

   def __repr__(self):
       return f'Todo : {self.name}'


@app.route("/")
def home():
   return render_template("home.html")


if __name__ == "__main__":
   app.run(debug=True)


Давайте добавим некоторые данные из интерпретатора Python( REPL )

$ python
Python 3.7.5 (default, Nov 20 2019, 09:21:52)
[GCC 9.2.1 20191008] on linux
Type "help", "copyright", "credits" or "license" for more information.

>>> from app import db, Task
>>> db.create_all()
>>> new_task = Task(name="Learn Flask")
>>> db.session.add(new_task)
>>> db.session.commit()
>>> tasks = Task.query.all()
>>> tasks
[Todo : Learn Flask]
>>>

Получение данных

Мы добавили наш первый, чтобы сделать это успешно из ОТВЕТА давайте отобразим их в нашем шаблоне home.html

from flask import Flask, render_template
from flask_sqlalchemy import SQLAlchemy  # add
from datetime import datetime  # add

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///todo.db'  # add
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False  # add
db = SQLAlchemy(app)  # add

# add


class Task(db.Model):
   id = db.Column(db.Integer, primary_key=True)
   name = db.Column(db.String(80), nullable=False)
   created_at = db.Column(db.DateTime, nullable=False,
                          default=datetime.now)

   def __repr__(self):
       return f'Todo : {self.name}'


@app.route("/")
def home():
   tasks = Task.query.order_by(Task.created_at) # add
   return render_template("home.html", tasks=tasks) # add


if __name__ == "__main__":
   app.run(debug=True)

Измените свой home.html файл

{% extends "base.html" %}
{% block content %}

Flask Todo List

{% if tasks %} {% for task in tasks %} {% endfor %} {% else %}

No Task to display

{% endif %}
{% endblock content %}

Откройте браузер, и вы увидите список задач.

Добавление новых данных

Давайте создадим новую задачу из html-шаблонов

Изменение функции home app.py

from flask import Flask, render_template, request, redirect  # add
from flask_sqlalchemy import SQLAlchemy  # add
from datetime import datetime  # add

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///todo.db'  # add
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False  # add
db = SQLAlchemy(app)  # add

# add


class Task(db.Model):
   id = db.Column(db.Integer, primary_key=True)
   name = db.Column(db.String(80), nullable=False)
   created_at = db.Column(db.DateTime, nullable=False,
                          default=datetime.now)

   def __repr__(self):
       return f'Todo : {self.name}'


@app.route("/", methods=['POST', 'GET'])
def home():
   if request.method == "POST": # add
       name = request.form['name']
       new_task = Task(name=name)
       db.session.add(new_task)
       db.session.commit()
       return redirect('/')
   else:
       tasks = Task.query.order_by(Task.created_at).all()  # add
   return render_template("home.html", tasks=tasks)  # add


if __name__ == "__main__":
   app.run(debug=True)

Изменение функции home app.py

{% extends "base.html" %}
{% block content %}

Flask Todo List

{% include "partials/_form.html" %}
{% if tasks %} {% for task in tasks %} {% endfor %} {% else %}

No Task to display

{% endif %}
{% endblock content %}

Создайте новую папку внутри templates , переименуйте ее partial и поместите в нее форму.

partials/_form.html

Теперь вы можете добавить новую задачу, получить все задачи, а как насчет удаления задачи ? Давайте сделаем это

Удаление данных

В app.py

# remove a task
...
@app.route('/delete/')
def delete(id):
   task = Task.query.get_or_404(id)

   try:
       db.session.delete(task)
       db.session.commit()
       return redirect('/')
   except Exception:
       return "There was a problem deleting data."
...

В home.html

...

  Remove

...

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

Обновление данных

В app.py

...

# update task
@app.route('/update/', methods=['GET', 'POST'])
def update(id):
   task = Task.query.get_or_404(id)

   if request.method == 'POST':
       task.name = request.form['name']

       try:
           db.session.commit()
           return redirect('/')
       except:
           return "There was a problem updating data."

   else:
       title = "Update Task"
       return render_template('update.html', title=title, task=task)
...

В update.html

{% extends 'base.html' %}
{% block content %}

{{ title }}

{% endblock content %}

Теперь у нас есть полностью функциональное приложение Flask , но если мы хотим показать миру наше новое приложение ?

Давайте развернем приложение с помощью Героку

Развертывание в Heroku

Инициализировать новый репозиторий git

$ git init
$ touch .gitignore
...

В .gitignore файл добавить:

# Created by https://www.gitignore.io/api/flask
# Edit at https://www.gitignore.io/?templates=flask

### Flask ###
instance/*
!instance/.gitignore
.webassets-cache

### Flask.Python Stack ###
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
#  Usually these files are written by a python script from a template
#  before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/

# Translations
*.mo
*.pot

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# pyenv
.python-version

# pipenv
#   According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
#   However, in case of collaboration, if having platform-specific dependencies or dependencies
#   having no cross-platform support, pipenv may install dependencies that don't work, or not
#   install all needed dependencies.
#Pipfile.lock

# celery beat schedule file
celerybeat-schedule

# SageMath parsed files
*.sage.py

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# Mr Developer
.mr.developer.cfg
.project
.pydevproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/

# End of https://www.gitignore.io/api/flask

Создайте Профиль и добавьте:

$ touch Procfile
...
web: gunicorn app:app

Войдите в Heroku с вашей учетной записью

$ heroku login
...

Зафиксируйте свой код в репозитории

$ git add .
$ git commit -m "Initial commit"
...

Создайте новое приложение на Heroku

heroku create flasktailwindtodo

Разверните свое приложение в Heroku

$ git push heroku master
#...

Откройте браузер с терминала с помощью Heroku

$ heroku open
#...

Поздравляю 😍 Увидимся в следующем уроке