Python 10
Flask
If you know Javascript, there is a famous framework called react
. If you don’t know Javascript or react, it is fine. In python, prominent frameworks are Flask
and Django
.
It helps to build an app with many built-in functions that allow connecting with a web server.
Let’s look at the basic structure of Flask
with the counter app.
Check out the original app build here 👉 https://youtu.be/B9nFMZIYQl0
Please use replit to follow; it is simple to use for beginners! 👉 https://replit.com/
Counter App with Flask
At the top of the file, there are some codes for importing. import
brings another function from a different file
from flask import Flask, render_template_string
from replit import db
# original
# import counter_app
# from counter_app import home_page, app, show, db
Ignore this part for now, and press run
Basic Flask
functions
import counter_app
from counter_app import home_page, app, show, db
@app.route('/')
def home():
return 'HOME PAGE'
# running the app
app.run(host='0.0.0.0', port=81)
There are some helper functions from counter_app, and later we will replace it to flask functions.
The first replacement is the app function that can be replaced with app = Flask(__name__)
This is how we initialize the flask app, and we need to import Flask
function from flask
. You don’t need to memorize this, and we can go to the flask webpage to learn more 👇
https://flask.palletsprojects.com/en/2.2.x/quickstart/
For now, we need to focus on app.route('/')
@app.route('/')
def home():
return 'HOME PAGE'
We already know what the home page is. It shows the root of the page, and /
means the path for the URL.
@app.route('/')
, routing us to the page where inside of ()
, and in this case, it is the home page(root page).
def home():
return 'HOME PAGE'
Another part is a function, which we are familiar with. It doesn’t have to be home
, it is just the function’s name.
And it returns HOME PAGE
in our preview.
In this part, we need to return our html
code like return <h1>Hello Python</h1>
Try to change your return statement with HTML tags and refresh(press stop and re-run the server) the app.
app.route('/')
and functiondef home():
goes together 👇
# For example...
@app.route('/')
def home():
return 'HOME PAGE'
# Another route
@app.route('/my_page')
def my_page():
return 'My page'
HTML & CSS
Now we need to write our html code for the home page. HTML is a static code, meaning it cannot calculate or do action-like functions. It can only show the page that is written in the file.
my_home_page = '''
<h1>Number here</h1>
<div>
<form action='/decrement'>
<button type='submit'>-</button>
</form>
<form action='/increment'>
<button type='submit'>+</button>
</form>
</div>
'''
Here is a simple html code for the home page, now we want to render this page in our app.
How do we render this in our app? It is simple, we can just return
the variable my_home_page
And in flask
, there is a helpful function to render html tags without an error: render_template_string
Now our app should look below
import counter_app
from counter_app import db # deleted
from flask import Flask, render_template_string # 👈 don't forget to add
app = Flask(__name__)
my_home_page = '''
<h1>Number here</h1>
<div>
<form action='/decrement'>
<button type='submit'>-</button>
</form>
<form action='/increment'>
<button type='submit'>+</button>
</form>
</div>
'''
@app.route('/')
def home():
return render_template_string(my_home_page)
app.run(host='0.0.0.0', port=81)
If you see the Number here
and -
, +
buttons, we are ready to go next step.
We now have
render_template_string
to replaceshow()
,my_home_page
to replacehome_page
andapp = Flask(__name__)
to replaceapp
fromcounter_app
. We can delete three of them, but keepdb
Route
When we click the plus and minus buttons, we will see 404 Not found pages. That’s because we haven’t created the routes
for that pages.
We can create another app.route()
to create another route. But this time, the name in the parenthesis will be different.
@app.route('/decrement')
Create your own function that returns a page with the text decrement page
Toggle Answer 👇
@app.route('/decrement')
def decrement():
return 'decrement page'
Now try to finish the increment route with the same logic.
And when we click the minus button, we can now see it takes us to /decrement
route in the address bar.
Dynamic data
By far, we connect our buttons to each route. But we don’t want to see a different page. We want to increment or decrement numbers.
In order to do that, let’s briefly talk about dynamic data. Unlike static data, python can calculate numbers or take an action and we call this dynamic data.
But how do we pass python code
into html
?
my_home_page = '''
<h1></h1>
<div>
<form action='/decrement'>
<button type='submit'>-</button>
</form>
<form action='/increment'>
<button type='submit'>+</button>
</form>
</div>
'''
@app.route('/')
def home():
return render_template_string(my_home_page, number=0)
Take a look code above. Do you notice the differences compared to the previous code?
We added hard coded number=0
in the render_template_string()
function, and `` inside of the <h1>
tag. It can be <span>
too.
And to see the same result in different browsers routes, we can render the same number
and my_home_page
like this:
my_home_page = '''
<span></span>
<div>
<form action='/decrement'>
<button type='submit'>-</button>
</form>
<form action='/increment'>
<button type='submit'>+</button>
</form>
</div>
'''
@app.route('/')
def home():
return render_template_string(my_home_page, number=0)
@app.route('/decrement')
def decrement():
return render_template_string(my_home_page, number=0)
@app.route('/increment')
def increment():
return render_template_string(my_home_page, number=0)
app.run(host='0.0.0.0', port=81)
By doing this, we now have the hard-coded number 0 in our file. Also, if we click the buttons, it takes us to a different route, but still, we see the same html
.
Counter database
We have the hard-coded number 0, but it is not counting the numbers. To count numbers, we are going to create a temporary database.
database = {
'number': 0
}
Do you remember how to access the dictionary data? To change our hard coded number=0
, you can call database['number']
database in the app.
@app.route('/')
def home():
return render_template_string(my_home_page, number=database['number'])
Now we have the database, we can finish our increment
and decrement
function.
To decrement function with the data, we need to access the database and decrement the number.
database['number'] -= 1
# This code is the same as
database['number'] = database['number'] - 1
As a result, our decrement
function should look like this with route
@app.route('/decrement')
def decrement():
database['number'] -= 1
return render_template_string(my_home_page, number=database['number'])
Try to write your own increment function and continue.
Now we have a ‘temporary’ database, which means when we run the server each time, the database will reset the number to 0. If we want to save the number in a real-time database, we can use replit databse
Take the steps above, and cut and paste the line from replit import db
to the top.
Replace database
with db
, but there is one additional step we need to remember. What if db
from replit
does not have number
and 0
key-value pair?
To prevent that case, add this code where database
existed.
if 'number' not in db:
db['number'] = 0
Our code now should look like this:
import counter_app
from flask import Flask, render_template_string # 👈 don't forget to add
from replit import db
app = Flask(__name__)
# db = { 'number': 0 }
if 'number' not in db:
db['number'] = 0
my_home_page = '''
<span></span>
<div>
<form action='/decrement'>
<button type='submit'>-</button>
</form>
<form action='/increment'>
<button type='submit'>+</button>
</form>
</div>
'''
@app.route('/')
def home():
return render_template_string(my_home_page, number=db['number'])
@app.route('/decrement')
def decrement():
db['number'] -= 1
return render_template_string(my_home_page, number=db['number'])
@app.route('/increment')
def increment():
db['number'] += 1
return render_template_string(my_home_page, number=db['number'])
app.run(host='0.0.0.0', port=81)
CSS styling
Since this is not a CSS course, our focus is python code. But thankfully, clever programmer
prepared the CSS
styling for us.
All we have to do is add this magical line in our html.
<link rel='stylesheet' href='./static/counter_styles.css' />
my_home_page = '''
<link rel='stylesheet' href='./static/counter_styles.css' />
<span></span>
<div>
<form action='/decrement'>
<button type='submit'>-</button>
</form>
<form action='/increment'>
<button type='submit'>+</button>
</form>
</div>
'''
As a result, the CSS styles are applied.
Best practices
As beginner developers, we need to keep the code clean and keep the rules that most companies follow.
In most cases, we need to separate our html codes because of performance and architectural issues.
In order to do that, let’s create a new folder called templates
and inside the folder tempaltes
, create a file index.html
And copy and paste the html
codes to index.html
file, and we are going to import index.html
from our main.py
Now we have to import index.html
with the function called render_template
. This function comes from the flask, so we need to change our code like this:
from flask import Flask, render_template
And to use index.html
file, change our route function
@app.route('/')
def home():
# This part has changed! 🌟
return render_template('index.html', number=db['number'])
render_template_string
has changed to render_template
and my_home_page
has changed to index.html
Finally, our code should look like the one below. Check if anything changed from the previous result.
import counter_app
from flask import Flask, render_template # 👈 this part changed!
from replit import db
app = Flask(__name__)
# db = { 'number': 0 }
if 'number' not in db:
db['number'] = 0
# my_home_page = ''' We don't need this anymore '''
@app.route('/')
def home():
return render_template('index.html', number=db['number'])
@app.route('/decrement')
def decrement():
db['number'] -= 1
return render_template('index.html', number=db['number'])
@app.route('/increment')
def increment():
db['number'] += 1
return render_template('index.html', number=db['number'])
app.run(host='0.0.0.0', port=81)
Done! If you want to change styling, you can click the three dots from the bar where we created our folder, and choose show hidden file
There is static
folder and solutions too. Feel free to check solutions and change the styling by yourself!
Comments