[PYTHON] Understanding how to use Jinja2 makes development with Flask smarter

Currently, I am making something like a web service using Flask, but I often get stuck in Jinja2 notation after passing the value from the server side to the client side, so make a note of it.

Overview

What is Flask

A micro web development framework for Python. I think there is no problem with Sinatra in Ruby. I think there are many other articles on how to install and use Flask, so I will omit them here. I'm also happy to have a Japanese-language guide like the Flask User Guide. Flask relies on the Jinja2 </ b> template engine and the Werkzeug WSGI toolkit.

The trouble is that there is also a Jinja2 documentation, but this is in English. Jinja2 Documentation

In this article, Flask will describe the basic usage of Jinja2.

First of all, basic Flask usage

Directory structure

First, create a directory such as the project name. Here, qiita_flask is the project name. From the directory structure

qiita_flask
├── app.py
└── templates
    └── index.html

Please make it like this. app.py can have a different name, but the templates directory must have this name.

app.py describes server-side processing, and client-side is described in index.html etc. in templates.

Each file

app.py


# coding: utf-8
from flask import Flask, render_template
app = Flask(__name__) #Instance generation

@app.route("/") #When the access route is matched
def hello(): #The hello function works.
  return "Hello World!" #On the browser screen"Hello World!"Is output.

@app.route("/index") #application/When the index is accessed
def index():
   return render_template('index.html') #/When access comes to index, index in templates.html opens
#This is the point when passing something from the server side to the client side.

if __name__ == "__main__":
    #Web server launch
    app.run()

index.html


<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS" crossorigin="anonymous"></script>
  </head>
  <body>
    <div class="container">
      <div class="header">
        <h3 class="text-muted">Sample Page</h3>
      </div>
    </div>
  </body>
</html>

Now let's run app.py. After that, when you access [http: // localhost: 5000](http: // localhost: 5000), you should see "Hello World!" When you visit [http: // localhost: 5000 / index](http: // localhost: 5000 / index), Bootstrap should display Sample Page in a slightly fashionable way. I personally think that it is a good point that you can easily make something like that with Flask + Bootstrap like this. Focusing on the basic usage of Jinja2, there is no further explanation of how to use Flask and Bootstrap.

Basic usage of Jinja2

