Skip to content
This repository was archived by the owner on Aug 2, 2024. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
1d23673
create branch
bergasanargya May 24, 2024
b4ee9cc
Added models and views
bergasanargya May 24, 2024
35b608f
added new models and views
bergasanargya May 24, 2024
b0be572
manage to somewhat connect with inventory, still working to connect t…
bergasanargya May 25, 2024
cd2542c
New push to fix the viewon the curl command
bergasanargya May 25, 2024
6ccbeaf
Merge branch 'main' into working_inventory
dluman May 30, 2024
6f59e5e
Updating API structure changes
dluman May 30, 2024
03e87c8
Updating WSGI definition
dluman May 30, 2024
54ebcbf
Merge pull request #6 from term-world/main
dluman May 30, 2024
2a7d851
revised climate api to include django self-documentation
dyga01 Jun 1, 2024
0a97774
Factor into Django REST structure
dluman Jun 2, 2024
d9fbe76
Fixing up working structure to allow multiple companion applications
dluman Jun 2, 2024
affe8f9
Need to list individual response fields for documentation's sake
dluman Jun 2, 2024
410f354
Serializes correctly; would like to avoid manually specifying fields,…
dluman Jun 2, 2024
76d90db
Clear up serializer
dluman Jun 2, 2024
f7337ac
Fixing one-off API by assuming there's only ever 1-of-1
dluman Jun 3, 2024
db0bd2a
Removing extra semantic step for climate API
dluman Jun 3, 2024
a568294
postgresql
Danniyb Jun 3, 2024
d161884
adjusting models
Danniyb Jun 3, 2024
30efd8f
adjusting models
Danniyb Jun 3, 2024
d9a2b4a
merge
Danniyb Jun 3, 2024
0d64c31
Merging the working_inventory branch into refactored... to clean up w…
dluman Jun 3, 2024
3353060
Updating with new JSON API pass-through field
dluman Jun 5, 2024
e4a8be9
Updating dependencies to include setuptools
dluman Jun 5, 2024
8f491cb
attempted to implement swagger for documentation
dyga01 Jun 5, 2024
22c4736
Resolved merge conflicts and added swagger details
dyga01 Jun 5, 2024
5228585
First use of Swagger UI; how can we customize?
dluman Jun 5, 2024
b64d680
added static and template folders for swagger ui customization
dyga01 Jun 6, 2024
1f8e1dd
added swagger settings and attempted to implement colors
dyga01 Jun 8, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions srv/endpoints/api/admin.py

This file was deleted.

3 changes: 0 additions & 3 deletions srv/endpoints/api/models.py

This file was deleted.

3 changes: 0 additions & 3 deletions srv/endpoints/api/tests.py

This file was deleted.

3 changes: 0 additions & 3 deletions srv/endpoints/api/views.py

This file was deleted.

1 change: 1 addition & 0 deletions srv/endpoints/climate/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
default_app_config = 'climate.apps.ClimateConfig'
1 change: 1 addition & 0 deletions srv/endpoints/climate/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Register your models here.
5 changes: 2 additions & 3 deletions srv/endpoints/api/apps.py → srv/endpoints/climate/apps.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from django.apps import AppConfig


class ApiConfig(AppConfig):
class ClimateConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'api'
name = 'climate'
27 changes: 27 additions & 0 deletions srv/endpoints/climate/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Generated by Django 5.0.6 on 2024-06-02 16:07

import django.db.models.manager
from django.db import migrations, models


class Migration(migrations.Migration):

initial = True

dependencies = [
]

operations = [
migrations.CreateModel(
name='TransientModel',
fields=[
('id', models.IntegerField(primary_key=True, serialize=False)),
],
options={
'managed': False,
},
managers=[
('obj', django.db.models.manager.Manager()),
],
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Generated by Django 5.0.6 on 2024-06-05 19:04

import django.db.models.manager
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('climate', '0001_initial'),
]

operations = [
migrations.CreateModel(
name='ClimateModel',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('coord', models.JSONField()),
('weather', models.JSONField()),
('base', models.JSONField()),
('main', models.JSONField()),
('visibility', models.JSONField()),
('wind', models.JSONField()),
('rain', models.JSONField()),
('clouds', models.JSONField()),
('dt', models.JSONField()),
('sys', models.JSONField()),
('timezone', models.JSONField()),
('name', models.JSONField()),
('cod', models.JSONField()),
],
options={
'managed': False,
},
managers=[
('obj', django.db.models.manager.Manager()),
],
),
migrations.DeleteModel(
name='TransientModel',
),
]
68 changes: 68 additions & 0 deletions srv/endpoints/climate/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import os
import requests
from collections import UserList
from django.db import models
from django.core import serializers
from django.core.cache import caches
from dotenv import load_dotenv

