Skip to content

Commit

Permalink
refactor: import taxonomy view
Browse files Browse the repository at this point in the history
  • Loading branch information
rpenido committed Nov 7, 2023
1 parent d400a54 commit a50e08f
Show file tree
Hide file tree
Showing 7 changed files with 431 additions and 269 deletions.
20 changes: 0 additions & 20 deletions openedx_tagging/core/tagging/import_export/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,32 +48,12 @@

from django.utils.translation import gettext as _

from .. import api as taxonomy_api
from ..models import TagImportTask, TagImportTaskState, Taxonomy
from .exceptions import TagImportError
from .import_plan import TagImportPlan, TagImportTask
from .parsers import ParserFormat, get_parser


def create_taxonomy_and_import_tags(
taxonomy_name: str,
taxonomy_description: str,
file: BytesIO,
parser_format: ParserFormat
) -> bool:
"""
Create a taxonomy and import the tags from `file`
"""
taxonomy = taxonomy_api.create_taxonomy(taxonomy_name, taxonomy_description)

import_success = import_tags(taxonomy, file, parser_format)

if not import_success:
taxonomy.delete()

return import_success


def import_tags(
taxonomy: Taxonomy,
file: BytesIO,
Expand Down
9 changes: 7 additions & 2 deletions openedx_tagging/core/tagging/rest_api/v1/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,8 +182,6 @@ class TaxonomyImportBodySerializer(serializers.Serializer): # pylint: disable=a
"""
Serializer of the body for the Taxonomy Import action
"""
taxonomy_name = serializers.CharField(required=True)
taxonomy_description = serializers.CharField(default="")
file = serializers.FileField(required=True)

def validate(self, data):
Expand All @@ -198,3 +196,10 @@ def validate(self, data):

data['parser_format'] = parser_format
return data

class TaxonomyImportNewBodySerializer(TaxonomyImportBodySerializer): # pylint: disable=abstract-method
"""
Serializer of the body for the Taxonomy Create and Import action
"""
taxonomy_name = serializers.CharField(required=True)
taxonomy_description = serializers.CharField(default="")
5 changes: 0 additions & 5 deletions openedx_tagging/core/tagging/rest_api/v1/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,4 @@
views_import.TemplateView.as_view(),
name="taxonomy-import-template",
),
path(
"import/",
views_import.ImportView.as_view(),
name="taxonomy-import",
),
]
80 changes: 78 additions & 2 deletions openedx_tagging/core/tagging/rest_api/v1/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@
from __future__ import annotations

from django.db import models
from django.http import Http404, HttpResponse
from django.http import Http404, HttpResponse, HttpResponseBadRequest
from rest_framework import mixins, status
from rest_framework.decorators import action
from rest_framework.exceptions import MethodNotAllowed, PermissionDenied, ValidationError
from rest_framework.generics import ListAPIView, RetrieveUpdateDestroyAPIView
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.viewsets import GenericViewSet, ModelViewSet

