Search code examples
pythonflaskflask-restplus

Storing and accessing dictionary data in Flask


I have a Flask RESTful service where I want to read a JSON file as a dictionary during initialization and later read data from it during certain GET requests. The dictionary would have to be updated once every day.

This is what I tried using Flask global variable -

app.py

import json

from flask import Flask
from flask import g

from api import api


def create_app(config_file='settings.py'):
    app = Flask(__name__)
    app.config.from_pyfile(config_file)
    api.init_app(app)
    with app.app_context():
        f = open('data.json')
        g.data = json.loads(f.read())
    return app


app = create_app()

feat_api.py

from flask_restplus import Resource, reqparse, fields, Model
from flask import g

from extensions.restplus import api

ns = api.namespace('feat', description='Feature')


parser = reqparse.RequestParser()
parser.add_argument('id', type=str, required=True)


@ns.route('/')
class Feature(Resource):
    @api.expect(parser)
    def get(self):
        args = parser.parse_args()
        return {"data": g.data[args['id']]}

I get the following error - AttributeError: '_AppCtxGlobals' object has no attribute 'data' when making the API call.


Solution

  • The simplest way would be to save the dictionary as a pickle file and load it each time you need it:

    import pickle
    
    a = {'hello': 'world'}
    
    with open('filename.pickle', 'wb') as handle:
        pickle.dump(a, handle)
    
    with open('filename.pickle', 'rb') as handle:
        b = pickle.load(handle)
    

    Update:

    Alternatively you could save it like you are doing when creating the application and saving the variable each time it updates:

    def create_app(config_file='settings.py'):
    app = Flask(__name__)
    app.config.from_pyfile(config_file)
    api.init_app(app)
    with app.app_context():
        f = open('data.json')
        app.config['data'] = json.loads(f.read())
    return app
    

    feat_api.py

    import current_app
    @ns.route('/')
    class Feature(Resource):
        @api.expect(parser)
        def get(self):
            args = parser.parse_args()
            return {"data": current_app.config['data']}