Templated routes/views to be fulfilled. Added dotenv functionality. Updated requirements.

tyler
xxmistacruzxx 2024-02-09 14:11:31 -05:00
parent 37b589a664
commit 7afe1045c4
22 changed files with 302 additions and 49 deletions

0
.env Normal file
View File

2
.gitignore vendored
View File

@ -1,2 +1,4 @@
*/__pycache__/
/books /books
/covers /covers

View File

@ -21,16 +21,16 @@ from .views.books import BooksView
from .views.books_bookid import BooksBookidView from .views.books_bookid import BooksBookidView
from .views.books_bookid_export import BooksBookidExportView from .views.books_bookid_export import BooksBookidExportView
from .views.books_bookid_images import BooksBookidImagesView from .views.books_bookid_images import BooksBookidImagesView
from .views.books_bookid_src import BooksBookidSrcView from .views.books_bookid_image import BooksBookidImageView
from .views.images_hash import ImagesHashView from .views.images_hash import ImagesHashView
urlpatterns = [ urlpatterns = [
# path("admin/", admin.site.urls), # path("admin/", admin.site.urls),
# path("api-auth/", include("rest_framework.urls")), # path("api-auth/", include("rest_framework.urls")),
path("books", BooksView.as_view()), path("books", BooksView.as_view()),
path("books/<str:bookId>", BooksBookidView.as_view()), path("books/<str:bookid>", BooksBookidView.as_view()),
path("books/<str:bookId>/export", BooksBookidExportView.as_view()), path("books/<str:bookid>/export", BooksBookidExportView.as_view()),
path("books/<str:bookId>/images", BooksBookidImagesView.as_view()), path("books/<str:bookid>/images", BooksBookidImagesView.as_view()),
path("books/<str:bookId>/<str:src>", BooksBookidSrcView.as_view()), path("books/<str:bookid>/<str:src>", BooksBookidImageView.as_view()),
path("images/<str:hash>", ImagesHashView.as_view()), path("images/<str:hash>", ImagesHashView.as_view()),
] ]

View File

@ -8,23 +8,55 @@ from django.core.files.base import ContentFile
from uuid import uuid4 from uuid import uuid4
class BookSerializer(serializers.Serializer): class GetBooksSerializer(serializers.Serializer):
title = serializers.CharField() titleQ = serializers.CharField(required=False)
description = serializers.CharField() authorQ = serializers.CharField(required=False)
cover = serializers.ImageField() sortBy = serializers.ChoiceField(choices=['title', 'author'], style={'base_template': 'radio.html'}, default = 'title')
file = serializers.FileField() sortOrder = serializers.ChoiceField(choices=['asc', 'desc'], style={'base_template': 'radio.html'}, default = 'asc')
limit = serializers.IntegerField(min_value=1, required=False)
skip = serializers.IntegerField(min_value=0, required=False)
class AddBookSerializer(serializers.Serializer):
title = serializers.CharField(required=True, allow_blank=False)
author = serializers.CharField(required=True, allow_blank=False)
description = serializers.CharField(required=False, allow_blank=True)
file = serializers.FileField(required=True)
cover = serializers.ImageField(required=False)
class BooksView(APIView): class BooksView(APIView):
parser_classes = (FormParser, MultiPartParser) parser_classes = (FormParser, MultiPartParser)
serializer_class = BookSerializer serializer_class = AddBookSerializer
def get_serializer_class(self):
if self.request.method == 'GET':
return GetBooksSerializer
elif self.request.method == 'POST':
return AddBookSerializer
return super().get_serializer_class()
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
return Response({"TODO": "TODO"}, status=status.HTTP_200_OK) serializer_class = self.get_serializer_class()
serializer = serializer_class(data=request.query_params)
if not serializer.is_valid():
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
# Access validated data
validated_data = serializer.validated_data
title_query = validated_data.get('titleQ')
author_query = validated_data.get('authorQ')
sort_by = validated_data.get('sortBy')
sort_order = validated_data.get('sortOrder')
limit = validated_data.get('limit')
skip = validated_data.get('skip')
# TODO: perform logic
# TODO: return books
return Response(validated_data, status=status.HTTP_200_OK)
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
# validate request data # validate request data
serializer = self.serializer_class(data=request.data) serializer_class = self.get_serializer_class()
serializer = serializer_class(data=request.data)
if not serializer.is_valid(): if not serializer.is_valid():
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
validated_data = serializer.validated_data validated_data = serializer.validated_data
@ -41,7 +73,7 @@ class BooksView(APIView):
# TODO: ensure book has valid root html file # TODO: ensure book has valid root html file
# TODO: start analyzing book # TODO: analyze book and images, store them in database
# save cover image # save cover image
covers_path = "./covers/" covers_path = "./covers/"

