Skip to content

Commit

Permalink
Merge pull request #114 from luftdaten-at/113-catch-api-error-in-stat…
Browse files Browse the repository at this point in the history
…ions-and-cities

113 catch api error in stations and cities
  • Loading branch information
silvioheinze authored Jan 13, 2025
2 parents 289b8df + ba5304e commit 35a9618
Show file tree
Hide file tree
Showing 5 changed files with 203 additions and 47 deletions.
16 changes: 11 additions & 5 deletions app/cities/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,18 +50,24 @@ def CitiesDetailView(request, pk):

def CitiesListView(request):
api_url = f"{settings.API_URL}/city/all"

error_message = None
cities = []

try:
# Perform the GET request
response = requests.get(api_url)
response.raise_for_status() # Raise an error for unsuccessful requests
data = response.json() # Parse JSON response

# Extract and sort the list of cities alphabetically by name
cities = data.get("cities", [])
cities = sorted(cities, key=lambda city: city.get("name", "").lower()) # Sort case-insensitively

except requests.exceptions.HTTPError as err:
raise Http404(f"Cities not found.")
# Instead of raising a 404, store an error message to be shown in the template.
error_message = "There was an error fetching the city data: 404."
except requests.exceptions.RequestException as err:
# Catch any other request exceptions that might occur.
error_message = "There was an error fetching the city data."

return render(request, "cities/list.html", {"cities": cities})
return render(request, "cities/list.html", {"cities": cities, "error": error_message})
89 changes: 64 additions & 25 deletions app/stations/views.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import requests
from datetime import datetime, timezone, timedelta
from datetime import datetime, timedelta
from collections import defaultdict
from django.shortcuts import render, get_object_or_404
from django.shortcuts import render
from django.http import Http404
from django.conf import settings
from main.enums import Dimension, SensorModel, OutputFormat, Precision, Order
from main.enums import OutputFormat, Precision, Order
from requests.exceptions import HTTPError, RequestException
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger

def StationDetailView(request, pk):
# Beispiel API-URL, die von der Station-ID abhängt
Expand Down Expand Up @@ -61,33 +63,70 @@ def StationDetailView(request, pk):

def StationListView(request):
"""
max_station: List[Tuple[device,time_measured,dimension,value]]
min_stations: List[Tuple[device,time_measured,dimension,value]]
Fetches two lists: stations with the highest PM2.5 values and
stations with the lowest PM2.5 values.
"""

url_min = f"{settings.API_URL}/station/topn?n=10&dimension=3&order={Order.MIN.value}&output_format={OutputFormat.CSV.value}"
url_max = f"{settings.API_URL}/station/topn?n=10&dimension=3&order={Order.MAX.value}&output_format={OutputFormat.CSV.value}"

resp_min = requests.get(url_min)
resp_max = requests.get(url_max)

# TODO: try catch
resp_min.raise_for_status()
resp_max.raise_for_status()
error_message = None
try:
resp_min = requests.get(url_min)
resp_max = requests.get(url_max)

min_stations = [
line.split(",")
for i, line in enumerate(resp_min.text.splitlines())
if i
]
# Raise HTTPError for bad responses
resp_min.raise_for_status()
resp_max.raise_for_status()

max_stations = [
line.split(",")
for i, line in enumerate(resp_max.text.splitlines())
# Skip header line (i == 0)
min_stations = [
line.split(",")
for i, line in enumerate(resp_min.text.splitlines())
if i
]
]
max_stations = [
line.split(",")
for i, line in enumerate(resp_max.text.splitlines())
if i
]

except (HTTPError, RequestException) as e:
# Instead of raising a 404, store an error message in the context.
error_message = "There was an error fetching station data: 404."
# Optionally, you can log the error:
print(f"Error fetching station data: {e}")
min_stations = []
max_stations = []

# Paginate each list separately (example: 5 stations per page)
paginator_top = Paginator(max_stations, 5)
paginator_low = Paginator(min_stations, 5)

page_top = request.GET.get('page_top')
page_low = request.GET.get('page_low')

try:
top_stations_page = paginator_top.page(page_top)
except PageNotAnInteger:
top_stations_page = paginator_top.page(1)
except EmptyPage:
top_stations_page = paginator_top.page(paginator_top.num_pages)

try:
lowest_stations_page = paginator_low.page(page_low)
except PageNotAnInteger:
lowest_stations_page = paginator_low.page(1)
except EmptyPage:
lowest_stations_page = paginator_low.page(paginator_low.num_pages)

context = {
'top_stations': top_stations_page,
'lowest_stations': lowest_stations_page,
'paginator_top': paginator_top,
'paginator_low': paginator_low,
'page_top': top_stations_page,
'page_low': lowest_stations_page,
'error': error_message,
}

return render(request, 'stations/list.html', {
'top_stations': max_stations,
'lowest_stations': min_stations,
})
return render(request, 'stations/list.html', context)
29 changes: 22 additions & 7 deletions app/templates/cities/list.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,25 @@
{% endblock styles %}

{% block content %}
<h2>{% trans "Cities and municipalities" %}</h2>
<p>
{% for city in cities %}
<a href="/cities/{{ city.slug }}">{{ city.name }}</a> ({{ city.country.name }}){% if not forloop.last %}, {% endif %}
{% endfor %}
</p>
{% endblock content %}
<h2 class="mb-4 mt-5">{% trans "Cities and municipalities" %}</h2>

{% if error %}
<div class="alert alert-danger" role="alert">
{{ error }}
</div>
{% endif %}

