Simple Flask app to compare the weather of 2 cities

Posted by Bob on Thu 20 April 2017 in Flask • 3 min read

Some nice things coming out of our 100DaysOfCode Challenge. You seemed to like this one so I decided to do an article on it.

In this post I show you how to build a simple Flask app to compare the weather of 2 cities using the OpenWeatherMap API. Maybe this aids you in solving this week's challenge.

Our simple Flask app

Step by step

The full code is here. We deployed the app here.

  • First install dependencies we put in requirements.txt.

    $ python -m venv venv && source venv/bin/activate
    $ pip install -r requirements.txt
    
  • Get an API key from OpenWeatherMap API and store it in your environment

    $ vi .bashrc
    ...
    export WEATHER_API=xyz
    
  • Project code:

    • CSS goes into the static directory, our template into templates. It contains a POST form to submit 2 cities and a table for the results of the query. The nice and simple design are thanks to PureCSS.

    • The weather.py gets the API_KEY from the OS env, sets up some other constants and defines two helpers:

      1. get_local_time() -> tries to be as specific regarding timezone as possible, looking for both city and country. I had a good play with the pytz package here.

      2. query_api() queries the OpenWeatherMap API via requests

      3. With these helpers the main app becomes pretty lean (just 32 LOC). I only use the root (/) path for both view and POST. If POST, I get the 2 cities from the form with request.form.get, I query the API for both cities appending the results to data. If data does not have 2 items we set the error variable. All the data gets passed to the weather html template with this:

        return render_template("weather.html",
                            data=data,
                            error=error,
                            time=get_local_time)
        

        Note that we can pass in a function as well: get_local_time() which we use in the template:

        <td>{{ time(d['sys']['sunrise'], d['sys']['country'], d['name']) }}</td>
        

Deploy to Heroku

  • I then deployed the app and luckily took some notes. Prerequisite is installing Heroku CLI.
    (with your virtualenv enabled)
    
    $ pip install gunicorn
    
    $ pip freeze > requirements.txt
    $ echo "web: gunicorn <APP_FILE_NAME>:app" > Procfile
    $ echo "python-3.5.2" > runtime.txt
    $ git add . && git commit -m 'prep files heroku'
    
    $ heroku login
    Enter your Heroku credentials.
    Email: <your-email>
    Password (typing will be hidden):
    Logged in as <your-email>
    
    # you can name your app or let Heroku give you a random name
    $ heroku create weathercompare
    Creating  weathercompare... done
    https://weathercompare.herokuapp.com/ | https://git.heroku.com/weathercompare.git
    
    $ heroku git:remote -a weathercompare
    set git remote heroku to https://git.heroku.com/weathercompare.git
    
    $ git remote -v
    heroku    https://git.heroku.com/weathercompare.git (fetch)
    heroku    https://git.heroku.com/weathercompare.git (push)
    
    # if ENV variables
    $ heroku config:set WEATHER_API=XYZ
    Setting WEATHER_API and restarting  weathercompare... done, v3
    WEATHER_API: XYZ
    
    $ git push heroku master
    Counting objects: 15, done.
    Delta compression using up to 4 threads.
    Compressing objects: 100% (9/9), done.
    Writing objects: 100% (15/15), 2.55 KiB | 0 bytes/s, done.
    Total 15 (delta 1), reused 0 (delta 0)
    remote: Compressing source files... done.
    remote: Building source:
    remote:
    remote: -----> Python app detected
    remote: -----> Installing python-3.5.2
    remote: -----> Installing pip
    remote: -----> Installing requirements with pip
    ...
    ...
    ...
    remote: -----> Launching...
    remote:        Released v4
    remote:        https://weathercompare.herokuapp.com/ deployed to Heroku
    remote:
    remote: Verifying deploy... done.
    To https://git.heroku.com/weathercompare.git
    * [new branch]      master -> master
    
    $ heroku ps:scale web=1
    Scaling dynos... done, now running web at 1:Free
    
    # made a change? e.g. I added the CSS later, no problem, just deploy again
    
    $ git push heroku
    ...
    remote: Building source:
    remote:
    remote: -----> Python app detected
    remote: -----> Installing requirements with pip
    remote:
    remote: -----> Discovering process types
    remote:        Procfile declares types -> web
    remote:
    remote: -----> Compressing...
    remote:        Done: 57.5M
    remote: -----> Launching...
    remote:        Released v7
    remote:        https://weathercompare.herokuapp.com/ deployed to Heroku
    remote:
    remote: Verifying deploy... done.
    To https://git.heroku.com/weathercompare.git
    c9771bb..77abb53  master -> master
    

I hope this inspired you to build your own mini Flask app using an API and putting it on Heroku. I hope I have convinced you this is pretty awesome stuff, not too hard to grasp, yet powerful if you further exploit its features.

Leave a comment below if you want to share what you've built and/or join our Flask Code Challenge of this week.


Keep Calm and Code in Python!

-- Bob

>>> next(PyBites)

Get our 'Become a Better Python Developer' cheat sheet sent straight to your inbox by signing up for our Newsletter: