Search code examples
pythonjsontemplatesflaskapi-design

How do I serve both HTML and JSON content with Flask?


I'd like to setup a Flask app that has both a GUI and API component. So here's a simple example that retrieves a list of groups:

def get_groups():
    groups = db.session.query(SgmGroup.group_name).order_by(SgmGroup.group_name).all()
    return [group.group_name for group in groups]

@app.route('/list')
def group_list():
    groups_list = get_groups()
    return render_template('groups.html', groups=groups_list)

So far so good - this will give the user an HTML list of users, maybe in a table or some other nice GUI format.

But I'd also like to serve JSON content for API requests:

@app.route('/api/list')
def api_group_list():
    groups_list = get_groups()
    return jsonify({'groups': group_list})

This works - but is this a good idea? I have two questions:

1) Is this the appropriate way to use Flask when I have two different types of content? Make an /endpoint URL for web browsers (HTML), and an identical /api/endpoint URL to handle API requests (JSON)?

2) Or should I combine these two endpoints into a single function? That would seem to be neater, but how can you determine which endpoint the user accessed? That is, can the pseudocode below be done?

@app.route('/list')
@app.route('/api/list')
def group_list():
    groups_list = get_groups()

    if <user arrived here via the /list endpoint>:
        return render_template('groups.html', groups=groups_list)

    elif <user arrived here via the /api/list endpoint>:
        return jsonify({'groups': group_list})

Solution

  • To answer your second question:

    from flask import request
    
    @app.route('/')
    @app.route('/json')
    def index():
        if request.path == '/json':
            return {}
        return render_template('index.html')
    

    The doc reference is here.