View File

@ -7,17 +7,96 @@ from django.core.files.storage import default_storage
from django.core.files.base import ContentFile from django.core.files.base import ContentFile
from uuid import uuid4 from uuid import uuid4
class GetBookSerializer(serializers.Serializer):
bookid = serializers.CharField(required=True)
class UpdateBookSerialzer(serializers.Serializer):
bookid = serializers.CharField(required=True)
title = serializers.CharField(required=False, allow_blank=False)
author = serializers.CharField(required=False, allow_blank=False)
description = serializers.CharField(required=False, allow_blank=True)
cover = serializers.ImageField(required=False)
class AnalyzeBookSerializer(serializers.Serializer):
bookid = serializers.CharField(required=True)
class OverwriteBookSerializer(serializers.Serializer):
bookid = serializers.CharField(required=True)
file = serializers.FileField(required=True)
class DeleteBookSerializer(serializers.Serializer):
bookid = serializers.CharField(required=True)
class BooksBookidView(APIView): class BooksBookidView(APIView):
parser_classes = (FormParser, MultiPartParser) parser_classes = (FormParser, MultiPartParser)
def get(self, request, *args, **kwargs): serializer_class = UpdateBookSerialzer
return Response({"TODO": "TODO"}, status=status.HTTP_200_OK) def get_serializer_class(self):
if self.request.method == 'GET':
return GetBookSerializer
elif self.request.method == 'PATCH':
return UpdateBookSerialzer
elif self.request.method == 'PUT':
return AnalyzeBookSerializer
elif self.request.method == 'DELETE':
return DeleteBookSerializer
return super().get_serializer_class()
def post(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
return Response({"TODO": "TODO"}, status=status.HTTP_200_OK) serializer_class = self.get_serializer_class()
serializer = serializer_class(data={"bookid": kwargs.get('bookid')})
if not serializer.is_valid():
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
validated_data = serializer.validated_data
# TODO: IMPLEMENT LOGIC
return Response(validated_data, status=status.HTTP_200_OK)
def patch(self, request, *args, **kwargs):
serializer_class = self.get_serializer_class()
data = request.data
data['bookid'] = kwargs.get('bookid')
serializer = serializer_class(data=data)
if not serializer.is_valid():
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
validated_data = serializer.validated_data
# TODO: IMPLEMENT LOGIC
return Response(validated_data, status=status.HTTP_200_OK)
def put(self, request, *args, **kwargs): def put(self, request, *args, **kwargs):
return Response({"TODO": "TODO"}, status=status.HTTP_200_OK) serializer_class = self.get_serializer_class()
serializer = serializer_class(data={"bookid": kwargs.get('bookid')})
if not serializer.is_valid():
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
validated_data = serializer.validated_data
# TODO: IMPLEMENT LOGIC
return Response(validated_data, status=status.HTTP_200_OK)
def post(self, request, *args, **kwargs):
serializer_class = self.get_serializer_class()
data = request.data
data['bookid'] = kwargs.get('bookid')
serializer = serializer_class(data=request.data)
if not serializer.is_valid():
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
validated_data = serializer.validated_data
# TODO: IMPLEMENT LOGIC
return Response(validated_data, status=status.HTTP_200_OK)
def delete(self, request, *args, **kwargs): def delete(self, request, *args, **kwargs):
return Response({"TODO": "TODO"}, status=status.HTTP_200_OK) serializer_class = self.get_serializer_class()
serializer = serializer_class(data={"bookid": kwargs.get('bookid')})
if not serializer.is_valid():
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
validated_data = serializer.validated_data
# TODO: IMPLEMENT LOGIC
return Response(validated_data, status=status.HTTP_200_OK)

View File

@ -7,8 +7,19 @@ from django.core.files.storage import default_storage
from django.core.files.base import ContentFile from django.core.files.base import ContentFile
from uuid import uuid4 from uuid import uuid4
class ExportBookSerializer(serializers.Serializer):
bookid = serializers.CharField(required=True)
class BooksBookidExportView(APIView): class BooksBookidExportView(APIView):
parser_classes = (FormParser, MultiPartParser) parser_classes = (FormParser, MultiPartParser)
serializer_class = ExportBookSerializer
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
return Response({"TODO": "TODO"}, status=status.HTTP_200_OK) serializer = self.serializer_class(data={"bookid": kwargs.get('bookid')})
if not serializer.is_valid():
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
validated_data = serializer.validated_data
# TODO: IMPLEMENT LOGIC
return Response(validated_data, status=status.HTTP_200_OK)

View File

@ -0,0 +1,74 @@
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status, permissions, serializers
from rest_framework.exceptions import ValidationError
from rest_framework.parsers import FormParser, MultiPartParser
from django.core.files.storage import default_storage
from django.core.files.base import ContentFile
from uuid import uuid4
class GetImageBySrc(serializers.Serializer):
bookid = serializers.CharField(required=True)
src = serializers.CharField(required=True)
class UpdateImageBySrc(serializers.Serializer):
bookid = serializers.CharField(required=True)
src = serializers.CharField(required=True)
alt = serializers.CharField(required=True)
beforeContext = serializers.CharField(required=False)
afterContext = serializers.CharField(required=False)
class AnalyzeImageBySrc(serializers.Serializer):
bookid = serializers.CharField(required=True)
src = serializers.CharField(required=True)
class BooksBookidImageView(APIView):
parser_classes = (FormParser, MultiPartParser)
def get_serializer_class(self):
if self.request.method == 'GET':
return GetImageBySrc
elif self.request.method == 'PATCH':
return UpdateImageBySrc
elif self.request.method == 'PUT':
return AnalyzeImageBySrc
return super().get_serializer_class()
def get(self, request, *args, **kwargs):
serializer_class = self.get_serializer_class()
data = request.query_params
data['bookid'] = kwargs.get('bookid')
serializer = serializer_class(data=data)
if not serializer.is_valid():
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
validated_data = serializer.validated_data
# TODO: IMPLEMENT LOGIC
return Response(validated_data, status=status.HTTP_200_OK)
def patch(self, request, *args, **kwargs):
serializer_class = self.get_serializer_class()
data = request.data
data.update(request.query_params)
data['bookid'] = kwargs.get('bookid')
serializer = serializer_class(data=data)
if not serializer.is_valid():
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
validated_data = serializer.validated_data
# TODO: IMPLEMENT LOGIC
return Response(validated_data, status=status.HTTP_200_OK)
def put(self, request, *args, **kwargs):
serializer_class = self.get_serializer_class()
data = request.query_params
data['bookid'] = kwargs.get('bookid')
serializer = serializer_class(data=data)
if not serializer.is_valid():
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
validated_data = serializer.validated_data
# TODO: IMPLEMENT LOGIC
return Response(validated_data, status=status.HTTP_200_OK)

View File

@ -7,8 +7,19 @@ from django.core.files.storage import default_storage
from django.core.files.base import ContentFile from django.core.files.base import ContentFile
from uuid import uuid4 from uuid import uuid4
class ImagesFromBookSerializer(serializers.Serializer):
bookid = serializers.CharField(required=True)
class BooksBookidImagesView(APIView): class BooksBookidImagesView(APIView):
parser_classes = (FormParser, MultiPartParser) parser_classes = (FormParser, MultiPartParser)
serializer_class = ImagesFromBookSerializer
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
return Response({"TODO": "TODO"}, status=status.HTTP_200_OK) serializer = self.serializer_class(data={"bookid": kwargs.get('bookid')})
if not serializer.is_valid():
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
validated_data = serializer.validated_data
# TODO: IMPLEMENT LOGIC
return Response(validated_data, status=status.HTTP_200_OK)

View File

@ -1,20 +0,0 @@
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status, permissions, serializers
from rest_framework.exceptions import ValidationError
from rest_framework.parsers import FormParser, MultiPartParser
from django.core.files.storage import default_storage
from django.core.files.base import ContentFile
from uuid import uuid4
class BooksBookidSrcView(APIView):
parser_classes = (FormParser, MultiPartParser)
def get(self, request, *args, **kwargs):
return Response({"TODO": "TODO"}, status=status.HTTP_200_OK)
def patch(self, request, *args, **kwargs):
return Response({"TODO": "TODO"}, status=status.HTTP_200_OK)
def put(self, request, *args, **kwargs):
return Response({"TODO": "TODO"}, status=status.HTTP_200_OK)

View File

@ -7,8 +7,20 @@ from django.core.files.storage import default_storage
from django.core.files.base import ContentFile from django.core.files.base import ContentFile
from uuid import uuid4 from uuid import uuid4
class GetImagesByHashSerializer(serializers.Serializer):
hash = serializers.CharField(required=True)
class ImagesHashView(APIView): class ImagesHashView(APIView):
parser_classes = (FormParser, MultiPartParser) parser_classes = (FormParser, MultiPartParser)
serializer_class = GetImagesByHashSerializer
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
return Response({"TODO": "TODO"}, status=status.HTTP_200_OK) image_hash = kwargs.get('hash')
data = {'hash': image_hash}
serializer = self.serializer_class(data=data)
if not serializer.is_valid():
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
# TODO: IMPLEMENT LOGIC
return Response(data, status=status.HTTP_200_OK)

View File

@ -2,7 +2,7 @@
"""Django's command-line utility for administrative tasks.""" """Django's command-line utility for administrative tasks."""
import os import os
import sys import sys
from dotenv import load_dotenv
def main(): def main():
"""Run administrative tasks.""" """Run administrative tasks."""
@ -19,4 +19,5 @@ def main():
if __name__ == '__main__': if __name__ == '__main__':
load_dotenv()
main() main()

View File

@ -36,6 +36,31 @@ paths:
explode: true explode: true
schema: schema:
type: string type: string
- name: authorQ
in: query
description: String to match the author to.
required: false
explode: true
schema:
type: string
- name: sortBy
in: query
description: Field to sort by.
required: false
explode: true
schema:
type: string
enum: ["title", "author"]
default: "title"
- name: sortOrder
in: query
description: Order to sort by.
required: false
explode: true
schema:
type: string
enum: ["asc", "desc"]
default: "asc"
- name: limit - name: limit
in: query in: query
description: Max number of books to return. description: Max number of books to return.
@ -164,7 +189,6 @@ paths:
$ref: '#/components/schemas/Book' $ref: '#/components/schemas/Book'
'500': '500':
description: Internal Server Error description: Internal Server Error
# TODO: POST ROUTE TO UPLOAD NEW BOOK FILE
put: put:
tags: tags:
- Books - Books
@ -180,6 +204,32 @@ paths:
$ref: '#/components/schemas/Book' $ref: '#/components/schemas/Book'
'500': '500':
description: Internal Server Error description: Internal Server Error
post:
tags:
- Books
summary: Upload a new book file to a book object.
description: Upload a new book to a given book object (by its id), and re-analyze it (essentially creating a new book, except keeping the same bookid).
operationId: overwriteBook
requestBody:
required: true
content:
multipart/form-data:
schema:
type: object
properties:
book:
type: string
description: Zip file of the book.
format: binary
responses:
'200':
description: Successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/Book'
'500':
description: Internal Server Error
delete: delete:
tags: tags:
- Books - Books
@ -278,7 +328,7 @@ paths:
$ref: '#/components/schemas/Image' $ref: '#/components/schemas/Image'
'500': '500':
description: Internal Server Error description: Internal Server Error
/books/{bookid}/{src}: /books/{bookid}/image:
parameters: parameters:
- name: bookid - name: bookid
in: path in: path
@ -289,7 +339,7 @@ paths:
type: string type: string
example: "123e4567-e89b-12d3-a456-426614174000" example: "123e4567-e89b-12d3-a456-426614174000"
- name: src - name: src
in: path in: query
description: Src of the image. description: Src of the image.
required: true required: true
explode: true explode: true
@ -347,7 +397,7 @@ paths:
- Images - Images
summary: Re-analyze an image. summary: Re-analyze an image.
description: Generate an image's alt-text (written to genAlt field in image object). description: Generate an image's alt-text (written to genAlt field in image object).
operationId: analyzeImage operationId: analyzeImageBySrc
responses: responses:
'200': '200':
description: Successful operation description: Successful operation

View File

@ -1,2 +1,3 @@
django django
django_rest_framework django_rest_framework
python-dotenv