Creating a web application to fetch, filter, and export data is a common requirement for many projects. This blog post will guide you through building a Flask application that calls an open-source API, filters the necessary records, and exports the data in CSV format. We will use the OpenWeatherMap API for this example.

Prerequisites

Before we dive in, ensure you have Python and pip installed. You will also need to install Flask and requests:

pip install flask requests

Additionally, sign up for a free API key from OpenWeatherMap to access their weather data.

https://home.openweathermap.org/users/sign_up

Step 1: Set Up the Flask Application

Create a new file named app.py and start by importing the necessary modules:

from flask import Flask, request, send_file
import requests
import csv
import io

app = Flask(__name__)

Step 2: Configure the OpenWeatherMap API

Replace your_openweathermap_api_key with your actual API key:

API_KEY = 'your_openweathermap_api_key'
BASE_URL = 'http://api.openweathermap.org/data/2.5/weather'

Step 3: Define Routes

We will create two routes: a home route and a route to fetch and export weather data.

@app.route('/')
def home():
    return 'Weather Data API'

@app.route('/fetch_weather', methods=['GET'])
def fetch_weather():
    city = request.args.get('city', 'London')
    url = f"{BASE_URL}?q={city}&appid={API_KEY}"
    response = requests.get(url)
    data = response.json()
    
    if response.status_code != 200:
        return f"Error fetching data from OpenWeatherMap API: {data.get('message', 'Unknown error')}"

Step 4: Filter the Data

Extract and filter the relevant data from the API response:

filtered_data = {
    'City': data['name'],
    'Temperature': data['main']['temp'],
    'Weather': data['weather'][0]['description'],
    'Humidity': data['main']['humidity']
}

Step 5: Export Data to CSV

Write the filtered data to a CSV file in memory and return it as a downloadable file:

output = io.StringIO()
writer = csv.writer(output)
writer.writerow(filtered_data.keys())
writer.writerow(filtered_data.values())
output.seek(0)

return send_file(output, mimetype='text/csv', as_attachment=True, attachment_filename=f'{city}_weather.csv')

Step 6: Run the Application

The final step is to run the Flask application:

if __name__ == '__main__':
    app.run(debug=True)

Complete Code

Here is the complete code for your Flask application:

from flask import Flask, request, send_file
import requests
import csv
import io

app = Flask(__name__)

API_KEY = 'your_openweathermap_api_key'
BASE_URL = 'http://api.openweathermap.org/data/2.5/weather'

@app.route('/')
def home():
    return 'Weather Data API'

@app.route('/fetch_weather', methods=['GET'])
def fetch_weather():
    city = request.args.get('city', 'London')
    url = f"{BASE_URL}?q={city}&appid={API_KEY}"
    response = requests.get(url)
    data = response.json()
    
    if response.status_code != 200:
        return f"Error fetching data from OpenWeatherMap API: {data.get('message', 'Unknown error')}"

    filtered_data = {
        'City': data['name'],
        'Temperature': data['main']['temp'],
        'Weather': data['weather'][0]['description'],
        'Humidity': data['main']['humidity']
    }
    
    output = io.StringIO()
    writer = csv.writer(output)
    writer.writerow(filtered_data.keys())
    writer.writerow(filtered_data.values())
    output.seek(0)
    
    return send_file(output, mimetype='text/csv', as_attachment=True, attachment_filename=f'{city}_weather.csv')

if __name__ == '__main__':
    app.run(debug=True)

Conclusion

In this tutorial, we built a Flask application that calls the OpenWeatherMap API to fetch weather data for a specified city, filters the relevant information, and exports it as a CSV file. This simple yet powerful example demonstrates how Flask can be used to create web applications that interact with external APIs and handle data efficiently.

Feel free to extend this application by adding more routes, handling different APIs, or enhancing error handling as needed. Happy coding!

Categorized in: