One place for hosting & domains

      Flask

      Обработка данных входящих запросов в Flask


      Введение

      Веб-приложениям часто требуется обрабатывать данные входящих запросов пользователей. Эта полезная нагрузка может иметь форму строк запросов, данных форм и объектов JSON. Flask, как и любая другая веб-инфраструктура, предоставляет доступ к данным запросов.

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

      Предварительные требования

      Для данного обучающего руководства вам потребуется следующее:

      • Для данного проекта потребуется установить Python в локальной среде.
      • В этом проекте мы будем использовать инструмент Pipenv, предоставляющий отличные возможности упаковки для программирования на Python. Он предоставляет возможности Pipfile, pip и virtualenv в одной команде.
      • Для тестирования конечных точек API потребуется установить Postman или другой подобный инструмент.

      Для этого учебного модуля мы использовали версии Pipenv v2020.11.15, Python v3.9.0 и Flask v1.1.2.

      Настройка проекта

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

      Прежде всего, вам нужно будет создать каталог для проекта. Откройте терминал и запустите следующую команду:

      • mkdir flask_request_example

      Затем перейдите в новый каталог:

      Затем установите Flask. Откройте терминал и запустите следующую команду:

      Команда pipenv создаст среду virtualenv для этого проекта, Pipfile, install flask и Pipfile.lock.

      Для активации virtualenv этого проекта запустите следующую команду:

      Чтобы получить доступ к входящим данным в Flask, вам нужно будет использовать объект request. В объекте request хранятся все входящие данные запроса, включая тип MIME, источник, IP-адрес, необработанные данные, метод HTTP, заголовки и т. д.

      Хотя вся информация в объекте request может быть полезной для наших целей, в этом учебном модуле мы уделим основное внимание данным, которые обычно предоставляются вызывающей стороной напрямую.

      Чтобы получить доступ к запрашиваемому объекту в Flask, вам потребуется импортировать его из библиотеки Flask:

      from flask import request
      

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

      Используйте редактор кода для создания файла app.py. Импортируйте Flask и объект request. Также установите маршруты для query-example, form-example и json-example:

      app.py

      # import main Flask class and request object
      from flask import Flask, request
      
      # create the Flask app
      app = Flask(__name__)
      
      @app.route('/query-example')
      def query_example():
          return 'Query String Example'
      
      @app.route('/form-example')
      def form_example():
          return 'Form Data Example'
      
      @app.route('/json-example')
      def json_example():
          return 'JSON Object Example'
      
      if __name__ == '__main__':
          # run app in debug mode on port 5000
          app.run(debug=True, port=5000)
      

      Затем откройте терминал и запустите приложение с помощью следующей команды:

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

      http://127.0.0.1:5000/query-example (or localhost:5000/query-example)
      http://127.0.0.1:5000/form-example (or localhost:5000/form-example)
      http://127.0.0.1:5000/json-example (or localhost:5000/json-example)
      

      Код устанавливает три маршрута, и при открытии каждого маршрута вы увидите сообщения "Query String Example", "Form Data Example" и "JSON Object Example".

      Использование аргументов запроса

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

      Строка запроса выглядит следующим образом:

      example.com?arg1=value1&arg2=value2
      

      Строка запроса начинается после знака (?) вопроса:

      example.com?arg1=value1&arg2=value2
      

      В ней содержатся пары ключ-значение, разделенные символом амперсанда (&):

      example.com?arg1=value1&arg2=value2
      

      В каждой паре после ключа идет знак равенства (=), а затем идет значение.

      arg1 : value1
      arg2 : value2
      

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

      Давайте добавим строку запроса в маршрут query-example. В этом гипотетическом примере, мы укажем имя языка программирования, которое будет отображаться на экране. Создайте ключ "language" и значение "Python":

      http://127.0.0.1:5000/query-example?language=Python
      

      Если вы запустите приложение и перейдете к этому URL, вы увидите сообщение "Query String Example".

      Вам нужно будет программировать часть, обрабатывающую аргументы запроса. Этот код считает ключ language, используя request.args.get('language') или request.args['language'].

      При вызове request.args.get('language') приложение продолжит работу, если ключ language отсутствует по указанному URL. В этом случае данный метод будет иметь результат None.

      При вызове request.args['language'] приложение возвращает ошибку 400, если ключ language отсутствует по указанному URL.

      При работе со строками запросов, рекомендуется использовать request.args.get(), чтобы предотвратить возможные сбои в работе приложения.

      Давайте прочитаем ключ language и выведем его.

      Измените маршрут query-example в app.py с помощью следующего кода:

      app.py

      @app.route('/query-example')
      def query_example():
          # if key doesn't exist, returns None
          language = request.args.get('language')
      
          return '''<h1>The language value is: {}</h1>'''.format(language)
      

      Затем запустите приложение и перейдите к URL:

      http://127.0.0.1:5000/query-example?language=Python
      

      Браузер должен вывести следующее сообщение:

      Output

      The language value is: Python

      Аргумент из URL привязывается к переменной language, а затем возвращается через браузер.

      Чтобы добавить дополнительные параметры запроса, вы можете добавить амперсанды и новые пары ключ-значение в конце URL. Создайте ключ "framework" и значение "Flask":

      http://127.0.0.1:5000/query-example?language=Python&framework=Flask
      

      Если вам нужно больше, продолжайте добавлять амперсанды и пары ключ-значение. Создайте ключ "website" и значение "DigitalOcean":

      http://127.0.0.1:5000/query-example?language=Python&framework=Flask&website=DigitalOcean
      

      Чтобы получить доступ к этим значениям, мы все равно используем request.args.get() или request.args[]. Давайте используем оба варианта, чтобы продемонстрировать, что произойдет при отсутствии ключа. Измените маршрут query_example, чтобы назначить значение результатов переменным и вывести их:

      @app.route('/query-example')
      def query_example():
          # if key doesn't exist, returns None
          language = request.args.get('language')
      
          # if key doesn't exist, returns a 400, bad request error
          framework = request.args['framework']
      
          # if key doesn't exist, returns None
          website = request.args.get('website')
      
          return '''
                    <h1>The language value is: {}</h1>
                    <h1>The framework value is: {}</h1>
                    <h1>The website value is: {}'''.format(language, framework, website)
      

      Затем запустите приложение и перейдите к URL:

      http://127.0.0.1:5000/query-example?language=Python&framework=Flask&website=DigitalOcean
      

      Браузер должен вывести следующее сообщение:

      Output

      The language value is: Python The framework value is: Flask The website value is: DigitalOcean

      Удалите ключ language из URL:

      http://127.0.0.1:5000/query-example?framework=Flask&website=DigitalOcean
      

      Браузер должен вывести следующее сообщение со словом None, если для language будет отсутствовать значение:

      Output

      The language value is: None The framework value is: Flask The website value is: DigitalOcean

      Удалите ключ framework из URL:

      http://127.0.0.1:5000/query-example?language=Python&website=DigitalOcean
      

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

      Output

      werkzeug.exceptions.BadRequestKeyError werkzeug.exceptions.BadRequestKeyError: 400 Bad Request: The browser (or proxy) sent a request that this server could not understand. KeyError: 'framework'

      Теперь вы должны понимать, как следует обрабатывать строки запросов. Перейдем к следующему типу входящих данных.

      Использование данных форм

      Данные форм поступают из форм, отправленных на маршрут в виде запроса POST. Вместо отображения данных в URL (кроме случаев отправки форм в виде запроса GET) данные форм передаются приложению незаметно. Хотя вы не видите передаваемые данные форм, ваше приложение может их считывать.

      Чтобы продемонстрировать это, давайте изменим маршрут form-example в app.py так, чтобы принимать запросы GET и POST и возвращать форму:

      app.py

      # allow both GET and POST requests
      @app.route('/form-example', methods=['GET', 'POST'])
      def form_example():
          return '''
                    <form method="POST">
                        <div><label>Language: <input type="text" name="language"></label></div>
                        <div><label>Framework: <input type="text" name="framework"></label></div>
                        <input type="submit" value="Submit">
                    </form>'''
      

      Затем запустите приложение и перейдите к URL:

      http://127.0.0.1:5000/form-example
      

      Браузер должен отображать форму с двумя полями ввода: одно language и одно для framework, а также кнопку отправки.

      Важнее всего знать об этой форме то, что она выполняет запрос POST к тому же маршруту, который сгенерировал форму. Все ключи, которые считываются в приложении, поступают от атрибутов name в полях ввода формы. В этом случае language и framework являются именами полей ввода, и поэтому у вас будет доступ к ним в приложении.

      Внутри функции просмотра вам нужно будет проверить метод запроса: GET или POST. Если это запрос GET, вы можете вывести форму. В противном случае это запрос POST, и вам нужно обработать входящие данные.

      Измените маршрут form-example в app.py, добавив следующий код:

      app.py

      # allow both GET and POST requests
      @app.route('/form-example', methods=['GET', 'POST'])
      def form_example():
          # handle the POST request
          if request.method == 'POST':
              language = request.form.get('language')
              framework = request.form.get('framework')
              return '''
                        <h1>The language value is: {}</h1>
                        <h1>The framework value is: {}</h1>'''.format(language, framework)
      
          # otherwise handle the GET request
          return '''
                 <form method="POST">
                     <div><label>Language: <input type="text" name="language"></label></div>
                     <div><label>Framework: <input type="text" name="framework"></label></div>
                     <input type="submit" value="Submit">
                 </form>'''
      

      Затем запустите приложение и перейдите к URL:

      http://127.0.0.1:5000/form-example
      

      Введите в поле language значение Python, а в поле framework — значение Flask. Затем нажмите кнопку Submit.

      Браузер должен вывести следующее сообщение:

      Output

      The language value is: Python The framework value is: Flask

      Теперь вы понимаете, как обрабатывать данные формы. Перейдем к следующему типу входящих данных.

      Использование данных JSON

      Данные JSON обычно создаются процессом, который вызывает маршрут.

      Пример объекта JSON:

      {
        "language": "Python",
        "framework": "Flask",
        "website": "Scotch",
        "version_info": {
          "python": "3.9.0",
          "flask": "1.1.2"
        },
        "examples": ["query", "form", "json"],
        "boolean_test": true
      }
      

      Такая структура позволяет передавать более сложные данные, чем строки запросов и данные форм. В этом примере вы видите вложенные объекты JSON и массив элементов. Этот формат данных может обрабатываться Flask.

      Измените маршрут form-example в app.py, чтобы принимать запросы POST и игнорировать другие запросы, в частности GET:

      app.py

      @app.route('/json-example', methods=['POST'])
      def json_example():
          return 'JSON Object Example'
      

      Для строк запросов и данных форм в этом учебном модуле мы использовали браузер, но для отправки объекта JSON мы используем Postman, чтобы отправлять персонализированные запросы в URL.

      Примечание. Если вам нужна помощь в навигации по интерфейсу Postman для отправки запросов, воспользуйтесь официальной документацией.

      Добавьте URL в Postman и измените тип на POST. На вкладке body переключитесь на raw и выберите JSON из раскрывающегося списка.

      Эти настройки необходимы, чтобы Postman мог правильно отправлять данные JSON и чтобы ваше приложение Flask понимало, что получает данные JSON:

      POST http://127.0.0.1:5000/json-example
      Body
      raw JSON
      

      Затем скопируйте в поле ввода текста предыдущий пример JSON.

      Отправьте запрос. Вы должны получить ответ "JSON Object Example". Это не так интересно, но это ожидаемо, потому что код для обработки ответа данных JSON еще нужно написать.

      Чтобы читать данные, вам нужно понимать, как Flask преобразует данные JSON в структуры данных Python:

      • Все объекты конвертируются в словари Python. {"key" : "value"} в JSON соответствуют somedict['key'], который возвращает значение в Python.
      • Массив в JSON конвертируется в список в Python. Поскольку синтаксис одинаковый, приведем список примеров: [1,2,3,4,5]
      • Значения в кавычках объекта JSON станут строками в Python.
      • Логические операторы true и false становятся True и False в Python.
      • Числа без кавычек становятся числами в Python.

      Теперь давайте поработаем с кодом, чтобы считывать входящие данные JSON.

      Вначале добавим все содержимое объекта JSON в переменную, используя request.get_json().

      request.get_json() конвертирует объект JSON в данные Python. Давайте назначим данные входящего запроса в переменные и выведем их, внеся следующие изменения в маршрут json-example:

      app.py

      # GET requests will be blocked
      @app.route('/json-example', methods=['POST'])
      def json_example():
          request_data = request.get_json()
      
          language = request_data['language']
          framework = request_data['framework']
      
          # two keys are needed because of the nested object
          python_version = request_data['version_info']['python']
      
          # an index is needed because of the array
          example = request_data['examples'][0]
      
          boolean_test = request_data['boolean_test']
      
          return '''
                 The language value is: {}
                 The framework value is: {}
                 The Python version is: {}
                 The item at index 0 in the example list is: {}
                 The boolean value is: {}'''.format(language, framework, python_version, example, boolean_test)
      

      Обратите внимание на процедуру доступа к элементам, находящимся не на верхнем уровне. Поскольку мы вводим вложенный объект, используется ['version']['python']. А ['examples'][0] используется для доступа к индексу 0 в массиве example.

      Если объект JSON, отправленный с запросом, не имеет ключа, доступ к которому осуществляется через функцию view, запрос не будет выполняться. Если вы не хотите, чтобы запрос выдавал сбой при отсутствии ключа, вам нужно будет проверить наличие ключа, прежде чем пытаться получить к нему доступ.

      app.py

      # GET requests will be blocked
      @app.route('/json-example', methods=['POST'])
      def json_example():
          request_data = request.get_json()
      
          language = None
          framework = None
          python_version = None
          example = None
          boolean_test = None
      
          if request_data:
              if 'language' in request_data:
                  language = request_data['language']
      
              if 'framework' in request_data:
                  framework = request_data['framework']
      
              if 'version_info' in request_data:
                  if 'python' in request_data['version_info']:
                      python_version = request_data['version_info']['python']
      
              if 'examples' in request_data:
                  if (type(request_data['examples']) == list) and (len(request_data['examples']) > 0):
                      example = request_data['examples'][0]
      
              if 'boolean_test' in request_data:
                  boolean_test = request_data['boolean_test']
      
          return '''
                 The language value is: {}
                 The framework value is: {}
                 The Python version is: {}
                 The item at index 0 in the example list is: {}
                 The boolean value is: {}'''.format(language, framework, python_version, example, boolean_test)
      

      Запустите приложение и отправьте пример запроса JSON с помощью Postman. В ответе вы увидите следующее:

      Output

      The language value is: Python The framework value is: Flask The Python version is: 3.9 The item at index 0 in the example list is: query The boolean value is: false

      Теперь вы должны понимать принципы обработки объектов JSON.

      Заключение

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

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

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

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



      Source link

      Getting Started With Flask


      How to Join

      This Tech Talk is free and open to everyone. Register below to get a link to join the live stream or receive the video recording after it airs.

      Date Time RSVP
      March 17, 2021 11:00–12:00 p.m. ET / 4:00–5:00 p.m. GMT

      About the Talk

      Flask — a, free, open-source Python web application framework — is one of the best ways to build applications. It is a micro framework, meaning your entire application can fit inside a single Python source file.

      What You’ll Learn

      • How to use Flask to start an app
      • How Flask routes traffic to different endpoints
      • How Flask uses templates to create web pages

      This Talk Is Designed For

      Developers who want to build web applications using Python.

      Prerequisites

      Basic understanding of Python.

      Resources

      Flask documentation

      To join the live Tech Talk, register here.



      Source link

      How To Use Python-Markdown with Flask and SQLite


      The author selected the COVID-19 Relief Fund to receive a donation as part of the Write for DOnations program.

      Introduction

      Flask is a framework for building web applications using the Python language. With Flask, you can use SQLite as your database engine to store application data.

      Markdown is a markup language commonly used for the process of writing content in an easy-to-read text format. Using Markdown, you can format plain text with features such as headings, links, and images, you can then convert the text into HTML, which includes these formatting features. To learn how to use Markdown, check out the Markdown syntax standard.

      Python-Markdown is a Python library that allows you to convert Markdown text to HTML; it mostly follows the Markdown standard, with a few minor differences to the standard Markdown syntax.

      In this tutorial, you’ll use Flask, SQLite, and Python-Markdown to build a small note-taking web application that supports formatting text using Markdown. The app will allow users to display, create, and format notes with headings, links, lists, images, and other features. You’ll use the Bootstrap toolkit to style your application.

      Prerequisites

      Step 1 — Setting Up Dependencies

      In this step, you will activate your Python environment and install Flask and Python-Markdown using the pip package installer. Then you’ll create the database you will use to store notes and add some sample data to it.

      First, activate your programming environment if you haven’t already:

      Once you have activated your programming environment, install Flask and the Python-Markdown library using the following command:

      • pip install flask markdown

      Then create a database schema file called schema.sql, which will contain SQL commands to create a notes table. Open the file inside your flask_notes directory:

      Type the following SQL commands inside this file:

      flask_notes/schema.sql

      DROP TABLE IF EXISTS notes;
      
      CREATE TABLE notes (
          id INTEGER PRIMARY KEY AUTOINCREMENT,
          created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
          content TEXT NOT NULL
      );
      

      In this SQL file, you first delete any already existing table named notes, which could cause problems. This ensures that your notes table is exactly as described in this SQL. Note that this will delete all of the content you have in the database whenever you use these SQL commands, so ensure you don’t write any important content in the web application until you finish this tutorial and experiment with the final result.

      You use the CREATE TABLE notes statement to create the notes table with the following columns:

      • id: An integer that represents a primary key; the database will assign this a unique value for each entry (a note).
      • created: The note’s creation date; it will be automatically filled in with the time at which the note was added to the database.
      • content: The note’s content.

      Save and close the file.

      To create the database using the schema.sql file, open a file named init_db.py inside the flask_notes directory:

      Then add the following code:

      flask_notes/init_db.py

      
      import sqlite3
      
      connection = sqlite3.connect('database.db')
      
      
      with open('schema.sql') as f:
          connection.executescript(f.read())
      
      cur = connection.cursor()
      
      cur.execute("INSERT INTO notes (content) VALUES (?)", ('# The First Note',))
      cur.execute("INSERT INTO notes (content) VALUES (?)", ('_Another note_',))
      cur.execute("INSERT INTO notes (content) VALUES (?)", ('Visit [this page](https://www.digitalocean.com/community/tutorials) for more tutorials.',))
      
      connection.commit()
      connection.close()
      

      Here, you first import the sqlite3 module. Next, you connect to a file called database.db that will be created once you execute this program. database.db is the database that will hold all your application’s data. You then open the schema.sql file and run it using the executescript() method that executes multiple SQL statements at once. This will create the notes table.

      Using a Cursor object, you execute a few INSERT SQL statements to create three notes. You’re using Markdown syntax here: the first note is an <h1> heading, the second note is in italic, and the third note contains a link. You use the ? placeholder in the execute() method and pass a tuple containing the note’s content to safely insert data into the database.

      Finally, you commit the changes and close the connection.

      Save and close the file.

      Run the program:

      After execution, a new file called database.db will appear in your flask_notes directory.

      You’ve activated your environment, installed Flask and Python-Markdown, and created the SQLite database. Next, you’ll retrieve the Markdown notes from the database, convert them to HTML, and display them on the application’s homepage.

      Step 2 — Displaying the Notes on the Index Page

      In this step, you will create a Flask application that connects to the database and displays the sample data you have in the database. You will convert the Markdown text in the database to HTML and then render it on the index page.

      First, create the app.py application file inside your flask_notes directory:

      Add the following code to it:

      flask_notes/app.py

      import sqlite3
      import markdown
      from flask import Flask, render_template, request, flash, redirect, url_for
      
      def get_db_connection():
          conn = sqlite3.connect('database.db')
          conn.row_factory = sqlite3.Row
          return conn
      

      You first import the sqlite3 module, the markdown package, and Flask helpers.

      The get_db_connection() function opens a connection to the database.db database file and then sets the row_factory attribute to sqlite3.Row. This gives you name-based access to columns, which means that the database connection will return rows that behave like regular Python dictionaries. Lastly, the function returns the conn connection object you’ll be using to access the database.

      Following that, add the next snippet of code:

      flask_notes/app.py

      #. . .
      
      app = Flask(__name__)
      app.config['SECRET_KEY'] = 'this should be a secret random string'
      

      Here, you create the Flask application object and set a secret key to secure sessions.

      Then add the following code:

      flask_notes/app.py

      #. . .
      
      @app.route('/')
      def index():
          conn = get_db_connection()
          db_notes = conn.execute('SELECT id, created, content FROM notes;').fetchall()
          conn.close()
      
          notes = []
          for note in db_notes:
             note = dict(note)
             note['content'] = markdown.markdown(note['content'])
             notes.append(note)
      
          return render_template('index.html', notes=notes)
      

      The index() function is a Flask view function, which is a function decorated using the special @app.route decorator. Flask converts this function’s return value into an HTTP response that an HTTP client, such as a web browser, will display.

      In the index() view function, you open a database connection and you execute a SELECT SQL statement to fetch the ID, the creation date, and the content for all rows of the notes table. You use the fetchall() method to get a list of all the rows and save this data in the db_notes variable. Then, you close the connection.

      To convert the content of the notes from Markdown to HTML, you create a new empty list called notes. You loop through the db_notes list and convert each note from an sqlite3.Row to a regular Python dictionary using the dict() Python function to allow assignment. Next, you use the markdown.markdown() function to convert the value of note['content'] to HTML. For example, calling markdown.markdown('#Hi') would return the string '<h1>Hi</h1>' because in Markdown # represents the <h1> heading. After modifying note['content'], you append the note to the notes list.

      Finally, you render a template file called index.html, passing it the notes list.

      After all the additions, your file will be as follows:

      flask_notes/app.py

      import sqlite3
      import markdown
      from flask import Flask, render_template, request, flash, redirect, url_for
      
      def get_db_connection():
          conn = sqlite3.connect('database.db')
          conn.row_factory = sqlite3.Row
          return conn
      
      
      app = Flask(__name__)
      app.config['SECRET_KEY'] = 'this should be a secret random string'
      
      
      @app.route('/')
      def index():
          conn = get_db_connection()
          db_notes = conn.execute('SELECT id, created, content FROM notes;').fetchall()
          conn.close()
      
          notes = []
          for note in db_notes:
             note = dict(note)
             note['content'] = markdown.markdown(note['content'])
             notes.append(note)
      
          return render_template('index.html', notes=notes)
      

      Save and close the file.

      Next, you’ll create a base template and the index.html template file.

      In your flask_notes directory, create a templates directory and open a file called base.html inside it:

      • mkdir templates
      • nano templates/base.html

      Add the following code inside base.html; note that you’re using Bootstrap here. If you are not familiar with HTML templates in Flask, read Step 3 of How To Make a Web Application Using Flask in Python 3:

      flask_notes/templates/base.html

      <!doctype html>
      <html lang="en">
        <head>
          <!-- Required meta tags -->
          <meta charset="utf-8">
          <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
      
          <!-- Bootstrap CSS -->
          <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
      
          <title>{% block title %} {% endblock %}</title>
        </head>
        <body>
          <nav class="navbar navbar-expand-md navbar-light bg-light">
              <a class="navbar-brand" href="https://www.digitalocean.com/community/tutorials/{{ url_for("index')}}">FlaskNotes</a>
              <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
                  <span class="navbar-toggler-icon"></span>
              </button>
              <div class="collapse navbar-collapse" id="navbarNav">
                  <ul class="navbar-nav">
                  <li class="nav-item active">
                      <a class="nav-link" href="#">About</a>
                  </li>
                  </ul>
              </div>
          </nav>
          <div class="container">
              {% for message in get_flashed_messages() %}
                  <div class="alert alert-danger">{{ message }}</div>
              {% endfor %}
              {% block content %} {% endblock %}
          </div>
      
          <!-- Optional JavaScript -->
          <!-- jQuery first, then Popper.js, then Bootstrap JS -->
          <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
          <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
          <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
        </body>
      </html>
      

      Most of the code in the preceding block is standard HTML and code required for Bootstrap. The <meta> tags provide information for the web browser, the <link> tag links the Bootstrap CSS files, and the <script> tags are links to JavaScript code that allows some additional Bootstrap features.

      The <title>{% block title %} {% endblock %}</title> tag allows the inheriting templates to define a custom title. You use the for message in get_flashed_messages() loop to display the flashed messages, like warnings and alerts. The {% block content %} {% endblock %} placeholder is where inheriting templates place the content so that all templates have the extra code this base template provides to avoid repetition.

      Save and close the file.

      Next, create the index.html file that will extend this base.html file:

      • nano templates/index.html

      Add the following code to it:

      flask_notes/templates/index.html

      
      {% extends 'base.html' %}
      
      {% block content %}
          <h1>{% block title %} Welcome to FlaskNotes {% endblock %}</h1>
          {% for note in notes %}
          <div class="card">
              <div class="card-body">
                  <span class="badge badge-primary">#{{ note['id'] }}</span>
                  <span class="badge badge-default">{{ note['created'] }}</span>
                  <hr>
                  <p>{{ note['content'] |safe }}</p>
              </div>
          </div>
          <hr>
          {% endfor %}
      {% endblock %}
      

      Here you extend base.html, you define a title, and you use a for loop to go through notes displaying each note in a Bootstrap card. You display the note’s ID, the note’s creation date, and the note’s content, which you converted into HTML in the index() view function.

      You use the |safe Jinja filter, which you apply to the content using |; this is similar to calling a function in Python (in a similar way to safe(note['content'])). The |safe filter allows the browser to render HTML code—if it was not applied, it will display the HTML as plain text. This is usually referred to as “escaping HTML,” which is a security feature that prevents malicious HTML from being interpreted in the browser that would result in a dangerous security vulnerability called cross-site scripting (XSS). Since the Python-Markdown library returns safe HTML, you can allow the browser to render it using the |safe filter. Remember not to use this filter until you are certain that the HTML code you allow is safe and trusted.

      For more, read Flask’s documentation on controlling autoescaping.

      Save and close the file.

      Set the environment variables Flask needs and run the application using the following commands:

      • export FLASK_APP=app
      • export FLASK_ENV=development
      • flask run

      The FLASK_APP environment variable specifies the application you want to run (the app.py file). The FLASK_ENV environment variable specifies the mode; development means that the application will run in development mode with the debugger running (remember to avoid using this mode in production). You run the application using the flask run command.

      Open a browser and type in the URL http://127.0.0.1:5000/.

      Flask Notes Index

      Here, you’ll find that each note is formatted and rendered as HTML in the browser instead of plain text.

      You created a Flask application that connects to the database, fetches notes, converts their content from Markdown text to HTML, and then renders them on the index page. Next, you’ll add a route to allow users to add new notes, which they can write using Markdown syntax.

      Step 3 — Adding New Notes

      In this step, you’ll add a new route that will allow users to take new notes. Users can use Markdown syntax to write their notes—your application will save the notes to the database, which it will then display on the index page with the proper formatting. You will also add a button to the navigation bar that takes users to this new page.

      You will use web forms to allow users to submit data in your Flask application and you’ll store user-submitted data in your database.

      First open the app.py file to add a new route:

      Add the following code to the end of the file:

      flask_notes/app.py

      #. . .
      
      @app.route('/create/', methods=('GET', 'POST'))
      def create():
          conn = get_db_connection()
      
          if request.method == 'POST':
              content = request.form['content']
              if not content:
                  flash('Content is required!')
                  return redirect(url_for('index'))
              conn.execute('INSERT INTO notes (content) VALUES (?)', (content,))
              conn.commit()
              conn.close()
              return redirect(url_for('index'))
      
          return render_template('create.html')
      

      Since you will use this route to insert new data to the database via a web form, you allow both GET and POST requests using methods=('GET', 'POST') in the app.route() decorator. In the create() view function, you open a database connection.

      If the user has submitted a form that means the condition request.method == 'POST' is true, so you extract the note’s content that the user has submitted using request.form['content'] and save it to a variable called content. If the content is empty, you flash a 'Content is required!' message and redirect the user to the index page. If the content was not empty, you use an INSERT SQL statement to add the note’s content to the notes table. You commit the changes and close the connection, then you redirect the user to the index page.

      If the request is a GET request, meaning the user has just visited the page, you render a template file called create.html.

      Save and close the file.

      Next, open the create.html template file:

      • nano templates/create.html

      Add the following code to it:

      flask_notes/templates/create.html

      {% extends 'base.html' %}
      
      {% block content %}
          <h1>{% block title %} Add a New Note {% endblock %}</h1>
          <form method="post">
          <div class="form-group">
              <label for="content">Note Content</label>
              <textarea type="text" name="content"
                     placeholder="Note content, you can use Markdown syntax" class="form-control"
                     value="{{ request.form['content'] }}" autofocus></textarea>
          </div>
      
          <div class="form-group">
              <button type="submit" class="btn btn-primary">Submit</button>
          </div>
          </form>
      
      {% endblock %}
      

      Here, you use a form with a text area for the note’s content. You use request.form to access the form data that is stored in case something goes wrong with your form submission (for example, if no content was provided). You add a submit button under the text area for the user to press to send data to the application in a POST request.

      Save and close the file.

      Next open the base.html file to add a New Note button to the navigation bar:

      Edit the file with the highlighted code as follows:

      flask_notes/templates/base.html

      <!doctype html>
      <html lang="en">
        <head>
          <!-- Required meta tags -->
          <meta charset="utf-8">
          <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
      
          <!-- Bootstrap CSS -->
          <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
      
          <title>{% block title %} {% endblock %}</title>
        </head>
        <body>
          <nav class="navbar navbar-expand-md navbar-light bg-light">
              <a class="navbar-brand" href="https://www.digitalocean.com/community/tutorials/{{ url_for("index')}}">FlaskNotes</a>
              <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
                  <span class="navbar-toggler-icon"></span>
              </button>
              <div class="collapse navbar-collapse" id="navbarNav">
                  <ul class="navbar-nav">
                  <li class="nav-item active">
                      <a class="nav-link" href="#">About</a>
                  </li>
      
                  <li class="nav-item active">
                      <a class="nav-link" href="https://www.digitalocean.com/community/tutorials/{{ url_for("create') }}">New Note</a>
                 </li>
                  </ul>
              </div>
          </nav>
          <div class="container">
              {% for message in get_flashed_messages() %}
                  <div class="alert alert-danger">{{ message }}</div>
              {% endfor %}
              {% block content %} {% endblock %}
          </div>
      
          <!-- Optional JavaScript -->
          <!-- jQuery first, then Popper.js, then Bootstrap JS -->
          <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
          <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
          <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
        </body>
      </html>
      

      You add a new <li> item to the navigation bar with the url_for() function to link to the create() view function. With this, you can access the page for creating a new note from the navigation bar.

      Run the development server if you haven’t already:

      Use your browser to go to http://127.0.0.1:5000/create and add the following markdown note:

      ### Flask
      Flask is a **web** framework for _Python_.
      
      Here is the Flask logo:
      
      ![Flask Logo](https://flask.palletsprojects.com/en/1.1.x/_images/flask-logo.png)
      

      This markdown contains an h3 heading, the word web in bold, the word Python in italic, and an image.

      Submit the note, you will find that your application formats it into HTML.

      Markdown Formatted Note

      You now have a new route that allows users to add new notes to the database. Users can take notes with Markdown formatting and the application will display the notes in HTML on the index page.

      You can access the full code for the application from this repository.

      Conclusion

      You created a Flask application for taking notes in Markdown format to allow users to use text formatting such as headings, bold and italic text, adding images and links, among other things. You connected your application to a SQLite database to store and retrieve your data. You’ve incorporated Markdown text into HTML conversion so that notes will render on the page. To learn more about using Markdown in Python, read How To Use Python-Markdown to Convert Markdown Text to HTML.

      For further information about Flask, check out the following tutorials:



      Source link