Templated routes/views to be fulfilled. Added dotenv functionality. Updated requirements.
parent
37b589a664
commit
7afe1045c4
|
@ -1,2 +1,4 @@
|
|||
*/__pycache__/
|
||||
|
||||
/books
|
||||
/covers
|
Binary file not shown.
Binary file not shown.
|
@ -21,16 +21,16 @@ from .views.books import BooksView
|
|||
from .views.books_bookid import BooksBookidView
|
||||
from .views.books_bookid_export import BooksBookidExportView
|
||||
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
|
||||
|
||||
urlpatterns = [
|
||||
# path("admin/", admin.site.urls),
|
||||
# path("api-auth/", include("rest_framework.urls")),
|
||||
path("books", BooksView.as_view()),
|
||||
path("books/<str:bookId>", BooksBookidView.as_view()),
|
||||
path("books/<str:bookId>/export", BooksBookidExportView.as_view()),
|
||||
path("books/<str:bookId>/images", BooksBookidImagesView.as_view()),
|
||||
path("books/<str:bookId>/<str:src>", BooksBookidSrcView.as_view()),
|
||||
path("books/<str:bookid>", BooksBookidView.as_view()),
|
||||
path("books/<str:bookid>/export", BooksBookidExportView.as_view()),
|
||||
path("books/<str:bookid>/images", BooksBookidImagesView.as_view()),
|
||||
path("books/<str:bookid>/<str:src>", BooksBookidImageView.as_view()),
|
||||
path("images/<str:hash>", ImagesHashView.as_view()),
|
||||
]
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -8,23 +8,55 @@ from django.core.files.base import ContentFile
|
|||
from uuid import uuid4
|
||||
|
||||
|
||||
class BookSerializer(serializers.Serializer):
|
||||
title = serializers.CharField()
|
||||
description = serializers.CharField()
|
||||
cover = serializers.ImageField()
|
||||
file = serializers.FileField()
|
||||
class GetBooksSerializer(serializers.Serializer):
|
||||
titleQ = serializers.CharField(required=False)
|
||||
authorQ = serializers.CharField(required=False)
|
||||
sortBy = serializers.ChoiceField(choices=['title', 'author'], style={'base_template': 'radio.html'}, default = 'title')
|
||||
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):
|
||||
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):
|
||||
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):
|
||||
# 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():
|
||||
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
||||
validated_data = serializer.validated_data
|
||||
|
@ -41,7 +73,7 @@ class BooksView(APIView):
|
|||
|
||||
# TODO: ensure book has valid root html file
|
||||
|
||||
# TODO: start analyzing book
|
||||
# TODO: analyze book and images, store them in database
|
||||
|
||||
# save cover image
|
||||
covers_path = "./covers/"
|
||||
|
|
|
@ -7,17 +7,96 @@ from django.core.files.storage import default_storage
|
|||
from django.core.files.base import ContentFile
|
||||
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):
|
||||
parser_classes = (FormParser, MultiPartParser)
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
return Response({"TODO": "TODO"}, status=status.HTTP_200_OK)
|
||||
serializer_class = UpdateBookSerialzer
|
||||
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):
|
||||
return Response({"TODO": "TODO"}, status=status.HTTP_200_OK)
|
||||
def get(self, request, *args, **kwargs):
|
||||
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):
|
||||
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):
|
||||
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)
|
||||
|
|
|
@ -7,8 +7,19 @@ from django.core.files.storage import default_storage
|
|||
from django.core.files.base import ContentFile
|
||||
from uuid import uuid4
|
||||
|
||||
class ExportBookSerializer(serializers.Serializer):
|
||||
bookid = serializers.CharField(required=True)
|
||||
|
||||
class BooksBookidExportView(APIView):
|
||||
parser_classes = (FormParser, MultiPartParser)
|
||||
serializer_class = ExportBookSerializer
|
||||
|
||||
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)
|
||||
|
|
|
@ -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)
|
|
@ -7,8 +7,19 @@ from django.core.files.storage import default_storage
|
|||
from django.core.files.base import ContentFile
|
||||
from uuid import uuid4
|
||||
|
||||
class ImagesFromBookSerializer(serializers.Serializer):
|
||||
bookid = serializers.CharField(required=True)
|
||||
|
||||
class BooksBookidImagesView(APIView):
|
||||
parser_classes = (FormParser, MultiPartParser)
|
||||
serializer_class = ImagesFromBookSerializer
|
||||
|
||||
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)
|
||||
|
|
|
@ -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)
|
|
@ -7,8 +7,20 @@ from django.core.files.storage import default_storage
|
|||
from django.core.files.base import ContentFile
|
||||
from uuid import uuid4
|
||||
|
||||
class GetImagesByHashSerializer(serializers.Serializer):
|
||||
hash = serializers.CharField(required=True)
|
||||
|
||||
class ImagesHashView(APIView):
|
||||
parser_classes = (FormParser, MultiPartParser)
|
||||
serializer_class = GetImagesByHashSerializer
|
||||
|
||||
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)
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"""Django's command-line utility for administrative tasks."""
|
||||
import os
|
||||
import sys
|
||||
|
||||
from dotenv import load_dotenv
|
||||
|
||||
def main():
|
||||
"""Run administrative tasks."""
|
||||
|
@ -19,4 +19,5 @@ def main():
|
|||
|
||||
|
||||
if __name__ == '__main__':
|
||||
load_dotenv()
|
||||
main()
|
||||
|
|
58
openapi.yaml
58
openapi.yaml
|
@ -36,6 +36,31 @@ paths:
|
|||
explode: true
|
||||
schema:
|
||||
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
|
||||
in: query
|
||||
description: Max number of books to return.
|
||||
|
@ -164,7 +189,6 @@ paths:
|
|||
$ref: '#/components/schemas/Book'
|
||||
'500':
|
||||
description: Internal Server Error
|
||||
# TODO: POST ROUTE TO UPLOAD NEW BOOK FILE
|
||||
put:
|
||||
tags:
|
||||
- Books
|
||||
|
@ -180,6 +204,32 @@ paths:
|
|||
$ref: '#/components/schemas/Book'
|
||||
'500':
|
||||
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:
|
||||
tags:
|
||||
- Books
|
||||
|
@ -278,7 +328,7 @@ paths:
|
|||
$ref: '#/components/schemas/Image'
|
||||
'500':
|
||||
description: Internal Server Error
|
||||
/books/{bookid}/{src}:
|
||||
/books/{bookid}/image:
|
||||
parameters:
|
||||
- name: bookid
|
||||
in: path
|
||||
|
@ -289,7 +339,7 @@ paths:
|
|||
type: string
|
||||
example: "123e4567-e89b-12d3-a456-426614174000"
|
||||
- name: src
|
||||
in: path
|
||||
in: query
|
||||
description: Src of the image.
|
||||
required: true
|
||||
explode: true
|
||||
|
@ -347,7 +397,7 @@ paths:
|
|||
- Images
|
||||
summary: Re-analyze an image.
|
||||
description: Generate an image's alt-text (written to genAlt field in image object).
|
||||
operationId: analyzeImage
|
||||
operationId: analyzeImageBySrc
|
||||
responses:
|
||||
'200':
|
||||
description: Successful operation
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
django
|
||||
django_rest_framework
|
||||
python-dotenv
|
Loading…
Reference in New Issue