diff --git a/README.md b/README.md index 5f74f89..5d7ca5f 100644 --- a/README.md +++ b/README.md @@ -19,9 +19,18 @@ [pre-commit]: https://github.com/pre-commit/pre-commit [black]: https://github.com/psf/black +`django-owm` is a reusable Django app for fetching and storing weather data from the OpenWeatherMap One Call 3.0 API. It provides a simple interface for managing weather locations, fetching current, historical, and forecast weather data, and displaying this information in your Django project. + ## Features -- TODO +- Fetch and store weather data from OpenWeatherMap One Call API 3.0 +- Support for current, minutely, hourly, and daily weather data +- Weather alerts tracking +- Customizable models for storing weather data +- Management commands for easy interaction with the app +- Celery tasks for automated weather data fetching +- Built-in views and templates for displaying weather information +- Flexible configuration options ## Requirements @@ -29,15 +38,103 @@ ## Installation -You can install _django-owm_ via [pip] from [PyPI]: +1. Install the package using pip: + +```bash +pip install django-owm +``` + +2. Add `'django_owm'` to your `INSTALLED_APPS` setting: + +```python +INSTALLED_APPS = [ + ... + 'django_owm', +] +``` -```console -$ pip install django_owm +## Configuration + +Add the following settings to your Django project's `settings.py` file: + +```python +DJANGO_OWM = { + 'OWM_API_KEY': 'your_openweathermap_api_key', + 'OWM_API_RATE_LIMITS': { + 'one_call': { + 'calls_per_minute': 60, + 'calls_per_month': 1000000, + }, + }, + 'OWM_MODEL_MAPPINGS': { + 'WeatherLocation': 'your_app.WeatherLocation', + 'CurrentWeather': 'your_app.CurrentWeather', + 'MinutelyWeather': 'your_app.MinutelyWeather', + 'HourlyWeather': 'your_app.HourlyWeather', + 'DailyWeather': 'your_app.DailyWeather', + 'WeatherAlert': 'your_app.WeatherAlert', + 'WeatherErrorLog': 'your_app.WeatherErrorLog', + 'APICallLog': 'your_app.APICallLog', + }, + 'OWM_BASE_MODEL': models.Model, + 'OWM_USE_BUILTIN_ADMIN': True, + 'OWM_SHOW_MAP': False, + 'OWM_USE_UUID': False, +} ``` -## Usage +Replace `'your_openweathermap_api_key'` with your actual OpenWeatherMap API key, and adjust the model mappings to point to your custom model implementations if you're not using the default models. + +See the [Usage Reference] for more details. + +## Migrate Database + +Run migrations to create the necessary database tables: + +```bash +python manage.py migrate +``` + +## Quick Start + +1. Create a new weather location: + +```bash +python manage.py create_location +``` + +2. Fetch weather data for all locations: + +```bash +python manage.py manual_weather_fetch +``` + +3. View the weather data in the Django admin interface or use the provided views to display the information in your templates. + +## Customization + +### Models + +You can customize the models used by `django-owm` by creating your own models that inherit from the abstract base models provided by the app. Update the `OWM_MODEL_MAPPINGS` in your settings to use your custom models. + +### Views and Templates + +`django-owm` provides basic views and templates for displaying weather information. You can override these templates by creating your own templates with the same names in your project's template directory. + +### Celery Tasks + +To set up automated weather data fetching, configure Celery in your project and add the following task to your `CELERYBEAT_SCHEDULE`: + +```python +CELERYBEAT_SCHEDULE = { + 'fetch_weather_data': { + 'task': 'django_owm.tasks.fetch_weather', + 'schedule': crontab(minute='*/30'), # Run every 30 minutes + }, +} +``` -Please see the [Command-line Reference] for details. +Please see the [Usage Reference] for further details. ## Contributing @@ -68,4 +165,4 @@ This project was generated from [@OmenApps]'s [Cookiecutter Django Package] temp [license]: https://github.com/jacklinke/django-owm/blob/main/LICENSE [contributor guide]: https://github.com/jacklinke/django-owm/blob/main/CONTRIBUTING.md -[command-line reference]: https://django-owm.readthedocs.io/en/latest/usage.html +[usage reference]: https://django-owm.readthedocs.io/en/latest/usage.html diff --git a/docs/autoreference.md b/docs/autoreference.md new file mode 100644 index 0000000..746fec9 --- /dev/null +++ b/docs/autoreference.md @@ -0,0 +1,162 @@ +# Autoreference + +This document is an autogenerated reference for the `django_owm` package. It provides detailed information about the modules, classes, functions, and methods available in the package. + +## Table of Contents + +- [Autoreference](#autoreference) + - [Table of Contents](#table-of-contents) + - [django\_owm](#django_owm) + - [admin.py](#adminpy) + - [apps.py](#appspy) + - [app\_settings.py](#app_settingspy) + - [forms.py](#formspy) + - [management/commands/](#managementcommands) + - [create\_location.py](#create_locationpy) + - [delete\_location.py](#delete_locationpy) + - [list\_locations.py](#list_locationspy) + - [manual\_weather\_fetch.py](#manual_weather_fetchpy) + - [models/](#models) + - [abstract.py](#abstractpy) + - [base.py](#basepy) + - [concrete.py](#concretepy) + - [tasks.py](#taskspy) + - [urls.py](#urlspy) + - [utils/](#utils) + - [api.py](#apipy) + - [saving.py](#savingpy) + - [validators.py](#validatorspy) + - [views.py](#viewspy) + + +## django_owm + +```{eval-rst} +.. automodule:: django_owm + :members: +``` + +## admin.py + +```{eval-rst} +.. automodule:: django_owm.admin + :members: +``` + +## apps.py + +```{eval-rst} +.. automodule:: django_owm.apps + :members: +``` + +## app_settings.py + +```{eval-rst} +.. automodule:: django_owm.app_settings + :members: +``` + +## forms.py + +```{eval-rst} +.. automodule:: django_owm.forms + :members: +``` + +## management/commands/ + +### create_location.py + +```{eval-rst} +.. automodule:: django_owm.management.commands.create_location + :members: +``` + +### delete_location.py + +```{eval-rst} +.. automodule:: django_owm.management.commands.delete_location + :members: +``` + +### list_locations.py + +```{eval-rst} +.. automodule:: django_owm.management.commands.list_locations + :members: +``` + +### manual_weather_fetch.py + +```{eval-rst} +.. automodule:: django_owm.management.commands.manual_weather_fetch + :members: +``` + +## models/ + +### abstract.py + +```{eval-rst} +.. automodule:: django_owm.models.abstract + :members: +``` + +### base.py + +```{eval-rst} +.. automodule:: django_owm.models.base + :members: +``` + +### concrete.py + +```{eval-rst} +.. automodule:: django_owm.models.concrete + :members: +``` + +## tasks.py + +```{eval-rst} +.. automodule:: django_owm.tasks + :members: +``` + +## urls.py + +```{eval-rst} +.. automodule:: django_owm.urls + :members: +``` + +## utils/ + +### api.py + +```{eval-rst} +.. automodule:: django_owm.utils.api + :members: +``` + +### saving.py + +```{eval-rst} +.. automodule:: django_owm.utils.saving + :members: +``` + +## validators.py + +```{eval-rst} +.. automodule:: django_owm.validators + :members: +``` + +## views.py + +```{eval-rst} +.. automodule:: django_owm.views + :members: +``` diff --git a/docs/index.md b/docs/index.md index d405b8a..ec0c694 100644 --- a/docs/index.md +++ b/docs/index.md @@ -17,6 +17,7 @@ maxdepth: 1 usage terminology reference +autoreference contributing Code of Conduct License diff --git a/docs/reference.md b/docs/reference.md index 900bc50..c9470d2 100644 --- a/docs/reference.md +++ b/docs/reference.md @@ -1,8 +1,171 @@ # Reference -## django_owm +This document provides a detailed overview of the components of `django-owm`. -```{eval-rst} -.. automodule:: django_owm - :members: +## Table of Contents + +- [Reference](#reference) + - [Table of Contents](#table-of-contents) + - [Models](#models) + - [Management Commands](#management-commands) + - [Utility Functions](#utility-functions) + - [App Settings](#app-settings) + - [Example Settings Dictionary](#example-settings-dictionary) + - [Views](#views) + - [Admin](#admin) + +### Models + +The `django-owm` app includes several abstract models that developers can use or extend for storing weather data: + +- **AbstractWeatherLocation**: Stores information about the locations for which weather data is collected. +- **AbstractCurrentWeather**: Stores current weather data for a given location. +- **AbstractMinutelyWeather**: Stores weather data at minute intervals. +- **AbstractHourlyWeather**: Stores hourly weather data. +- **AbstractDailyWeather**: Stores daily weather data, including sunrise/sunset information. +- **AbstractWeatherAlert**: Stores alerts issued for the weather in a particular location. +- **AbstractWeatherErrorLog**: Stores information about errors encountered when fetching weather data. +- **AbstractAPICallLog**: Stores information about API calls made for weather data collection. + +These models are all abstract, allowing developers to customize their own concrete versions as needed. + +### Management Commands + +The app provides several management commands to interact with the weather data models: + +- **create\_location**: Creates a new weather location. + + - **Input Parameters**: + - **name** (str): The name of the location. + - **latitude** (float): The latitude of the location. + - **longitude** (float): The longitude of the location. + - **timezone** (str, optional): The timezone of the location. + +- **delete\_location**: Deletes a specified weather location. + + - **Input Parameters**: + - **location\_id** (int or UUID): The ID of the location to delete. + +- **list\_locations**: Lists all weather locations stored in the database. + + - **Input Parameters**: None. + +- **manual\_weather\_fetch**: Manually fetches weather data for a specific location. + + - **Input Parameters**: + - **location\_id** (int or UUID): The ID of the location for which to fetch weather data. + +These commands help developers easily manage the locations for which weather data is collected. + +### Utility Functions + +The `utils` module provides various utility functions to interact with the OpenWeatherMap API and save data: + +- **API Interaction**: Functions such as `make_api_call` for making requests to OpenWeatherMap, and `check_api_limits` to enforce API rate limits. +- **Data Saving**: Functions such as `save_weather_data`, `save_current_weather`, `save_hourly_weather`, etc., for storing weather data in the database. +- **Error Logging**: Function `save_error_log` to log errors encountered when fetching weather data. + +### App Settings + +The settings for the `django-owm` app are defined in `app_settings.py`, allowing flexibility for customization: + +- **OWM\_API\_KEY** (default: `None`): A string representing the API key used to make requests to OpenWeatherMap. This key is required for the app to function properly, as it authorizes API requests. + + - **Type**: `str` + - **Example**: `OWM_API_KEY = "your_openweathermap_api_key_here"` + - **Why Set**: Developers need to provide their own API key to connect to the OpenWeatherMap API. + +- **OWM\_API\_RATE\_LIMITS** (default: `{ "one_call": { "calls_per_minute": 60, "calls_per_month": 1000000 } }`): A dictionary defining the rate limits for the API calls, including calls per minute and per month. This helps manage API usage effectively. + + - **Type**: `dict` + - **Example**: + ```python + OWM_API_RATE_LIMITS = { + "one_call": { + "calls_per_minute": 60, + "calls_per_month": 1000000, + }, + } + ``` + - **Why Set**: To ensure that the app respects the rate limits of the OpenWeatherMap API and prevents exceeding them, which could result in blocked access. + +- **OWM\_MODEL\_MAPPINGS** (default: `{}`): A dictionary mapping abstract models to concrete model implementations in the developer's application. This setting allows developers to customize the data storage by specifying their own models. **Note: All models must be mapped in ********`OWM_MODEL_MAPPINGS`******** for the app to function correctly.** + + - **Type**: `dict` + - **Example**: + ```python + OWM_MODEL_MAPPINGS = { + "WeatherLocation": "myapp.CustomWeatherLocation", + "CurrentWeather": "myapp.CustomCurrentWeather", + "MinutelyWeather": "myapp.CustomMinutelyWeather", + "HourlyWeather": "myapp.CustomHourlyWeather", + "DailyWeather": "myapp.CustomDailyWeather", + "WeatherAlert": "myapp.CustomWeatherAlert", + "WeatherErrorLog": "myapp.CustomWeatherErrorLog", + "APICallLog": "myapp.CustomAPICallLog", + } + ``` + - **Why Set**: Developers must provide mappings for all abstract models to ensure the app's functionality. This allows them to extend or modify the behavior of default models to fit the specific requirements of their application. + +- **OWM\_USE\_BUILTIN\_ADMIN** (default: `True`): A boolean that controls whether built-in Django admin views should be used for the models. + + - **Type**: `bool` + - **Example**: `OWM_USE_BUILTIN_ADMIN = False` + - **Why Set**: If developers prefer to create custom admin interfaces for managing weather data, they can set this to `False` and override the default behavior. + +- **OWM\_USE\_UUID** (default: `False`): A boolean that configures whether a `uuid` field should be added to the models for querying and data uniqueness. + + - **Type**: `bool` + - **Example**: `OWM_USE_UUID = True` + - **Why Set**: Developers may choose to use UUIDs for models to enhance data uniqueness and security, particularly in distributed systems. + +#### Example Settings Dictionary + +```python +DJANGO_OWM = { + "OWM_API_KEY": "your_openweathermap_api_key_here", + "OWM_API_RATE_LIMITS": { + "one_call": { + "calls_per_minute": 60, + "calls_per_month": 1000000, + }, + }, + "OWM_MODEL_MAPPINGS": { + "WeatherLocation": "myapp.CustomWeatherLocation", + "CurrentWeather": "myapp.CustomCurrentWeather", + "MinutelyWeather": "myapp.CustomMinutelyWeather", + "HourlyWeather": "myapp.CustomHourlyWeather", + "DailyWeather": "myapp.CustomDailyWeather", + "WeatherAlert": "myapp.CustomWeatherAlert", + "WeatherErrorLog": "myapp.CustomWeatherErrorLog", + "APICallLog": "myapp.CustomAPICallLog", + }, + "OWM_USE_BUILTIN_ADMIN": True, + "OWM_USE_UUID": False, +} ``` + +These settings provide a flexible and extensible approach to managing the app's configuration, allowing developers to tailor the behavior and data models of the `django-owm` app to meet the needs of their specific project. + +### Views + +The app provides several function-based views for displaying weather data: + +- **list\_locations**: Displays a list of all weather locations. +- **create\_location**: Allows users to create a new weather location. +- **update\_location**: Allows users to update an existing location's details. +- **delete\_location**: Deletes a specified weather location. +- **weather\_detail**: Displays current weather details for a specified location. +- **weather\_history**: Displays historical weather data. +- **weather\_forecast**: Shows hourly and daily forecasts for a location. +- **weather\_alerts**: Displays any active weather alerts for a location. +- **weather\_errors**: Shows logged errors encountered when fetching data. + +These views are designed to be easily customizable and integrate seamlessly with Django templates. + +### Admin + +The app provides built-in Django admin support for the weather data models, including: + +- **WeatherLocationAdmin**: Manage weather locations. +- **CurrentWeatherAdmin**: View and manage current weather data diff --git a/docs/terminology.md b/docs/terminology.md index 8e5a62c..0f79079 100644 --- a/docs/terminology.md +++ b/docs/terminology.md @@ -1,9 +1,29 @@ -# Terminology and Definitions +# django-owm Terminology and Definitions -## Topic 1 +This document provides definitions for key terms and concepts used in the `django-owm` app. -Content +## Weather Data Terms -## Topic 2 +- **Current Weather**: The most recent weather data for a specific location. +- **Minutely Forecast**: Minute-by-minute weather forecast for the next hour. +- **Hourly Forecast**: Hour-by-hour weather forecast for the next 48 hours. +- **Daily Forecast**: Day-by-day weather forecast for the next 7 days. +- **Weather Alert**: Severe weather warnings or advisories for a specific location. -Content +## API-related Terms + +- **OpenWeatherMap**: The third-party service providing weather data through its API. +- **One Call API 3.0**: The specific OpenWeatherMap API used by `django-owm` to fetch weather data. +- **API Key**: A unique identifier required to authenticate and make requests to the OpenWeatherMap API. +- **API Rate Limit**: The maximum number of API requests allowed within a specific time frame. + +## Model-related Terms + +- **WeatherLocation**: A model representing a geographic location for which weather data is collected. +- **CurrentWeather**: A model storing the current weather conditions for a location. +- **MinutelyWeather**: A model storing minute-by-minute weather forecast data. +- **HourlyWeather**: A model storing hour-by-hour weather forecast data. +- **DailyWeather**: A model storing day-by-day weather forecast data. +- **WeatherAlert**: A model storing severe weather alerts for a location. +- **WeatherErrorLog**: A model for logging errors that occur during weather data fetching or processing. +- **APICallLog**: A model for tracking API calls made to OpenWeatherMap. diff --git a/docs/usage.md b/docs/usage.md index f5b797e..eb7a1fa 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -1,43 +1,132 @@ -# Usage +# Using django-owm -## admin.py +This guide provides detailed instructions on how to use the `django-owm` app in your Django project. -```{eval-rst} -.. automodule:: django_owm.admin - :members: -``` +## 1. Setting Up Weather Locations + +Before you can fetch weather data, you need to set up one or more weather locations. -## apps.py +### Using the Management Command -```{eval-rst} -.. automodule:: django_owm.apps - :members: +```bash +python manage.py create_location ``` -## forms.py +This command will prompt you to enter the location name, latitude, and longitude. + +### Using the Django Admin + +1. Navigate to the Django admin interface. +2. Click on "Weather locations" under the "Django_owm" section. +3. Click "Add weather location" and fill in the required information. + +### Using the Provided View + +1. Navigate to `/owm/locations/create/` in your browser. +2. Fill out the form with the location details and submit. + +## 2. Fetching Weather Data + +### Manual Fetching + +To manually fetch weather data for all locations: -```{eval-rst} -.. automodule:: django_owm.forms - :members: +```bash +python manage.py manual_weather_fetch ``` -## models.py +To fetch data for a specific location: -```{eval-rst} -.. automodule:: django_owm.models - :members: +```bash +python manage.py manual_weather_fetch ``` -## views.py +### Automated Fetching with Celery + +If you've set up Celery and configured the periodic task as described in the README, weather data will be fetched automatically according to your specified schedule. + +## 3. Viewing Weather Data + +### Using the Django Admin + +1. Navigate to the Django admin interface. +2. Click on the desired weather data model (e.g., "Current weathers", "Hourly weathers", etc.) under the "Django_owm" section. +3. You can view and filter the weather data for different locations and timestamps. + +### Using the Provided Views + +- List all locations: `/owm/locations/` +- Weather detail for a location: `/owm/weather//` + +## 4. Customizing the App + +### Overriding Templates -```{eval-rst} -.. automodule:: django_owm.views - :members: +To customize the appearance of the provided views, create your own templates in your project's template directory with the same names as the `django-owm` templates. For example: + +- `templates/django_owm/list_locations.html` +- `templates/django_owm/weather_detail.html` +- `templates/django_owm/weather_forecast.html` + +### Extending Models + +To add custom fields or methods to the weather data models: + +1. Create your own models that inherit from the `django-owm` abstract models. +2. Update the `OWM_MODEL_MAPPINGS` in your project's settings to use your custom models. + +Example: + +```python +from django_owm.models import AbstractCurrentWeather + +class CustomCurrentWeather(AbstractCurrentWeather): + custom_field = models.CharField(max_length=100) + + class Meta: + abstract = False + +# In your settings.py +DJANGO_OWM = { + # ... + 'OWM_MODEL_MAPPINGS': { + # ... + 'CurrentWeather': 'your_app.CustomCurrentWeather', + # ... + }, + # ... +} ``` -## urls.py +### Creating Custom Views -```{eval-rst} -.. automodule:: django_owm.urls - :members: +You can create your own views to display weather data in a custom format or to integrate it with other parts of your application. Use the `django-owm` models to query the weather data as needed. + +Example: + +```python +from django.shortcuts import render +from django_owm.app_settings import OWM_MODEL_MAPPINGS +from django.apps import apps + +def custom_weather_view(request, location_id): + WeatherLocationModel = apps.get_model(OWM_MODEL_MAPPINGS.get('WeatherLocation')) + CurrentWeatherModel = apps.get_model(OWM_MODEL_MAPPINGS.get('CurrentWeather')) + + location = WeatherLocationModel.objects.get(pk=location_id) + current_weather = CurrentWeatherModel.objects.filter(location=location).latest('timestamp') + + context = { + 'location': location, + 'current_weather': current_weather, + } + return render(request, 'your_app/custom_weather_template.html', context) ``` + +## 5. Troubleshooting + +- If you're not seeing any weather data, ensure that you've set up at least one weather location and run the `manual_weather_fetch` command or waited for the Celery task to execute. +- Check the `WeatherErrorLog` model in the Django admin for any errors that occurred during weather data fetching. +- Verify that your OpenWeatherMap API key is correct and that you haven't exceeded your API rate limits. + +By following this guide, you should be able to effectively use and customize the `django-owm` app in your Django project. If you encounter any issues or have questions, please refer to the project's documentation or open an issue on the GitHub repository. diff --git a/noxfile.py b/noxfile.py index e12733c..fcdee68 100644 --- a/noxfile.py +++ b/noxfile.py @@ -2,24 +2,12 @@ import os import shlex import shutil -import sys from pathlib import Path from textwrap import dedent import nox - - -try: - from nox_poetry import Session - from nox_poetry import session -except ImportError: - message = f"""\ - Nox failed to import the 'nox-poetry' package. - - Please install it using the following command: - - {sys.executable} -m pip install nox-poetry""" - raise SystemExit(dedent(message)) from None +from nox import session +from nox.sessions import Session # DJANGO_STABLE_VERSION should be set to the latest Django LTS version @@ -28,12 +16,13 @@ DJANGO_VERSIONS = [ "4.2", "5.0", + "5.1", ] # PYTHON_STABLE_VERSION should be set to the latest stable Python version PYTHON_STABLE_VERSION = "3.12" -PYTHON_VERSIONS = ["3.9", "3.10", "3.11", "3.12"] +PYTHON_VERSIONS = ["3.10", "3.11", "3.12"] package = "django_owm" @@ -152,7 +141,7 @@ def precommit(session: Session, django: str) -> None: @nox.parametrize("django", DJANGO_STABLE_VERSION) def safety(session: Session, django: str) -> None: """Scan dependencies for insecure packages.""" - requirements = session.poetry.export_requirements() + requirements = session.posargs or ["requirements.txt"] session.install("safety") session.run("safety", "check", "--full-report", f"--file={requirements}")