load_dotenv()
CACHE = caches["default"]

# This functionality builds on an answer for the following SO question,
# but not the accepted answer; this one is farther down in the post:
#
# https://stackoverflow.com/questions/9091305/django-models-without-database

class ClimateModelManager(models.Manager):

api = os.getenv("OPENWEATHER_API")
lat = os.getenv("OPENWEATHER_LAT")
lon = os.getenv("OPENWEATHER_LON")

cache_key = "cached-transient-models"
cache_sentinel = object()
cache_timeout = 600

def get_queryset(self):
climate_model_data = CACHE.get(self.cache_key, self.cache_sentinel)
if climate_model_data is self.cache_sentinel:
response = requests.get(
f"https://api.openweathermap.org/data/2.5/weather?lat={self.lat}&lon={self.lon}&appid={self.api}"
)
response.raise_for_status()
climate_model_data = response.json()
CACHE.set(self.cache_key, climate_model_data, self.cache_timeout)
return ClimateModelQueryset(
[ClimateModel(**climate_model_data)]
)

class ClimateModelQueryset(UserList):
pass

class ClimateModel(models.Model):
class Meta:
managed = False

obj = ClimateModelManager.from_queryset(ClimateModelQueryset)()

coord = models.JSONField()
weather = models.JSONField()
base = models.JSONField()
main = models.JSONField()
visibility = models.JSONField()
wind = models.JSONField()
rain = models.JSONField()
clouds = models.JSONField()
dt = models.JSONField()
sys = models.JSONField()
timezone = models.JSONField()
name = models.JSONField()
cod = models.JSONField()

def as_dict(self):
result = {}
fields = self._meta.fields
for field in fields:
result[field.name] = getattr(self, field.name)
return result
9 changes: 9 additions & 0 deletions srv/endpoints/climate/serializers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from rest_framework import serializers
from climate.models import ClimateModel

class ClimateModelSerializer(serializers.ModelSerializer):

class Meta:
model = ClimateModel
fields = "__all__"

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 16 additions & 0 deletions srv/endpoints/climate/static/climate/swagger-ui/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
html {
box-sizing: border-box;
overflow: -moz-scrollbars-vertical;
overflow-y: scroll;
}

*,
*:before,
*:after {
box-sizing: inherit;
}

body {
margin: 0;
background: #fafafa;
}
19 changes: 19 additions & 0 deletions srv/endpoints/climate/static/climate/swagger-ui/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<!-- HTML for static distribution bundle build -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Swagger UI</title>
<link rel="stylesheet" type="text/css" href="./swagger-ui.css" />
<link rel="stylesheet" type="text/css" href="index.css" />
<link rel="icon" type="image/png" href="./favicon-32x32.png" sizes="32x32" />
<link rel="icon" type="image/png" href="./favicon-16x16.png" sizes="16x16" />
</head>

