-
Notifications
You must be signed in to change notification settings - Fork 33
feat: add import taxonomy endpoint #112
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 11 commits
c1d5944
05105bc
a6919a1
f030767
4fe2457
06efd55
d400a54
a50e08f
e1b1789
d9950f6
7450737
ae76400
62e2593
a827178
730b73f
4e52c57
a8a0c7e
c4fe95d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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 | ||
|
|
||
|
|
@@ -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, get_last_import_log, import_tags | ||
| from ...import_export.parsers import ParserFormat | ||
| from ...models import Taxonomy | ||
| from ...rules import ObjectTagPermissionItem | ||
|
|
@@ -37,6 +38,8 @@ | |
| ObjectTagUpdateQueryParamsSerializer, | ||
| TagDataSerializer, | ||
| TaxonomyExportQueryParamsSerializer, | ||
| TaxonomyImportBodySerializer, | ||
| TaxonomyImportNewBodySerializer, | ||
| TaxonomyListQueryParamsSerializer, | ||
| TaxonomySerializer, | ||
| TaxonomyTagCreateBodySerializer, | ||
|
|
@@ -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+" | ||
|
|
@@ -239,6 +264,63 @@ 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") | ||
|
pomegranited marked this conversation as resolved.
Outdated
|
||
|
|
||
| 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) | ||
| try: | ||
| import_success = import_tags(taxonomy, file, parser_format) | ||
|
|
||
| if import_success: | ||
| return HttpResponse(status=200) | ||
|
pomegranited marked this conversation as resolved.
Outdated
|
||
| else: | ||
| import_error = get_last_import_log(taxonomy) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm.. This works fine in a serial environment, but if we've got multiple imports happening at the same time, this won't necessarily be the import log we're interested in here. Really, the only way to get that is if we have the task ID after import. But I don't know if it's worth refactoring
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is not as alarming as I made it sound: |
||
| taxonomy.delete() | ||
| return HttpResponseBadRequest(import_error) | ||
| except ValueError as e: | ||
| return HttpResponseBadRequest(e) | ||
|
|
||
| @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") | ||
|
pomegranited marked this conversation as resolved.
Outdated
|
||
|
|
||
| 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() | ||
| try: | ||
| import_success = import_tags(taxonomy, file, parser_format) | ||
|
|
||
| if import_success: | ||
| return HttpResponse(status=200) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ditto here, can we return the Taxonomy on success?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, but I think we will need to revisit this in the future. I think we should return the We will have a cleaner view when implementing the Import inside the Taxonomy Details. And just to make sure: the import inside the Taxonomy Details is not part of this task, right?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Agreed -- ok to just return Taxonomy for now.
Correct, importing tags to an existing taxonomy is covered by openedx/modular-learning#140 |
||
| else: | ||
| import_error = get_last_import_log(taxonomy) | ||
| return HttpResponseBadRequest(import_error) | ||
| except ValueError as e: | ||
| return HttpResponseBadRequest(e) | ||
|
|
||
|
|
||
| @view_auth_classes | ||
| class ObjectTagView( | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.