Source code for django_owm.models.abstract

"""Models for OpenWeatherMap API data storage in django_owm."""

from django.db import models
from django.utils.translation import gettext_lazy as _

from ..app_settings import OWM_BASE_MODEL
from ..app_settings import OWM_MODEL_MAPPINGS
from ..app_settings import OWM_USE_UUID
from ..validators import validate_latitude
from ..validators import validate_longitude
from .base import AbstractBaseWeatherData


if OWM_USE_UUID:
    import uuid

if callable(OWM_BASE_MODEL):
    OWM_BASE_MODEL = OWM_BASE_MODEL()


[docs] class AbstractWeatherLocation(OWM_BASE_MODEL): """Abstract model for storing weather location data.""" if OWM_USE_UUID: uuid = models.UUIDField( primary_key=True, editable=False, unique=True, default=uuid.uuid4, ) name = models.CharField( _("Location Name"), max_length=255, blank=True, null=True, ) latitude = models.DecimalField( _("Latitude"), max_digits=4, decimal_places=2, validators=[validate_latitude], help_text=_("Latitude of the location, decimal (−90; 90)"), ) longitude = models.DecimalField( _("Longitude"), max_digits=5, decimal_places=2, validators=[validate_longitude], help_text=_("Longitude of the location, decimal (−180; 180)"), ) timezone = models.CharField( _("Timezone"), max_length=255, blank=True, null=True, help_text=_("Timezone name for the requested location"), ) timezone_offset = models.IntegerField( _("Timezone Offset"), blank=True, null=True, help_text=_("Offset from UTC in seconds"), ) class Meta(OWM_BASE_MODEL.Meta): """Meta options for the AbstractWeatherLocation model.""" abstract = True def __str__(self): # noqa: D105 return str(self.name) if self.name else f"{self.latitude}, {self.longitude}"
[docs] class AbstractCurrentWeather(AbstractBaseWeatherData): """Abstract model for storing current weather data.""" if OWM_USE_UUID: uuid = models.UUIDField( primary_key=True, editable=False, unique=True, default=uuid.uuid4, ) sunrise = models.DateTimeField(blank=True, null=True) sunset = models.DateTimeField(blank=True, null=True) temp = models.DecimalField( _("Temperature"), max_digits=5, decimal_places=2, blank=True, null=True, ) feels_like = models.DecimalField( _("Feels Like Temperature"), max_digits=5, decimal_places=2, blank=True, null=True, ) visibility = models.IntegerField(blank=True, null=True) rain_1h = models.DecimalField( _("Rain (1h)"), max_digits=5, decimal_places=2, blank=True, null=True, help_text=_("Precipitation in mm/h"), ) snow_1h = models.DecimalField( _("Snow (1h)"), max_digits=5, decimal_places=2, blank=True, null=True, help_text=_("Snowfall in mm/h"), ) class Meta: """Meta options for the AbstractCurrentWeather model.""" abstract = True def __str__(self): # noqa: D105 return f"{self.location.name} - {self.timestamp}"
[docs] class AbstractMinutelyWeather(OWM_BASE_MODEL): """Abstract model for storing minutely weather data.""" if OWM_USE_UUID: uuid = models.UUIDField( primary_key=True, editable=False, unique=True, default=uuid.uuid4, ) location = models.ForeignKey( OWM_MODEL_MAPPINGS["WeatherLocation"], on_delete=models.CASCADE, related_name="minutely_weather", help_text=_("Location for this weather data by minute"), ) timestamp = models.DateTimeField( _("Timestamp"), help_text=_("Unix timestamp converted to DateTime"), ) precipitation = models.DecimalField( _("Precipitation"), max_digits=5, decimal_places=2, ) class Meta(OWM_BASE_MODEL.Meta): """Meta options for the AbstractMinutelyWeather model.""" abstract = True def __str__(self): # noqa: D105 return f"{self.location.name} - {self.timestamp}"
[docs] class AbstractHourlyWeather(AbstractBaseWeatherData): """Abstract model for storing hourly weather data.""" if OWM_USE_UUID: uuid = models.UUIDField( primary_key=True, editable=False, unique=True, default=uuid.uuid4, ) temp = models.DecimalField( _("Temperature"), max_digits=5, decimal_places=2, blank=True, null=True, ) feels_like = models.DecimalField( _("Feels Like Temperature"), max_digits=5, decimal_places=2, blank=True, null=True, ) visibility = models.IntegerField(blank=True, null=True) pop = models.DecimalField( _("Probability of Precipitation"), max_digits=5, decimal_places=2, blank=True, null=True, ) rain_1h = models.DecimalField( _("Rain (1h)"), max_digits=5, decimal_places=2, blank=True, null=True, ) snow_1h = models.DecimalField( _("Snow (1h)"), max_digits=5, decimal_places=2, blank=True, null=True, ) class Meta: """Meta options for the AbstractHourlyWeather model.""" abstract = True def __str__(self): # noqa: D105 return f"{self.location.name} - {self.timestamp}"
[docs] class AbstractDailyWeather(AbstractBaseWeatherData): """Abstract model for storing daily weather data.""" if OWM_USE_UUID: uuid = models.UUIDField( primary_key=True, editable=False, unique=True, default=uuid.uuid4, ) sunrise = models.DateTimeField(blank=True, null=True) sunset = models.DateTimeField(blank=True, null=True) moonrise = models.DateTimeField(blank=True, null=True) moonset = models.DateTimeField(blank=True, null=True) moon_phase = models.DecimalField( _("Moon Phase"), max_digits=5, decimal_places=2, blank=True, null=True, ) summary = models.TextField(blank=True, null=True) temp_min = models.DecimalField( _("Temperature Min"), max_digits=5, decimal_places=2, blank=True, null=True, ) temp_max = models.DecimalField( _("Temperature Max"), max_digits=5, decimal_places=2, blank=True, null=True, ) temp_morn = models.DecimalField( _("Morning Temperature"), max_digits=5, decimal_places=2, blank=True, null=True, ) temp_day = models.DecimalField( _("Day Temperature"), max_digits=5, decimal_places=2, blank=True, null=True, ) temp_eve = models.DecimalField( _("Evening Temperature"), max_digits=5, decimal_places=2, blank=True, null=True, ) temp_night = models.DecimalField( _("Night Temperature"), max_digits=5, decimal_places=2, blank=True, null=True, ) feels_like_morn = models.DecimalField( _("Feels Like - Morning"), max_digits=5, decimal_places=2, blank=True, null=True, ) feels_like_day = models.DecimalField( _("Feels Like - Day"), max_digits=5, decimal_places=2, blank=True, null=True, ) feels_like_eve = models.DecimalField( _("Feels Like - Evening"), max_digits=5, decimal_places=2, blank=True, null=True, ) feels_like_night = models.DecimalField( _("Feels Like - Night"), max_digits=5, decimal_places=2, blank=True, null=True, ) pop = models.DecimalField( _("Probability of Precipitation"), max_digits=5, decimal_places=2, blank=True, null=True, ) rain = models.DecimalField( _("Rain"), max_digits=5, decimal_places=2, blank=True, null=True, ) snow = models.DecimalField( _("Snow"), max_digits=5, decimal_places=2, blank=True, null=True, ) class Meta: """Meta options for the AbstractDailyWeather model.""" abstract = True def __str__(self): # noqa: D105 return f"{self.location.name} - {self.timestamp}" @property def moon_phase_description(self): # pylint: disable=R0911 """Return a description of the moon phase.""" match self.moon_phase: case 0 | 1: return _("New Moon") case 0.25: return _("First Quarter") case 0.5: return _("Full Moon") case 0.75: return _("Last Quarter") case phase if 0 < phase < 0.25: return _("Waxing Crescent") case phase if 0.25 < phase < 0.5: return _("Waxing Gibbous") case phase if 0.5 < phase < 0.75: return _("Waning Gibbous") case phase if 0.75 < phase < 1: return _("Waning Crescent") case _: return _("Unknown")
[docs] class AbstractWeatherAlert(OWM_BASE_MODEL): """Abstract model for storing weather alerts.""" if OWM_USE_UUID: uuid = models.UUIDField( primary_key=True, editable=False, unique=True, default=uuid.uuid4, ) location = models.ForeignKey( OWM_MODEL_MAPPINGS["WeatherLocation"], on_delete=models.CASCADE, related_name="weather_alerts", ) sender_name = models.CharField(max_length=255) event = models.CharField(max_length=255) start = models.DateTimeField(_("Start Time"), help_text=_("Start time of the alert")) end = models.DateTimeField(_("End Time"), help_text=_("End time of the alert")) description = models.TextField() tags = models.JSONField(default=list, blank=True, null=True) class Meta(OWM_BASE_MODEL.Meta): """Meta options for the AbstractWeatherAlert model.""" abstract = True def __str__(self): # noqa: D105 return f"{self.location.name} - ({self.start} - {self.end})"
[docs] class AbstractWeatherErrorLog(OWM_BASE_MODEL): """Abstract model for storing weather API error logs.""" if OWM_USE_UUID: uuid = models.UUIDField( primary_key=True, editable=False, unique=True, default=uuid.uuid4, ) timestamp = models.DateTimeField(auto_now_add=True) location = models.ForeignKey( OWM_MODEL_MAPPINGS["WeatherLocation"], on_delete=models.CASCADE, related_name="error_logs", ) api_name = models.CharField(max_length=255) error_message = models.TextField() response_data = models.TextField(blank=True, null=True) class Meta(OWM_BASE_MODEL.Meta): """Meta options for the AbstractWeatherErrorLog model.""" abstract = True def __str__(self): # noqa: D105 return f"{self.api_name} - {self.timestamp}"
[docs] class AbstractAPICallLog(OWM_BASE_MODEL): """Abstract model for storing API call logs.""" if OWM_USE_UUID: uuid = models.UUIDField( primary_key=True, editable=False, unique=True, default=uuid.uuid4, ) timestamp = models.DateTimeField(auto_now_add=True) api_name = models.CharField(max_length=255)
[docs] class UnitsType(models.TextChoices): """Choices for the units type field.""" STANDARD = "standard", _("Standard") METRIC = "metric", _("Metric") IMPERIAL = "imperial", _("Imperial")
units = models.CharField( _("Units"), max_length=10, choices=UnitsType.choices, default=UnitsType.STANDARD, ) class Meta(OWM_BASE_MODEL.Meta): """Meta options for the AbstractAPICallLog model.""" abstract = True def __str__(self): # noqa: D105 return f"{self.api_name} - {self.timestamp}"