<body>
<div id="swagger-ui"></div>
<script src="./swagger-ui-bundle.js" charset="UTF-8"> </script>
<script src="./swagger-ui-standalone-preset.js" charset="UTF-8"> </script>
<script src="./swagger-initializer.js" charset="UTF-8"> </script>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<!doctype html>
<html lang="en-US">
<head>
<title>Swagger UI: OAuth2 Redirect</title>
</head>
<body>
<script>
'use strict';
function run () {
var oauth2 = window.opener.swaggerUIRedirectOauth2;
var sentState = oauth2.state;
var redirectUrl = oauth2.redirectUrl;
var isValid, qp, arr;

if (/code|token|error/.test(window.location.hash)) {
qp = window.location.hash.substring(1).replace('?', '&');
} else {
qp = location.search.substring(1);
}

arr = qp.split("&");
arr.forEach(function (v,i,_arr) { _arr[i] = '"' + v.replace('=', '":"') + '"';});
qp = qp ? JSON.parse('{' + arr.join() + '}',
function (key, value) {
return key === "" ? value : decodeURIComponent(value);
}
) : {};

isValid = qp.state === sentState;

if ((
oauth2.auth.schema.get("flow") === "accessCode" ||
oauth2.auth.schema.get("flow") === "authorizationCode" ||
oauth2.auth.schema.get("flow") === "authorization_code"
) && !oauth2.auth.code) {
if (!isValid) {
oauth2.errCb({
authId: oauth2.auth.name,
source: "auth",
level: "warning",
message: "Authorization may be unsafe, passed state was changed in server. The passed state wasn't returned from auth server."
});
}

if (qp.code) {
delete oauth2.state;
oauth2.auth.code = qp.code;
oauth2.callback({auth: oauth2.auth, redirectUrl: redirectUrl});
} else {
let oauthErrorMsg;
if (qp.error) {
oauthErrorMsg = "["+qp.error+"]: " +
(qp.error_description ? qp.error_description+ ". " : "no accessCode received from the server. ") +
(qp.error_uri ? "More info: "+qp.error_uri : "");
}

oauth2.errCb({
authId: oauth2.auth.name,
source: "auth",
level: "error",
message: oauthErrorMsg || "[Authorization failed]: no accessCode received from the server."
});
}
} else {
oauth2.callback({auth: oauth2.auth, token: qp, isValid: isValid, redirectUrl: redirectUrl});
}
window.close();
}

if (document.readyState !== 'loading') {
run();
} else {
document.addEventListener('DOMContentLoaded', function () {
run();
});
}
</script>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
window.onload = function() {
//<editor-fold desc="Changeable Configuration Block">

// the following lines will be replaced by docker/configurator, when it runs in a docker-container
window.ui = SwaggerUIBundle({
url: "https://petstore.swagger.io/v2/swagger.json",
dom_id: '#swagger-ui',
deepLinking: true,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
layout: "StandaloneLayout"
});

//</editor-fold>
};

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

19 changes: 19 additions & 0 deletions srv/endpoints/climate/static/climate/swagger-ui/swagger-ui.css

Large diffs are not rendered by default.

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions srv/endpoints/climate/static/climate/swagger-ui/swagger-ui.js

Large diffs are not rendered by default.

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions srv/endpoints/climate/tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Create your tests here.
6 changes: 6 additions & 0 deletions srv/endpoints/climate/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.urls import re_path, path
from .views import ClimateDataViewAll

urlpatterns = [
path('', ClimateDataViewAll.as_view(), name='climate-all'),
]
7 changes: 7 additions & 0 deletions srv/endpoints/climate/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from drf_yasg.inspectors import SwaggerAutoSchema

class CustomAutoSchema(SwaggerAutoSchema):
def get_operation(self, operation_keys):
operation = super().get_operation(operation_keys)
# Customize the operation object as needed here
return operation
27 changes: 27 additions & 0 deletions srv/endpoints/climate/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import json

from rest_framework.generics import ListAPIView, RetrieveAPIView
from rest_framework.exceptions import APIException
from rest_framework.response import Response
from django.http import HttpResponse
from django.core import serializers
from rest_framework.permissions import AllowAny

from climate.models import ClimateModel
from climate.serializers import ClimateModelSerializer

class ClimateDataViewAll(RetrieveAPIView):

permission_classes = [AllowAny]
serializer_class = ClimateModelSerializer

def get_queryset(self):
try:
queryset = ClimateModel.obj.all()
return queryset
except Exception as e:
raise APIException(e) from e

def get(self, request):
fields = [obj.as_dict() for obj in self.get_queryset()][-1]
return HttpResponse(json.dumps(fields), content_type = "application/json")
7 changes: 7 additions & 0 deletions srv/endpoints/core/asgi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import os

from django.core.asgi import get_asgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'core.settings')

application = get_asgi_application()
Loading