-
Notifications
You must be signed in to change notification settings - Fork 3.9k
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
feat: add import taxonomy endpoint #33663
Changes from 3 commits
dad3503
13c7ecc
4eb0ad2
553ada0
a123c21
3a2e3f8
805e76d
ea67de1
ad20000
1b65728
a8d0c9e
9913e78
3c1a9d0
7c30a56
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -2,8 +2,14 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Tagging Org API Views | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from django.http import HttpResponse, HttpResponseBadRequest | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from openedx_tagging.core.tagging import rules as oel_tagging_rules | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from openedx_tagging.core.tagging.rest_api.v1.views import ObjectTagView, TaxonomyView | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from openedx_tagging.core.tagging.rest_api.v1.serializers import TaxonomyImportBodySerializer, TaxonomyImportNewBodySerializer | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from openedx_tagging.core.tagging.import_export.api import get_last_import_log, import_tags | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from rest_framework.decorators import action | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from rest_framework.exceptions import PermissionDenied | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from rest_framework.request import Request | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from ...api import ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
create_taxonomy, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -61,6 +67,79 @@ def perform_create(self, serializer): | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
user_admin_orgs = get_admin_orgs(self.request.user) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
serializer.instance = create_taxonomy(**serializer.validated_data, orgs=user_admin_orgs) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@action(detail=False, url_path="import", methods=["post"]) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def create_import(self, request: Request, **_kwargs) -> HttpResponse: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Creates 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"] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# ToDo: This code is temporary | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# In the future, the orgs parameter will be defined in the request body from the frontend | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# See: https://github.com/openedx/modular-learning/issues/116 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if oel_tagging_rules.is_taxonomy_admin(request.user): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
orgs = None | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
else: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
orgs = get_admin_orgs(request.user) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
taxonomy = create_taxonomy(taxonomy_name, taxonomy_description, orgs=orgs) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
try: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import_success = import_tags(taxonomy, file, parser_format) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if import_success: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return HttpResponse(status=200) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
else: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import_error = get_last_import_log(taxonomy) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
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: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Creates 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 = TaxonomyImportBodySerializer(data=request.data) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
body.is_valid(raise_exception=True) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
file = body.validated_data["file"].file | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
parser_format = body.validated_data["parser_format"] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# ToDo: This code is temporary | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# In the future, the orgs parameter will be defined in the request body from the frontend | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# See: https://github.com/openedx/modular-learning/issues/116 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if oel_tagging_rules.is_taxonomy_admin(request.user): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
orgs = None | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
else: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
orgs = get_admin_orgs(request.user) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
taxonomy = self.get_object() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
try: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import_success = import_tags(taxonomy, file, parser_format) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if import_success: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return HttpResponse(status=200) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
else: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import_error = get_last_import_log(taxonomy) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return HttpResponseBadRequest(import_error) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
except ValueError as e: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return HttpResponseBadRequest(e) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
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. Can this whole method can go away? I think the parent
Suggested change
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. Done ea67de1! |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
class ObjectTagOrgView(ObjectTagView): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now that the parent
TaxonomyView
returns the created taxonomy, we can do this with less duplicated code:There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure about this one @pomegranited.
We are preventing some code duplication in the
View
but duplicating the logic of theedx-platform/create_taxonomy
.It will be a pain if our
create_taxonomy
gets complicated. Or we will get in trouble if we change some behavior from theoel_tagging/create_taxonomy
.Do you think it is ok to leave the duplicated
create_import
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@rpenido I don't think we should be writing/maintaining more code than we need..
@bradenmacdonald , could we get a 2nd opinion here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like @pomegranited's suggestion; it re-uses more code. If we're going to have a separate "create_import" function at all, we should aim to keep it as small as possible, just calling the other create and import functions.
The content_tagging version of
create_taxonomy
is only two lines of code so it's fine to duplicate it here. Just make sure to add comments explaining everything and any concerns about that.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the discussion! 😄
Done here: 1b65728