Perfect πŸš€ Let’s expand your Country Data Dashboard into a modular, production-style repo with SQLite + SQLAlchemy integration.


πŸ“‚ Final Repo Structure

string_project/
β”œβ”€β”€ app.py                # Flask entrypoint
β”œβ”€β”€ config.py             # Config (DB path, API URL)
β”œβ”€β”€ requirements.txt
β”œβ”€β”€ data_fetch.py         # Fetch data from API
β”œβ”€β”€ data_clean.py         # String cleaning & transformations
β”œβ”€β”€ models.py             # SQLAlchemy ORM models
β”œβ”€β”€ populate_db.py        # Populate DB with cleaned data
β”œβ”€β”€ templates/
β”‚   β”œβ”€β”€ home.html
β”‚   └── countries.html
β”œβ”€β”€ static/
β”‚   └── style.css
└── dashboard.db          # SQLite DB (auto-created)

πŸ”Ή requirements.txt

flask
pandas
requests
sqlalchemy
plotly

πŸ”Ή config.py

API_URL = "https://restcountries.com/v3.1/all"
DB_URL = "sqlite:///dashboard.db"

πŸ”Ή models.py

from sqlalchemy import Column, Integer, String, Float
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine
from config import DB_URL

Base = declarative_base()
engine = create_engine(DB_URL, echo=False)
SessionLocal = sessionmaker(bind=engine)

class Country(Base):
    __tablename__ = "countries"
    id = Column(Integer, primary_key=True, index=True)
    name = Column(String, unique=True, nullable=False)
    region = Column(String)
    capital = Column(String)
    population = Column(Integer)
    area = Column(Float)
    name_length = Column(Integer)

def init_db():
    Base.metadata.create_all(bind=engine)

πŸ”Ή data_fetch.py

import requests
import pandas as pd
from config import API_URL

def fetch_data():
    res = requests.get(API_URL)
    countries = res.json()
    df = pd.json_normalize(countries)
    return df

πŸ”Ή data_clean.py

import pandas as pd

def clean_data(df):
    df['name.common'] = df['name.common'].str.strip().str.title()
    df['region'] = df['region'].fillna("Unknown").str.upper()
    df['capital'] = df['capital'].astype(str).str.replace(r"[\[\]']", "", regex=True)
    df['name_length'] = df['name.common'].str.len()

    return df[['name.common', 'region', 'capital', 'population', 'area', 'name_length']]

πŸ”Ή populate_db.py

from data_fetch import fetch_data
from data_clean import clean_data
from models import Country, init_db, SessionLocal

def populate():
    init_db()
    df = clean_data(fetch_data())
    session = SessionLocal()

    for _, row in df.iterrows():
        country = Country(
            name=row['name.common'],
            region=row['region'],
            capital=row['capital'],
            population=row['population'],
            area=row['area'],
            name_length=row['name_length']
        )
        session.merge(country)  # merge avoids duplicate insert
    session.commit()
    session.close()

if __name__ == "__main__":
    populate()
    print("Database populated successfully βœ…")

πŸ”Ή app.py

from flask import Flask, render_template, request
from models import SessionLocal, Country

app = Flask(__name__)

@app.route("/")
def home():
    session = SessionLocal()
    total_countries = session.query(Country).count()
    total_population = session.query(Country).with_entities(Country.population).all()
    total_population = sum([p[0] for p in total_population if p[0]])
    largest_country = session.query(Country).order_by(Country.area.desc()).first()
    session.close()

    summary = {
        "total_countries": total_countries,
        "total_population": total_population,
        "largest_country": largest_country.name if largest_country else None
    }
    return render_template("home.html", summary=summary)

@app.route("/countries")
def countries():
    q = request.args.get("q", "")
    session = SessionLocal()
    query = session.query(Country)
    if q:
        query = query.filter(Country.name.ilike(f"%{q}%"))
    countries = query.all()
    session.close()
    return render_template("countries.html", countries=countries, query=q)

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

πŸ”Ή templates/home.html

<!DOCTYPE html>
<html>
<head>
  <title>Country Dashboard</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css">
</head>
<body class="container mt-4">
  <h1>🌍 Country Dashboard</h1>
  <p>Total Countries: {{ summary.total_countries }}</p>
  <p>Total Population: {{ summary.total_population }}</p>
  <p>Largest Country (Area): {{ summary.largest_country }}</p>
  <a href="/countries" class="btn btn-primary mt-3">Browse Countries</a>
</body>
</html>

πŸ”Ή templates/countries.html

<!DOCTYPE html>
<html>
<head>
  <title>Countries</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css">
</head>
<body class="container mt-4">
  <h2>Countries</h2>
  <form method="get">
    <input type="text" name="q" value="{{ query }}" placeholder="Search by name">
    <button type="submit" class="btn btn-primary btn-sm">Search</button>
  </form>
  <table class="table table-striped mt-3">
    <thead>
      <tr>
        <th>Name</th>
        <th>Region</th>
        <th>Capital</th>
        <th>Population</th>
        <th>Area</th>
        <th>Name Length</th>
      </tr>
    </thead>
    <tbody>
      {% for c in countries %}
      <tr>
        <td>{{ c.name }}</td>
        <td>{{ c.region }}</td>
        <td>{{ c.capital }}</td>
        <td>{{ "{:,}".format(c.population) if c.population else "" }}</td>
        <td>{{ c.area }}</td>
        <td>{{ c.name_length }}</td>
      </tr>
      {% endfor %}
    </tbody>
  </table>
</body>
</html>

πŸ”Ή How to Run

# 1. Clone / create folder
cd string_project

# 2. Create env & install deps
python -m venv venv
venv\Scripts\activate      # Windows
source venv/bin/activate   # Linux/Mac
pip install -r requirements.txt

# 3. Populate DB
python populate_db.py

# 4. Run Flask app
python app.py

Then open β†’ http://127.0.0.1:5000/


⚑ This repo is now:
βœ” Modular (fetch β†’ clean β†’ DB β†’ app).
βœ” SQLite via SQLAlchemy ORM.
βœ” Easily extendable (charts, filters, etc.).


Do you also want me to add interactive charts (Plotly) into the dashboard (e.g., population by continent) to make it more data-science / analytics style?

Pages: 1 2 3 4 5 6


Discover more from HintsToday

Subscribe to get the latest posts sent to your email.

Posted in

Discover more from HintsToday

Subscribe now to keep reading and get access to the full archive.

Continue reading