{% if cities %}
<p>
{% for city in cities %}
<a href="/cities/{{ city.slug }}">{{ city.name }}</a> ({{ city.country.name }}){% if not forloop.last %}, {% endif %}
{% endfor %}
</p>
{% else %}
{% if not error %}
<div class="alert alert-info" role="alert">
{% trans "No cities available." %}
</div>
{% endif %}
{% endif %}
{% endblock content %}
114 changes: 105 additions & 9 deletions app/templates/stations/list.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,32 +33,128 @@
{% endblock styles %}

{% block content %}
<h2>{% trans "Stations overview" %}</h2>
<h2 class="mb-4 mt-5">{% trans "Stations overview" %}</h2>

<!-- Display error message if present -->
{% if error %}
<div class="alert alert-danger" role="alert">
{{ error }}
</div>
{% else %}
<div class="row">
<!-- Spalte 1: Stationen mit den höchsten Werten -->
<!-- Column 1: Top 10 with the highest values -->
<div class="col-md-6">
<h3 class="text-center">{% trans "Top 10 with the highest values for PM2.5" %}</h3>
<ul class="list-group">
{% for station in top_stations %}
<li class="list-group-item d-flex justify-content-between align-items-center">
<a href="/stations/{{ station.0 }}" class="station-link">Station {{ station.0 }}</a>
<span class="badge bg-danger rounded-pill">{{ station.3 }} µg/m³</span> <!-- Value -->
<a href="{% url 'station-detail' station.0 %}" class="station-link">
Station {{ station.0 }}
</a>
<span class="badge bg-danger rounded-pill">{{ station.3 }} µg/m³</span>
</li>
{% endfor %}
</ul>

{% if top_stations.has_other_pages %}
<nav aria-label="{% trans 'Top station pagination' %}">
<ul class="pagination justify-content-center mt-2">
{% if top_stations.has_previous %}
<li class="page-item">
<a class="page-link" href="?page_top={{ top_stations.previous_page_number }}" aria-label="{% trans 'Previous' %}">
<span aria-hidden="true">&laquo;</span>
</a>
</li>
{% else %}
<li class="page-item disabled">
<span class="page-link" aria-hidden="true">&laquo;</span>
</li>
{% endif %}

{% for num in paginator_top.page_range %}
{% if top_stations.number == num %}
<li class="page-item active" aria-current="page">
<span class="page-link">{{ num }}</span>
</li>
{% elif num > top_stations.number|add:'-3' and num < top_stations.number|add:'3' %}
<li class="page-item">
<a class="page-link" href="?page_top={{ num }}">{{ num }}</a>
</li>
{% endif %}
{% endfor %}

{% if top_stations.has_next %}
<li class="page-item">
<a class="page-link" href="?page_top={{ top_stations.next_page_number }}" aria-label="{% trans 'Next' %}">
<span aria-hidden="true">&raquo;</span>
</a>
</li>
{% else %}
<li class="page-item disabled">
<span class="page-link" aria-hidden="true">&raquo;</span>
</li>
{% endif %}
</ul>
</nav>
{% endif %}
</div>
<!-- Spalte 2: Stationen mit den niedrigsten Werten -->

<!-- Column 2: Top 10 with the lowest values -->
<div class="col-md-6">
<h3 class="text-center">{% trans "Top 10 with the lowest values for PM2.5" %}</h3>
<ul class="list-group">
{% for station in lowest_stations %}
<li class="list-group-item d-flex justify-content-between align-items-center">
<a href="/stations/{{ station.0 }}" class="station-link">Station {{ station.0 }}</a>
<span class="badge bg-success rounded-pill">{{ station.3 }} µg/m³</span> <!-- Value -->
<a href="{% url 'station-detail' station.0 %}" class="station-link">
Station {{ station.0 }}
</a>
<span class="badge bg-success rounded-pill">{{ station.3 }} µg/m³</span>
</li>
{% endfor %}
</ul>

{% if lowest_stations.has_other_pages %}
<nav aria-label="{% trans 'Lowest station pagination' %}">
<ul class="pagination justify-content-center mt-2">
{% if lowest_stations.has_previous %}
<li class="page-item">
<a class="page-link" href="?page_low={{ lowest_stations.previous_page_number }}" aria-label="{% trans 'Previous' %}">
<span aria-hidden="true">&laquo;</span>
</a>
</li>
{% else %}
<li class="page-item disabled">
<span class="page-link" aria-hidden="true">&laquo;</span>
</li>
{% endif %}

{% for num in paginator_low.page_range %}
{% if lowest_stations.number == num %}
<li class="page-item active" aria-current="page">
<span class="page-link">{{ num }}</span>
</li>
{% elif num > lowest_stations.number|add:'-3' and num < lowest_stations.number|add:'3' %}
<li class="page-item">
<a class="page-link" href="?page_low={{ num }}">{{ num }}</a>
</li>
{% endif %}
{% endfor %}

{% if lowest_stations.has_next %}
<li class="page-item">
<a class="page-link" href="?page_low={{ lowest_stations.next_page_number }}" aria-label="{% trans 'Next' %}">
<span aria-hidden="true">&raquo;</span>
</a>
</li>
{% else %}
<li class="page-item disabled">
<span class="page-link" aria-hidden="true">&raquo;</span>
</li>
{% endif %}
</ul>
</nav>
{% endif %}
</div>
</div>

{% endblock content %}
{% endif %}
{% endblock content %}
2 changes: 1 addition & 1 deletion app/templates/workshops/list.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
{% block title %}{% trans "Workshops" %}{% endblock title %}

{% block content %}
<h2 class="mb-4">{% trans "Workshops" %}</h2>
<h2 class="mb-4 mt-5">{% trans "Workshops" %}</h2>
<p>{% trans "We continuously host workshops where air quality is measured together. On this page, the results of all public workshops are listed." %}</p>

<!-- Laufende Workshops -->
Expand Down

0 comments on commit 35a9618

Please sign in to comment.