First implementation working

This commit is contained in:
willy 2024-12-22 03:07:07 +01:00
parent 7d2454c3be
commit 551ae8691b
6 changed files with 138041 additions and 7 deletions

View file

@ -1,8 +1,10 @@
# catalog/api_views.py # catalog/api_views.py
from rest_framework import generics from rest_framework import generics
from rest_framework.parsers import MultiPartParser, FormParser from rest_framework.parsers import MultiPartParser, FormParser, JSONParser
from rest_framework.filters import SearchFilter from rest_framework.filters import SearchFilter
from .permissions import IsAuthenticatedOrReadOnly
from .models import Plant from .models import Plant
from .serializers import PlantSerializer from .serializers import PlantSerializer
@ -10,12 +12,14 @@ from .serializers import PlantSerializer
class PlantListCreateAPIView(generics.ListCreateAPIView): class PlantListCreateAPIView(generics.ListCreateAPIView):
queryset = Plant.objects.all() queryset = Plant.objects.all()
serializer_class = PlantSerializer serializer_class = PlantSerializer
parser_classes = [MultiPartParser, FormParser] # Allow file uploads parser_classes = [JSONParser, MultiPartParser, FormParser] # Allow file uploads
filter_backends = [SearchFilter] # Add search filter filter_backends = [SearchFilter] # Add search filter
search_fields = ['name', 'description'] # Search by name and description search_fields = ['name', 'description'] # Search by name and description
permission_classes = [IsAuthenticatedOrReadOnly] # Apply custom permission
# Retrieve, Update, and Delete a Plant # Retrieve, Update, and Delete a Plant
class PlantRetrieveUpdateDestroyAPIView(generics.RetrieveUpdateDestroyAPIView): class PlantRetrieveUpdateDestroyAPIView(generics.RetrieveUpdateDestroyAPIView):
queryset = Plant.objects.all() queryset = Plant.objects.all()
serializer_class = PlantSerializer serializer_class = PlantSerializer
parser_classes = [MultiPartParser, FormParser] # Allow file uploads and form data parser_classes = [JSONParser, MultiPartParser, FormParser] # Allow file uploads and form data
permission_classes = [IsAuthenticatedOrReadOnly] # Apply custom permission

View file

@ -0,0 +1,10 @@
from rest_framework.permissions import SAFE_METHODS, BasePermission
class IsAuthenticatedOrReadOnly(BasePermission):
"""
Allows GET, HEAD, OPTIONS for everyone, but restricts POST, PUT, DELETE to authenticated users.
"""
def has_permission(self, request, view):
if request.method in SAFE_METHODS:
return True # Allow read-only access
return request.user and request.user.is_authenticated

View file

@ -2,10 +2,16 @@
from django.http import HttpResponseRedirect from django.http import HttpResponseRedirect
from django.urls import path from django.urls import path
from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView
from .api_views import PlantListCreateAPIView, PlantRetrieveUpdateDestroyAPIView from .api_views import PlantListCreateAPIView, PlantRetrieveUpdateDestroyAPIView
urlpatterns = [ urlpatterns = [
path('', lambda request: HttpResponseRedirect('/api/plants/')), path('', lambda request: HttpResponseRedirect('/api/plants/')),
path('api/plants/', PlantListCreateAPIView.as_view(), name='plant_list_create'), # List and Create path('api/plants/', PlantListCreateAPIView.as_view(), name='plant_list_create'), # List and Create
path('api/plants/<int:pk>/', PlantRetrieveUpdateDestroyAPIView.as_view(), name='plant_detail_update_delete'), # Retrieve, Update, Delete path('api/plants/<int:pk>/', PlantRetrieveUpdateDestroyAPIView.as_view(), name='plant_detail_update_delete'), # Retrieve, Update, Delete
path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
] ]

File diff suppressed because it is too large Load diff

View file

@ -12,7 +12,6 @@ https://docs.djangoproject.com/en/5.0/ref/settings/
import os import os
from pathlib import Path from pathlib import Path
import logging
# Build paths inside the project like this: BASE_DIR / 'subdir'. # Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent BASE_DIR = Path(__file__).resolve().parent.parent
@ -33,6 +32,18 @@ ALLOWED_HOSTS = ['gonzalohd.eu', 'plantsapi.gonzalohd.eu', 'localhost', '192.168
CSRF_TRUSTED_ORIGINS = [ CSRF_TRUSTED_ORIGINS = [
"https://succulentspectrum.gonzalohd.eu", "https://succulentspectrum.gonzalohd.eu",
"https://plantsapi.gonzalohd.eu",
"http://localhost:5173", # local development URL
]
CORS_ALLOW_HEADERS = [
'authorization',
'content-type',
'accept',
'origin',
'x-requested-with',
'user-agent',
'accept-language',
] ]
@ -63,6 +74,11 @@ MIDDLEWARE = [
'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware',
] ]
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
USE_X_FORWARDED_HOST = True
CORS_ALLOW_ALL_ORIGINS = True # Allow all origins for development CORS_ALLOW_ALL_ORIGINS = True # Allow all origins for development
ROOT_URLCONF = 'plant_catalog.urls' ROOT_URLCONF = 'plant_catalog.urls'
@ -91,6 +107,14 @@ REST_FRAMEWORK = {
), ),
'DEFAULT_PARSER_CLASSES': ( 'DEFAULT_PARSER_CLASSES': (
'rest_framework.parsers.JSONParser', 'rest_framework.parsers.JSONParser',
'rest_framework.parsers.FormParser',
'rest_framework.parsers.MultiPartParser',
),
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_simplejwt.authentication.JWTAuthentication',
),
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
), ),
} }
@ -191,4 +215,4 @@ LOGGING = {
USE_X_FORWARDED_HOST = True

View file

@ -2,6 +2,12 @@ asgiref==3.8.1
Django==5.0.8 Django==5.0.8
django-cors-headers==4.4.0 django-cors-headers==4.4.0
djangorestframework==3.15.2 djangorestframework==3.15.2
djangorestframework-simplejwt==5.3.1
mysqlclient==2.2.4 mysqlclient==2.2.4
pillow==10.4.0 pillow==10.4.0
sqlparse==0.5.1 sqlparse==0.5.1
pip==23.0.1
PyJWT==2.10.0
setuptools==66.1.1
wheel==0.37.0