Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • fejao/c3buttons
1 result
Show changes
Commits on Source (2)
Showing
with 1040 additions and 0 deletions
*.venv*
*__pycache__*
*OLD*
*fejao_notes*
"""
Default setted file from django for an added app.
"""
from django.apps import AppConfig
class ApiConfig(AppConfig):
"""Default setted SharedModelsConfig class for the app.
"""
default_auto_field = "django.db.models.BigAutoField"
name = "api"
"""
File for setting the URLs used from the api django app.
"""
from django.urls import path
from . import views
urlpatterns = [
path('box/search', views.ButtonBoxSearchView.as_view(), name='box_search'),
path('box/use', views.ButtonBoxUseView.as_view(), name='box_use'),
path('box/use/count', views.ButtonBoxUseCountView.as_view(), name='box_use_count'),
]
"""
File for setting the view classes used from the api django app.
"""
from datetime import datetime, timezone
from shared_models.models import ButtonBox, ButtonBoxUse
from shared_models.serializers import ButtonBoxSerializer, ButtonBoxUseSerializer
from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.renderers import JSONRenderer
from rest_framework_simplejwt.authentication import JWTAuthentication
###
### HELPERS
###
def helper_get_from_parsed(parsed_name: str, parsed_value: str, parsed_type: str):
"""Helper method used from the ButtonBoxUseView class for setting the return values from different 'parsed_name' and 'parsed_type'.
It will fetch or update the values from the ButtonBoxUse model.
Parameters
----------
parsed_name: str
String with the name parsed.
parsed_value: str
String with the value parsed.
parsed_type: str
String with the type parsed.
Returns
-------
ret_dict: dict
The Dictionary with the output from executing this helper method.
ret_status: rest_framework.status
The HTTP status from executing this helper method.
"""
founded_box = None
ret_dict = None
ret_status = status.HTTP_500_INTERNAL_SERVER_ERROR
try:
if parsed_name == "id":
founded_box = ButtonBox.objects.get(id=parsed_value)
elif parsed_name == "name":
founded_box = ButtonBox.objects.get(name=parsed_value)
elif parsed_name == "pin_button":
founded_box = ButtonBox.objects.get(pin_button=parsed_value)
elif parsed_name == "pin_led":
founded_box = ButtonBox.objects.get(pin_led=parsed_value)
else:
ret_dict = {
'error': True,
'error_msg': f"ERROR: unknown parameter parsed: {parsed_name}."
}
ret_status = status.HTTP_406_NOT_ACCEPTABLE
except ButtonBox.DoesNotExist:
ret_dict = {
'error': True,
'error_msg': f"No Box could be founded with the '{parsed_name}': {parsed_value}"
}
ret_status = status.HTTP_404_NOT_FOUND
except Exception as e:
ret_dict = {
'error': True,
'error_msg': f"ERROR happend when trying to search for the box with {parsed_name}: {parsed_value} | Error: {e}"
}
ret_status = status.HTTP_406_NOT_ACCEPTABLE
### If error ocurred, finish
if ret_dict is not None:
pass
else:
if parsed_type == "add":
try:
### Add pushed from pin
added = ButtonBoxUse(box_used=founded_box)
added.save()
ret_dict = {
'error': False,
'message': "Added button press",
"button-used": {
"id": added.id,
"box_id": added.box_used.id,
'box_name': added.box_used.name,
'box_pin_button': added.box_used.pin_button,
'box_pin_led': added.box_used.pin_led,
'date': str(added.date)
}
}
ret_status = status.HTTP_200_OK
except Exception as e:
ret_dict = {
'error': True,
'message': f"Error saving the press button with output: {e}",
}
ret_status = status.HTTP_418_IM_A_TEAPOT
elif parsed_type == "list":
try:
### Get list pushed button
box_uses = ButtonBoxUse.objects.filter(box_used=founded_box)
serializer = ButtonBoxUseSerializer(box_uses, many=True)
ret_dict = serializer.data
ret_status = status.HTTP_200_OK
except Exception as e:
ret_dict = {
'error': True,
'error_msg': f"ERROR happend when trying to search for the box with {parsed_name}: {parsed_value} | Error: {e}"
}
ret_status = status.HTTP_406_NOT_ACCEPTABLE
else:
ret_dict = {
'error': True,
'error_msg': "ERROR parsing response from 'helper_get_from_parsed' function"
}
ret_status = status.HTTP_501_NOT_IMPLEMENTED
return ret_dict, ret_status
###
### VIEW CLASSES
###
class ButtonBoxSearchView(APIView):
"""Class for setting the API views for Searching at the ButtonBox model.
"""
# permission_classes = [IsAuthenticated]
authentication_classes = [JWTAuthentication]
renderer_classes = [JSONRenderer]
def get(self, request, format=None):
"""Method for dealing with the GET requests done at this view.
Parameters
----------
request: rest_framework.request.Request
The parameters from the GET request.
format: None
If some format was sent.
Returns
-------
rest_framework.response.Response
The response object.
"""
# Get parsed
box_id = request.query_params.get("id")
box_name = request.query_params.get("name")
box_pin_button = request.query_params.get("pin_button")
box_pin_led = request.query_params.get("pin_led")
if box_id is not None and box_name is None and box_pin_button is None and box_pin_led is None:
box_founded = ButtonBox.objects.filter(id__icontains=box_id)
elif box_id is None and box_name is not None and box_pin_button is None and box_pin_led is None:
box_founded = ButtonBox.objects.filter(name__icontains=box_name)
elif box_id is None and box_name is None and box_pin_button is not None and box_pin_led is None:
box_founded = ButtonBox.objects.filter(pin_button__icontains=box_pin_button)
elif box_id is None and box_name is None and box_pin_button is None and box_pin_led is not None:
box_founded = ButtonBox.objects.filter(pin_led__icontains=box_pin_led)
# If not, return all
else:
box_founded = ButtonBox.objects.all()
serializer = ButtonBoxSerializer(box_founded, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)
class ButtonBoxUseView(APIView):
"""Class for setting the API views for Searching and Adding values at the ButtonBoxUse model.
"""
# permission_classes = [IsAuthenticated]
authentication_classes = [JWTAuthentication]
renderer_classes = [JSONRenderer]
def get(self, request, format=None):
"""Method for dealing with the GET requests done at this view.
Parameters
----------
request: rest_framework.request.Request
The parameters from the GET request.
format: None
If some format was sent.
Returns
-------
rest_framework.response.Response
The response object.
"""
# Get parsed
box_id = request.query_params.get("id")
box_name = request.query_params.get("name")
box_pin_button = request.query_params.get("pin_button")
box_pin_led = request.query_params.get("pin_led")
if box_id is not None and box_name is None and box_pin_button is None and box_pin_led is None:
founded_box = ButtonBox.objects.get(id=box_id)
elif box_id is None and box_name is not None and box_pin_button is None and box_pin_led is None:
founded_box = ButtonBox.objects.get(name=box_name)
elif box_id is None and box_name is None and box_pin_button is not None and box_pin_led is None:
founded_box = ButtonBox.objects.get(pin_button=box_pin_button)
elif box_id is None and box_name is None and box_pin_button is None and box_pin_led is not None:
founded_box = ButtonBox.objects.get(pin_led=box_pin_led)
else:
founded_box = None
# Get from parsed, if None get all
if founded_box is None:
boxes_uses = ButtonBoxUse.objects.all()
serializer = ButtonBoxUseSerializer(boxes_uses, many=True)
else:
box_uses = ButtonBoxUse.objects.filter(box_used=founded_box)
serializer = ButtonBoxUseSerializer(box_uses, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)
def post(self, request, format=None):
"""Method for dealing with the POST requests done at this view.
Parameters
----------
request: rest_framework.request.Request
The parameters from the POST request.
format: None
If some format was sent.
Returns
-------
rest_framework.response.Response
The response object.
"""
# Get the box name from the query parameters (if Nonne, default to empty str)
parsed_id = request.data.get("id")
parsed_name = request.data.get("name")
# parsed_pin_number = request.data.get("pin_number")
parsed_pin_button = request.data.get("pin_button")
parsed_pin_led = request.data.get("pin_led")
if parsed_id is None and parsed_name is None and parsed_pin_button is None and parsed_pin_led is None:
ret_dict = {
"error": True,
"message": "Unable to add box used from this end-point withtout parsed info from 'name', 'pin_button' or 'pin_led'"
}
ret_status = status.HTTP_400_BAD_REQUEST
elif parsed_id is not None and parsed_name is not None and parsed_pin_button is not None and parsed_pin_led is not None:
ret_dict = {
"error": True,
"message": "Unable to add box used from this end-point with MULTIPLE parsed infos from 'id', 'name', 'pin_button' and 'pin_led'. Use only one"
}
ret_status = status.HTTP_400_BAD_REQUEST
### ID
elif parsed_id is not None and parsed_name is None and parsed_pin_button is None and parsed_pin_led is None:
ret_dict, ret_status = helper_get_from_parsed(
parsed_name='id',
parsed_value=parsed_id,
parsed_type='add'
)
### NAME
elif parsed_name is not None and parsed_pin_button is None and parsed_pin_led is None:
ret_dict, ret_status = helper_get_from_parsed(
parsed_name='name',
parsed_value=parsed_name,
parsed_type='add'
)
### PIN_BUTTON
elif parsed_name is None and parsed_pin_button is not None and parsed_pin_led is None:
ret_dict, ret_status = helper_get_from_parsed(
parsed_name='pin_button',
parsed_value=parsed_pin_button,
parsed_type='add'
)
### PIN_LED
elif parsed_name is None and parsed_pin_button is None and parsed_pin_led is not None:
ret_dict, ret_status = helper_get_from_parsed(
parsed_name='pin_led',
parsed_value=parsed_pin_led,
parsed_type='add'
)
else:
ret_dict = {
"error": True,
"message": "Option not implemented..."
}
ret_status = status.HTTP_501_NOT_IMPLEMENTED
return Response(ret_dict, status=ret_status)
class ButtonBoxUseCountView(APIView):
"""Class for setting the API views for getting the amount of uses from a Button Box.
It is mostly used from Grafana for getting the fancy requests from date windows.
"""
# permission_classes = [IsAuthenticated]
authentication_classes = [JWTAuthentication]
renderer_classes = [JSONRenderer]
def get(self, request, format=None):
"""Method for dealing with the GET requests done at this view.
Parameters
----------
request: rest_framework.request.Request
The parameters from the GET request.
format: None
If some format was sent.
Returns
-------
rest_framework.response.Response
The response object.
"""
###
### EXAMPLE of the grafana used URL ;)
###
### http://localhost:8000/api/box/use/count?from=${__from}&to=${__to}
###
### GET PARSED
query_param_from = request.query_params.get("from")
query_param_to = request.query_params.get("to")
if query_param_from is not None and query_param_to is None:
ret_list = [
{
'error': True,
'error_msg': "Query parameter for 'from' is parsed and 'to' is not parsed. You have to use BOUTH or NONE"
}
]
ret_status = status.HTTP_400_BAD_REQUEST
elif query_param_from is None and query_param_to is not None:
ret_list = [
{
'error': True,
'error_msg': "Query parameter for 'to' is parsed and 'from' is not parsed. You have to use BOUTH or NONE"
}
]
ret_status = status.HTTP_400_BAD_REQUEST
### RETURN ALL
elif query_param_from is None and query_param_to is None:
ret_list = []
for button_box in ButtonBox.objects.all():
ret_list.append(
{
"name": button_box.name,
"count": ButtonBoxUse.objects.filter(box_used=button_box).count()
}
)
ret_status = status.HTTP_200_OK
### RETURN FROM TIME FRAME
elif query_param_from is not None and query_param_to is not None:
try:
date_from = datetime.fromtimestamp(int(query_param_from) / 1000, timezone.utc)
except Exception as e:
ret_list = [
{
'error': True,
'error_msg': f"Error parsing epoch time to datetime from parsed 'date_from' parameter with error: {e}"
}
]
ret_status = status.HTTP_400_BAD_REQUEST
try:
date_to = datetime.fromtimestamp(int(query_param_to) / 1000, timezone.utc)
except Exception as e:
ret_list = [
{
'error': True,
'error_msg': f"Error parsing epoch time to datetime from parsed 'date_to' parameter with error: {e}"
}
]
ret_status = status.HTTP_400_BAD_REQUEST
ret_list = []
for button_box in ButtonBox.objects.all():
button_name = button_box.name
count = 0
for button_use in ButtonBoxUse.objects.filter(date__gt=date_from, date__lt=date_to):
if button_name == button_use.box_name:
count += 1
ret_list.append(
{
"name": button_name,
"count": count,
"date": button_use.date
}
)
ret_status = status.HTTP_200_OK
else:
ret_list = [
{
'error': True,
'error_msg': "Not implemented"
}
]
ret_status = status.HTTP_501_NOT_IMPLEMENTED
return Response(ret_list, status=ret_status)
"""
Default setted file from django for an added app.
"""
from django.apps import AppConfig
class ApiAdminConfig(AppConfig):
"""Default setted SharedModelsConfig class for the app.
"""
default_auto_field = "django.db.models.BigAutoField"
name = "api_admin"
"""
File for setting the URLs used from the api_admin django app.
"""
from django.urls import path
from . import views
urlpatterns = [
path('box', views.AdminButtonBoxListCreateDeleteView.as_view(), name='admin_box'),
path('box/edit/<int:pk>', views.AdminButtonBoxRetrieveUpdateDestroyView.as_view(), name='admin_box_edit'),
path('box/use', views.AdminButtonBoxUseListCreateView.as_view(), name='admin_box_use'),
]
"""
File for setting the view classes used from the api_admin django app.
"""
from shared_models.models import ButtonBox, ButtonBoxUse
from shared_models.serializers import ButtonBoxSerializer, ButtonBoxUseSerializer
from rest_framework import generics, status
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
from backend.settings import DEFAULT_DJANGO_DEBUG
class AdminButtonBoxListCreateDeleteView(generics.ListCreateAPIView):
"""Class for setting the API views for Create, Read and Delete the entries at the ButtonBox model.
"""
permission_classes = [IsAuthenticated]
queryset = ButtonBox.objects.all()
serializer_class = ButtonBoxSerializer
def delete(self, request, *args, **kwargs):
"""Method for deleting all ButtonBox model objects.
"""
# Delete only by debug mode
if DEFAULT_DJANGO_DEBUG:
ButtonBox.objects.all().delete()
return Response(status=status.HTTP_204_NO_CONTENT)
else:
ret_dict = {
"error": False,
"message": "You can only delete all in debub mode --> set the 'DEFAULT_DJANGO_DEBUG' to 'True'"
}
return Response(ret_dict, status=status.HTTP_412_PRECONDITION_FAILED)
class AdminButtonBoxRetrieveUpdateDestroyView(generics.RetrieveUpdateDestroyAPIView):
"""Class for setting the API views for Updating entries at the ButtonBox model.
"""
permission_classes = [IsAuthenticated]
queryset = ButtonBox.objects.all()
serializer_class = ButtonBoxSerializer
### pk --> primary_key
lookup_field = "pk"
class AdminButtonBoxUseListCreateView(generics.ListCreateAPIView):
"""Class for setting the API views for Creating entries at the ButtonBoxUse model.
"""
permission_classes = [IsAuthenticated]
queryset = ButtonBoxUse.objects.all()
serializer_class = ButtonBoxUseSerializer
def delete(self, request, *args, **kwargs):
"""Method for deleting all ButtonBoxUse model objects.
"""
# Delete only by debug mode
if DEFAULT_DJANGO_DEBUG:
ButtonBoxUse.objects.all().delete()
return Response(status=status.HTTP_204_NO_CONTENT)
else:
ret_dict = {
"error": False,
"message": "You can only delete all in debub mode --> set the 'DEFAULT_DJANGO_DEBUG' to 'True'"
}
return Response(ret_dict, status=status.HTTP_412_PRECONDITION_FAILED)
"""
Default setted file from django for an added app.
"""
from django.apps import AppConfig
class ApiAuthConfig(AppConfig):
"""Default setted SharedModelsConfig class for the app.
"""
default_auto_field = "django.db.models.BigAutoField"
name = "api_auth"
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Login</title>
</head>
<body>
<h2>Login</h2>
{% if user.is_authenticated %}
<p>Logged in as {{ user.username }}</p>
<a href="{% url 'logout' %}">Logout</a>
{% else %}
<p>You are not logged in.</p>
{% endif %}
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Login</button>
</form>
</body>
</html>
\ No newline at end of file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Logout</title>
</head>
<body>
<h2>You have been logged out.</h2>
<a href="{% url 'login' %}">Log in again</a>
</body>
</html>
\ No newline at end of file
"""
File for setting the URLs used from the api_auth django app.
"""
### TOKEN
from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView
### LOGIN
from django.contrib.auth import views as auth_views
from django.urls import path
from . import views
urlpatterns = [
path('test/open', views.TestOpenView.as_view(), name='test-open'),
path('test/closed', views.TestClosedView.as_view(), name='test-closed'),
path('login/', auth_views.LoginView.as_view(template_name='login.html'), name='login'),
path('logout/', views.custom_logout, name='logout'),
path("token/", TokenObtainPairView.as_view(), name='token_obtain_pair'),
path("token/refresh/", TokenRefreshView.as_view(), name='token_refresh'),
]
"""
TODO: Add this !!!
"""
from rest_framework import status
from rest_framework.views import APIView
from rest_framework import permissions
# from rest_framework.permissions import IsAuthenticated
from rest_framework.renderers import JSONRenderer
from rest_framework_simplejwt.authentication import JWTAuthentication
from django.views.decorators.http import require_GET
from django.contrib.auth import logout
from django.shortcuts import redirect
from django.http import JsonResponse
class TestOpenView(APIView):
"""Class for testing an end-point without authentication.
"""
permission_classes = [permissions.AllowAny]
def get(self, request=None, format=None):
"""Method for dealing with the GET requests done at this view.
Parameters
----------
request: rest_framework.request.Request
The parameters from the GET request.
format: None
If some format was sent.
Returns
-------
rest_framework.response.Response
The response object.
"""
ret_dict = {
"error": False,
"message": "This is the auth test open end-point"
}
return JsonResponse(ret_dict, status=status.HTTP_200_OK)
class TestClosedView(APIView):
"""Class for testing the authentication.
"""
# permission_classes = [IsAuthenticated]
authentication_classes = [JWTAuthentication]
renderer_classes = [JSONRenderer]
def get(self, request=None, format=None):
"""Method for dealing with the GET requests done at this view.
Parameters
----------
request: rest_framework.request.Request
The parameters from the GET request.
format: None
If some format was sent.
Returns
-------
rest_framework.response.Response
The response object.
"""
ret_dict = {
"error": False,
"message": "You are authenticated"
}
return JsonResponse(ret_dict, status=status.HTTP_200_OK)
# from rest_framework.response import Response
@require_GET
def custom_logout(request):
"""Method for logging out from django.
Parameters
----------
request: rest_framework.request.Request
The parameters from the GET request.
Returns
-------
redirect:
Redirects to the login page.
"""
logout(request)
# return HttpResponse("You have been logged out.") # Temporary for debugging
return redirect('/auth/login/')
"""
ASGI config for backend project.
It exposes the ASGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/5.1/howto/deployment/asgi/
"""
import os
from django.core.asgi import get_asgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "backend.settings")
application = get_asgi_application()
"""
Django settings for myproject project.
Generated by 'django-admin startproject' using Django 5.1.6.
For more information on this file, see
https://docs.djangoproject.com/en/5.1/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/5.1/ref/settings/
"""
import os
from pathlib import Path
from datetime import timedelta
from dotenv import load_dotenv
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/5.1/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = "django-insecure-9^f+%n36vxg-^q-iu1$x4&+--&u+i4ds@!xhe@+i8w(-wg00bu"
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
# ALLOWED_HOSTS = []
ALLOWED_HOSTS = ['*']
###
### LOAD VARIABLES
###
# Try loading from the .env file, if it exists...
load_dotenv()
try:
DEFAULT_TOKEN_EXPIRE_MIN = int(os.getenv("DEFAULT_TOKEN_EXPIRE_MIN"))
except Exception:
DEFAULT_TOKEN_EXPIRE_MIN = 10080
try:
DEFAULT_TOKEN_REFRESH_DAYS = int(os.getenv("DEFAULT_TOKEN_REFRESH_DAYS"))
except Exception:
DEFAULT_TOKEN_REFRESH_DAYS = 7
try:
fetched = int(os.getenv("DEFAULT_DJANGO_DEBUG"))
if fetched in ('YES', 'yes', 'true', 'True', 'TRUE'):
DEFAULT_DJANGO_DEBUG = True
else:
DEFAULT_DJANGO_DEBUG = False
except Exception:
DEFAULT_DJANGO_DEBUG = False
print("\n---> DJANGO VARIABLES")
print(f"DEFAULT_TOKEN_EXPIRE_MIN: {DEFAULT_TOKEN_EXPIRE_MIN}")
print(f"DEFAULT_TOKEN_REFRESH_DAYS: {DEFAULT_TOKEN_REFRESH_DAYS}")
print(f"DEFAULT_DJANGO_DEBUG: {DEFAULT_DJANGO_DEBUG}")
print("<---DJANGO VARIABLES\n")
# Application definition
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
### ADDED
"rest_framework",
### SWAGGER
"drf_yasg",
### JWT TOKEN
"rest_framework_simplejwt",
### SSL
"sslserver",
### MY STUFF
"shared_models",
"api",
"api_auth",
"api_admin",
]
###
### AUTH
###
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated', # Require authentication for all endpoints
],
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication',
),
}
SESSION_ENGINE = "django.contrib.sessions.backends.db"
LOGIN_REDIRECT_URL = '/swagger/' # Redirect here after login
LOGIN_URL = '/auth/login/' # The URL to redirect to for login
LOGOUT_REDIRECT_URL = '/auth/login/' # Redirect here after logout
###
### TOKEN
###
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=DEFAULT_TOKEN_EXPIRE_MIN),
'SLIDING_TOKEN_REFRESH_LIFETIME': timedelta(days=DEFAULT_TOKEN_REFRESH_DAYS),
'SLIDING_TOKEN_LIFETIME': timedelta(days=30),
'SLIDING_TOKEN_REFRESH_LIFETIME_LATE_USER': timedelta(days=3),
'SLIDING_TOKEN_LIFETIME_LATE_USER': timedelta(days=30),
}
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
###
### ADDED
###
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = "backend.urls"
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [],
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
"django.template.context_processors.debug",
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
],
},
},
]
WSGI_APPLICATION = "backend.wsgi.application"
# Database
# https://docs.djangoproject.com/en/5.1/ref/settings/#databases
DATABASES = {
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": BASE_DIR / "db.sqlite3",
}
}
# Password validation
# https://docs.djangoproject.com/en/5.1/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
},
{
"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
},
{
"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
},
{
"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
},
]
# Internationalization
# https://docs.djangoproject.com/en/5.1/topics/i18n/
LANGUAGE_CODE = "en-us"
# TIME_ZONE = "UTC"
TIME_ZONE = 'Europe/Berlin'
USE_I18N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/5.1/howto/static-files/
STATIC_URL = "static/"
# Default primary key field type
# https://docs.djangoproject.com/en/5.1/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
"""
URL configuration for backend project.
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/5.1/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from rest_framework import permissions
from drf_yasg.views import get_schema_view
from drf_yasg import openapi
from django.contrib import admin
from django.urls import path, include
schema_view = get_schema_view(
openapi.Info(
title="c3buttons",
default_version='1.0.0',
description="Swagger Documentation for c3buttons",
# terms_of_service="https://link.to.something",
contact=openapi.Contact(name="fejao", email="dont@bug.me"),
license=openapi.License(name="MIT"),
),
### AUTH
public=False,
permission_classes=(permissions.IsAuthenticated,),
)
urlpatterns = [
path("admin/", admin.site.urls),
###
### SWAGGER
###
path('swagger/', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'),
path('swagger.json/', schema_view.without_ui(cache_timeout=0), name='schema-json'),
###
### APPS
###
path('auth/', include('api_auth.urls')),
# path("api/box/", include("api.urls")),
path("api/", include("api.urls")),
path("api-admin/", include("api_admin.urls")),
]
"""
WSGI config for backend project.
It exposes the WSGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/5.1/howto/deployment/wsgi/
"""
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "backend.settings")
application = get_wsgi_application()