Directory layout

Probably other layouts can work an might be even better, for better separation, but this is a working version.

.
├── app.py
├── echo
│   └── templates
│       └── echo
│           └── main.html
├── echo.py
├── templates
│   └── main.html
├── test_app.py
└── test_echo.py

The blueprint

examples/flask/blueprint/echo.py

from flask import Blueprint, render_template, request

echo_app = Blueprint('echo', __name__, template_folder='echo/templates',)

@echo_app.route('/')
def main():
    return render_template(f'echo/main.html')

@echo_app.route('/run')
def echo():
    text = request.args.get('text') or 'Nope'
    return render_template(f'echo/main.html', text = text)

The template of the blueprint

examples/flask/blueprint/echo/templates/echo/main.html

<h2>Echo main</h2>
<form action="{{url_for('.echo')}}" method="GET">
<input name="text">
<input type="submit" value="Echo">
</form>

{% if text %}
You typed in {{text}}
{% endif %}

The test of the blueprint

We create an application in it, hang the bluprint in the root of the application and test it there.

examples/flask/blueprint/test_echo.py

from flask import Flask
from echo import echo_app

def test_app():
    app = Flask(__name__)
    app.register_blueprint(echo_app, url_prefix='/')

    web = app.test_client()

    rv = web.get('/')
    assert rv.status == '200 OK'
    assert '<h2>Echo main</h2>' in rv.data.decode('utf-8')
    assert 'You typed' not in rv.data.decode('utf-8')

    rv = web.get('/run?text=Hello World')
    assert rv.status == '200 OK'
    assert '<h2>Echo main</h2>' in rv.data.decode('utf-8')
    assert 'You typed in Hello World' in rv.data.decode('utf-8')
    
    #print(rv.data)

The application

It has a single route of its own and uses the blueprint. It could add more bluprints, if there were more.

examples/flask/blueprint/app.py

from flask import Flask
from flask.templating import render_template
from echo import echo_app

app = Flask(__name__)
app.register_blueprint(echo_app, url_prefix='/echo')


@app.route('/')
def main():
    return render_template('main.html')

The template of the main application

examples/flask/blueprint/templates/main.html

<h2>Main</h2>

<a href="{{ url_for('echo.main') }}">Echo</a>

Test the application

In this test we also tested the routes of the blueprint. This is probably not necessary as we already tested them earlier, but these tests can ensure that the routes work properly even when they are attached to a path different from the root.

examples/flask/blueprint/test_app.py

import app

def test_app():
    web = app.app.test_client()

    rv = web.get('/')
    assert rv.status == '200 OK'
    assert '<h2>Main</h2>' in rv.data.decode('utf-8')


    rv = web.get('/echo/')
    assert rv.status == '200 OK'
    assert '<h2>Echo main</h2>' in rv.data.decode('utf-8')
    assert 'You typed' not in rv.data.decode('utf-8')

    rv = web.get('/echo/run?text=Hello World')
    assert rv.status == '200 OK'
    assert '<h2>Echo main</h2>' in rv.data.decode('utf-8')
    assert 'You typed in Hello World' in rv.data.decode('utf-8')
    
    #print(rv.data)