Hello. An entry in the Python category for Advent Calendar 2019.
He started writing Python as a hobby at the end of 2018, and is a person from a different industry and has no practical experience. Today, I tried to write a model and a view using Flask, and I had a lot of trouble, so I would like to write it. In particular, it was extremely difficult to delete. There may be a lot of strange things, but it worked for the time being. It is for beginners.
app.py
from flask import Flask,render_template,request,redirect
app = Flask(__name__)
class DatabaseInit():
db = []
def __init__(self):
pass
class DatabaseManager(DatabaseInit):
def db_append(self,add_value):
self.db.append(add_value)
def db_get(self):
return self.db
def db_delete(self,value):
self.db.pop(value)
@app.route('/', methods=['POST','GET'])
def index():
if request.method == 'GET':
db = DatabaseInit()
return render_template('index.html')
if request.method == 'POST':
db_manage = DatabaseManager()
num = request.form.get('comment')
if num == None:
view_lists = db_manage.db_get()
else:
db_manage.db_append(num)
view_lists = db_manage.db_get()
return render_template('index.html', show_lists = view_lists)
@app.route('/delete', methods=['POST'])
def delete():
db_manage = DatabaseManager()
id = int(request.form['delete_id'])
db_manage.db_delete(id)
return redirect('/',code=307)
if __name__ == '__main__':
app.run(host='127.0.0.1',port='5000',debug=True)
index.html
<html>
<head>
<title>Flask</title>
</head>
<body>
<h1>Flask WEB app</h1>
<h2>Comment registration</h2>
<form action="/" name="comment" method="POST">
<input type="text" name="comment">
<input type="submit" name="submit_comment">
</form>
<h2>Comment display</h2>
{% for show_list in show_lists %}
{{ show_list }}
<form method="POST" name="delete" action="/delete">
<input type="hidden" name="delete_id" value="{{ show_lists.index(show_list) }}">
<input type="submit" name="delete_id" value="Delete">
</form>
</br>
{% endfor %}
</body>
</html>
--Since SQL couldn't be written in full scratch, use an array instead of a database --Manipulate database with model class --Minimize the number of files
python -m venv venv
source venv/bin/activate
pip install flask
touch app.py
Flask needs to put the html in the templates folder.
mkdir templates
cd templates
touch index.html
/ Working folder ┝app.py ┗/templates ┗index.html HelloWorld
app.py
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return 'Hello World'
if __name__ == '__main__':
app.run()
python app.py
If you set the debug mode to True, it will be reflected just by updating the browser, so it is easy. If you set @ app.route ('/'), it will be treated as GET. In other words, it will be the screen that is displayed when you access the root URL.
app.py
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return 'Hello World'
if __name__ == '__main__':
app.run(host='127.0.0.1',port='5000',debug=True)
Import render_template.
index.html
<html>
<head>
<title>Flask</title>
</head>
<body>
<h1>Hello World</h1>
<p>This is html.</p>
</body>
</html>
app.py
from flask import Flask,render_template
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html')
if __name__ == '__main__':
app.run(host='127.0.0.1', port='5000', debug=True)
action ='/' means to send data to'/'. For example, if you want to move to another page, write'/ something' and the data will be sent to that URL. Since this is a single page, we will send the data to the current'/'. method = "POST" sends the data by POST. The image is that GET publishes data to a URL and sends data, and POST hides data and sends data. This time, the page initialized at the time of GET is displayed, and the page that updated the data sent in the form is displayed in the case of POST. name ='comment' is required to receive the data in app.py. You can use any character string you like.
index.html
<html>
<head>
<title>Flask</title>
</head>
<body>
<h1>Flask WEB app</h1>
<h2>Comment registration</h2>
<form action="/" name="comment" method="POST">
<input type="text" name="comment">
<input type="submit" name="submit_comment">
</form>
<h2>Comment display</h2>
</body>
</html>
Flask uses a template engine called jinja2. On the python side, write the variable name on the html side = the variable name on the python side in the argument of the render_template () function. On the html side, it can be displayed by typing {{variable name on the html side}}.
app.py
from flask import Flask,render_template
app = Flask(__name__)
@app.route('/')
def index():
show_py = 'I'm from python'
return render_template('index.html',show_html = show_py)
if __name__ == '__main__':
app.run(host='127.0.0.1', port='5000', debug=True)
index.html
<html>
<head>
<title>Flask</title>
</head>
<body>
<h1>Flask WEB app</h1>
<h2>Comment registration</h2>
<form action="/" name="comment" method="POST">
<input type="text" name="comment">
<input type="submit" name="submit_comment">
</form>
<h2>Comment display</h2>
{{ show_html }}
</body>
</html>
This time we will do the database as an array. Initialize the array with DatabaseInit. Create a method in DatabaseManager and use that method to operate the database. This time, I created three functions: add element, get element, and delete element. I used an array this time, but I think that the idea is the same as long as it is rewritten to SQL or DB.
If you don't want to write anything but need to write something, write pass. The point is to do nothing. The instance is assigned to self. In Python, the first argument of each method is always self. def __ init __ (self): is executed when instantiated. class DatabaseManager (DatabaseInit) is an inheritance. Inheriting to access list db.
app.py
class DatabaseInit():
db = []
def __init__(self):
pass
class DatabaseManager(DatabaseInit):
def db_append(self,add_value):
self.db.append(add_value)
def db_get(self):
return self.db
def db_delete(self,value):
self.db.pop(value)
Set method = ['GET','POST'] so that it can be accessed by both GET and POST. GET is the screen you see when you first access it, and POST is the screen you see when the data is sent. Process it with an if statement. Judge with request.method ==. Instantiate the DatabaseInit class with db = DatabaseInit (). In other words, this time we are creating an empty array called db. The POST process also has a nested if statement. This is to separate the process of sending a character string in the html form and the process of deleting it. num = request.form.get ('comment') is assigned when the string is sent in the html form. There is an if num == None :, which means that when the deletion is sent, it will lead to this process. When the string is sent, else: is processed: db_manage.db_append (num) adds the string assigned to the num variable to the array. I'm getting the array with db_manage.db_get ().
app.py
from flask import Flask,render_template,request,redirect
app = Flask(__name__)
@app.route('/', methods=['POST','GET'])
def index():
if request.method == 'GET':
db = DatabaseInit()
return render_template('index.html')
if request.method == 'POST':
db_manage = DatabaseManager()
num = request.form.get('comment')
if num == None:
view_lists = db_manage.db_get()
else:
db_manage.db_append(num)
view_lists = db_manage.db_get()
return render_template('index.html', show_lists = view_lists)
In jinja2, you can embed python code by enclosing it in {%%}. Since we want to output the list one by one, enclose the process to be repeated with {% for xx in xxx%} ~ {% endfor%}. If is written as {% if expression%} ~ {% endif%}.
index.html
<html>
<head>
<title>Flask</title>
</head>
<body>
<h1>Flask WEB app</h1>
<h2>Comment registration</h2>
<form action="/" name="comment" method="POST">
<input type="text" name="comment">
<input type="submit" name="submit_comment">
</form>
<h2>Comment display</h2>
{% for show_list in show_lists %}
{{ show_list }}
<form method="POST" name="delete" action="/delete">
<input type="hidden" name="delete_id" value="{{ show_lists.index(show_list) }}">
<input type="submit" name="delete_id" value="Delete">
</form>
</br>
{% endfor %}
</body>
</html>
The most addictive part was the delete part. Since it is a specification that only POST and GET can be sent with a normal form, use type = "hidden" and send name = "delete_id" and value = "{{show_lists.index (show_list)}}" in post. .. It does not appear on the screen. Since the recognition of form is a little weak, there may be places where it is not necessary to describe the name. .. Please let me know. ..
When the delete button is pressed, post will get the index value of the array to be deleted, and the db_delete () method will delete the element from the array. Since the data acquired by request.form is a character string, type convert it with int (). redirect () means to force the page to move. With render_template (), a page will be created at the current URL, so a strange URL such as local / delete / index.html will result in an error. '/' will be routed to the def index (): function. code = 307 means redirect with POST. Since the redirect will send data by GET, by setting the code to 307, it will be an operation to maintain POST.
app.py
@app.route('/delete', methods=['POST'])
def delete():
db_manage = DatabaseManager()
id = int(request.form['delete_id'])
db_manage.db_delete(id)
return redirect('/',code=307)
For the first time, I wrote something technically on Qiita properly, so I think that there are many parts that are not fully explained, but I hope it helps someone. If you find any mistakes, please let us know and we will correct them.
Next time I would like to try using DB!