Expand All @@ -24,7 +25,7 @@
update_tag_in_taxonomy,
)
from ...data import TagDataQuerySet
from ...import_export.api import export_tags
from ...import_export.api import export_tags, import_tags
from ...import_export.parsers import ParserFormat
from ...models import Taxonomy
from ...rules import ObjectTagPermissionItem
Expand All @@ -37,6 +38,8 @@
ObjectTagUpdateQueryParamsSerializer,
TagDataSerializer,
TaxonomyExportQueryParamsSerializer,
TaxonomyImportBodySerializer,
TaxonomyImportNewBodySerializer,
TaxonomyListQueryParamsSerializer,
TaxonomySerializer,
TaxonomyTagCreateBodySerializer,
Expand Down Expand Up @@ -164,7 +167,29 @@ class TaxonomyView(ModelViewSet):
* 400 - Invalid query parameter
* 403 - Permission denied
**Import/Create Taxonomy Example Requests**
POST /tagging/rest_api/v1/taxonomy/import/
{
"taxonomy_name": "Taxonomy Name",
"taxonomy_description": "This is a description",
"file": <file>,
}
**Import/Create Taxonomy Query Returns**
* 200 - Success
* 400 - Bad request
* 403 - Permission denied
**Import/Update Taxonomy Example Requests**
PUT /tagging/rest_api/v1/taxonomy/:pk/tags/import/
{
"file": <file>,
}
**Import/Update Taxonomy Query Returns**
* 200 - Success
* 400 - Bad request
* 403 - Permission denied
"""

lookup_value_regex = r"\d+"
Expand Down Expand Up @@ -239,6 +264,57 @@ def export(self, request, **_kwargs) -> HttpResponse:

return HttpResponse(tags, content_type=content_type)

@action(detail=False, url_path="import", methods=["post"])
def create_import(self, request: Request, **_kwargs) -> HttpResponse:
"""
Create a new taxonomy and imports the tags from the uploaded file.
"""
perm = "oel_tagging.import_taxonomy"
if not request.user.has_perm(perm):
raise PermissionDenied("You do not have permission to import taxonomies")

body = TaxonomyImportNewBodySerializer(data=request.data)
body.is_valid(raise_exception=True)

taxonomy_name = body.validated_data["taxonomy_name"]
taxonomy_description = body.validated_data["taxonomy_description"]
file = body.validated_data["file"].file
parser_format = body.validated_data["parser_format"]

taxonomy = create_taxonomy(taxonomy_name, taxonomy_description)
import_success = import_tags(taxonomy, file, parser_format)

if import_success:
return HttpResponse(status=200)
else:
import_error = "Error importing taxonomy" # ToDo: Get actual error message
taxonomy.delete()
return HttpResponseBadRequest(import_error)

@action(detail=True, url_path="tags/import", methods=["put"])
def update_import(self, request: Request, **_kwargs) -> HttpResponse:
"""
Imports tags from the uploaded file to an already created taxonomy.
"""
perm = "oel_tagging.import_taxonomy"
if not request.user.has_perm(perm):
raise PermissionDenied("You do not have permission to import taxonomies")

body = TaxonomyImportBodySerializer(data=request.data)
body.is_valid(raise_exception=True)

file = body.validated_data["file"].file
parser_format = body.validated_data["parser_format"]

taxonomy = self.get_object()
import_success = import_tags(taxonomy, file, parser_format)

if import_success:
return HttpResponse(status=200)
else:
import_error = "Error importing taxonomy" # ToDo: Get actual error message
return HttpResponseBadRequest(import_error)


@view_auth_classes
class ObjectTagView(
Expand Down
54 changes: 1 addition & 53 deletions openedx_tagging/core/tagging/rest_api/v1/views_import.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,10 @@

import os

from django.http import FileResponse, Http404, HttpResponse, HttpResponseBadRequest
from rest_framework.exceptions import PermissionDenied
from django.http import FileResponse, Http404
from rest_framework.request import Request
from rest_framework.views import APIView

from ...import_export import api
from .serializers import TaxonomyImportBodySerializer


class TemplateView(APIView):
"""
Expand Down Expand Up @@ -53,51 +49,3 @@ def get(self, request: Request, file_ext: str, *args, **kwargs) -> FileResponse:
response = FileResponse(fh, content_type=content_type)
response['Content-Disposition'] = content_disposition
return response


class ImportView(APIView):
"""
View to import taxonomies
**Example Requests**
POST /tagging/rest_api/v1/import/
{
"taxonomy_name": "Taxonomy Name",
"taxonomy_description": "This is a description",
"file": <file>,
}
**Query Returns**
* 200 - Success
* 400 - Bad request
* 405 - Method not allowed
"""
http_method_names = ['post']

def post(self, request: Request, *args, **kwargs) -> HttpResponse:
"""
Imports the taxonomy from the uploaded file.
"""
perm = "oel_tagging.import_taxonomy"
if not request.user.has_perm(perm):
raise PermissionDenied("You do not have permission to import taxonomies")

body = TaxonomyImportBodySerializer(data=request.data)
body.is_valid(raise_exception=True)

taxonomy_name = body.validated_data["taxonomy_name"]
taxonomy_description = body.validated_data["taxonomy_description"]
file = body.validated_data["file"].file
parser_format = body.validated_data["parser_format"]

import_success = api.create_taxonomy_and_import_tags(
taxonomy_name=taxonomy_name,
taxonomy_description=taxonomy_description,
file=file,
parser_format=parser_format,
)

if import_success:
return HttpResponse(status=200)
else:
return HttpResponseBadRequest("Error importing taxonomy")
Loading

0 comments on commit a50e08f

Please sign in to comment.