From this point onward, information will be given from the server side to the client side when calling index.html. To try it out, go to [http: // localhost: 5000 / index](http: // localhost: 5000 / index).

Pass String from server side to client side

app.py


#Omission
@app.route("/index")
def index():
	message = 'sample_string'
	return render_template('index.html', message=message)

index.html


{#Omission#}
  <body>
    <div class="container">
      <div class="header">
        <h3 class="text-muted">Sample Page</h3>
        {% if message %}
          <p>{{message}}</p>
        {% endif %}
      </div>
    </div>
  </body>

Render_template ('index.html', message = message) as above That means passing a variable called message when reading index.html. And on the html side, {% if message%} means that something is in the variable called message. {{message}} will display what is in the variable called message.

Pass a dictionary type variable

app.py


#Omission
@app.route("/index")
def index():
	my_dic = {}
	my_dic['name'] = ryo2851
	my_dic['univ'] = 'hogehoge University'
	return render_template('index.html', message=my_dic)  

index.html


{#Omission#}
  <body>
    <div class="container">
      <div class="header">
        <h3 class="text-muted">Sample Page</h3>
        {% if message %}
          <p>name: {{message.name}}</p>
          <p>univ: {{message.univ}}</p>
        {% endif %}
      </div>
    </div>
  </body>

Pass the list

app.py


import numpy as np
#Omission
@app.route("/index")
def index():
	num_list = np.arange(10)
	return render_template('index.html', message=num_list)

index.html


{#Omission#}
  <body>
    <div class="container">
      <div class="header">
        <h3 class="text-muted">Sample Page</h3>
        {% for num in message %}
          <p>{{num}}</p>
        {% endfor %}
      </div>
    </div>
  </body>

A little application

Create a directory for images

Images are saved in a directory called static.

qiita_flask
├── app.py
├── static
│   ├── qiita1.png
│   └── qiita2.png
└── templates
    └── index.html

It will be configured like this. Sorry to trouble you, but please prepare a few suitable images. The name is also appropriate and it's okay.

Elements pass a dictionary-type list

For example, if you want to use an image link

<a href = http://hogehoge.com><img src = "hoge.png "> </a>

You need the destination URL and the name of the image, such as. We will send URL and image information from the server side to the client side.

app.py


from os.path import join, relpath
from glob import glob
#Omission
@app.route("/index") #application/When the index is accessed
def index():
  path = "./static" 
  image_names = [relpath(x, path) for x in glob(join(path, '*.png'))]
  #In static.png file is image_It is stored in names.
  my_list = []
  for image in image_names:
    my_dic = {}
    my_dic['image_name'] = 'static/' + image
    my_dic['link_url'] = 'http://qiita.com/ryo2851/items/4e3c287d5a0005780034'
    #I couldn't secure many URLs to jump to, so I tried to jump to the same URL for every image.
    my_list.append(my_dic)
  return render_template('index.html', message = my_list) #/When access comes to index, index in templates.html opens

index.html


{#Omission#}
  <body>
    <div class="container">
      <div class="header">
        <h3 class="text-muted">Sample Page</h3>
        {% for item in message %}
          <a href={{item.link_url}} class="thumbnail"><img src={{item.image_name}}></a>
          {% endfor %}
      </div>
  </body>

The link in the source is my past article. Please have a look if you have time. Now go to / index![Screenshot 2016-07-14 23.49.13.png](https://qiita-image-store.s3.amazonaws.com/0/83457/f38882b1-3074-17f5-8bcf -c05ab3a60aea.png "Screenshot 2016-07-14 23.49.13.png ") It should look like this. You can jump to the link by clicking each image.

application

Incorporate Jinja2 in html to be smart.

I want to display the names of members of that grade in a pull-down menu when I press a button like the one in the image below. スクリーンショット 2016-07-15 2.35.31.png

Stupid honest coding

Stupid honestly try to write in html

index.html


{#Omission#}
<body>
    <div class="container">
      <div class="header">
        <h3 class="text-muted">Sample Page</h3>
      </div>
      <hr/>

      <div class="btn-group" role="group">
        <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
          B4
        </button>
        <ul class="dropdown-menu">
            <li><a href="#">B4taro</a></li>
            <li><a href="#">B4Jiro</a></li>
            <li><a href="#">B4hanako</a></li>
        </ul>
      </div>
      <div class="btn-group" role="group">
        <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
          M1
        </button>
        <ul class="dropdown-menu">
            <li><a href="#">M1taro</a></li>
            <li><a href="#">M1Jiro</a></li>
            <li><a href="#">M1hanako</a></li>
        </ul>
      </div>
      <div class="btn-group" role="group">
        <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
          M2
        </button>
        <ul class="dropdown-menu">
            <li><a href="#">M2taro</a></li>
            <li><a href="#">M2Jiro</a></li>
            <li><a href="#">M2hanako</a></li>
        </ul>
      </div>
    </div>
  </body>

You've written similar code repeatedly.

Coding using Jinja2

I will write using Jinja2 and also on the server side.

app.py


#Omission
@app.route("/index") 
def index():
  member_dic = {}
  B4_list = ['B4taro', 'B4jiro', 'B4hanako']
  M1_list = ['M1taro', 'M1jiro', 'M1hanako']
  M2_list = ['M2taro', 'M2jiro', 'M2hanako']
  member_dic['B4'] = B4_list
  member_dic['M1'] = M1_list
  member_dic['M2'] = M2_list
  return render_template('index.html', message=member_dic)

index.html


{#Omission#}
<body>
    <div class="container">
      <div class="header">
        <h3 class="text-muted">Sample Page</h3>
      </div>
      <hr/>
    {% for grade in message.keys() %}
        <div class="btn-group" role="group">
            <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                {{ grade }}
            </button>
            <ul class="dropdown-menu">
                {% for name in message[grade] %}
                    <li><a href="#">{{ name }}</a></li>
                {% endfor %}
            </ul>
        </div>
    {% endfor %}
    </div>
  </body>

If it is a pattern without ingenuity, for example, when you put in B4, M1, M2, Doctor, Professor, you will want to cry. If you already have a DB with registered members, I think the server side will be simpler. By using Jinja2, I was able to write html on the client side very neatly.

Recommended Posts

Understanding how to use Jinja2 makes development with Flask smarter
Python: How to use async with
How to use FTP with Python
How to use an external editor for Python development with Grasshopper
How to use ManyToManyField with Django's Admin
How to use OpenVPN with Ubuntu 18.04.3 LTS
How to use Cmder with PyCharm (Windows)
How to use Ass / Alembic with HtoA
How to use Japanese with NLTK plot
How to use jupyter notebook with ABCI
How to use CUT command (with sample)
How to use SQLAlchemy / Connect with aiomysql
How to use JDBC driver with Redash
How to use PyCharm with Glue development endpoints running inside a VPC
How to use GCP trace with open Telemetry
How to use tkinter with python in pyenv
How to use xml.etree.ElementTree
How to use Python-shell
How to use tf.data
How to use virtualenv
How to use Seaboan
How to use image-match
How to use shogun
How to use Pandas 2
How to use numpy.vectorize
How to use pytest_report_header
Easy to use Flask
How to use partial
How to use Bio.Phylo
How to use SymPy
How to use x-means
How to use WikiExtractor.py
How to use IPython
How to use virtualenv
How to use Matplotlib
How to use iptables
How to use numpy
How to use TokyoTechFes2015
How to use venv
How to use dictionary {}
How to use Pyenv
How to use list []
How to use python-kabusapi
How to use OptParse
How to use return
How to use dotenv
How to use pyenv-virtualenv
How to use Go.mod
How to use imutils
How to use import
How to use xgboost: Multi-class classification with iris data
How to use App Engine's local development server dev_appserver.py
How to use python interactive mode with git bash
How to upload with Heroku, Flask, Python, Git (Part 1)
How to upload with Heroku, Flask, Python, Git (Part 2)
Autoencoder with Chainer (Notes on how to use + trainer)
Scraping with Python-Selenium is old! ?? ・ ・ ・ How to use Pyppeteer
How to make a Cisco Webex Teams BOT with Flask
How to use Qt Designer
How to use search sorted
[gensim] How to use Doc2Vec