This commit adds validation for course advanced settings. Currently when course
administrators make invalid changes in the Settings/Advanced Settings tab,
they're not notified through a new modal window of the list of invalid settings
changes.
* Extending CourseMetadata
- Previously, we only had update_from_json method in CourseMetadata.py,
and it was only validating one field every POST request.
- Now we have validate_and_update_from_json method that encapsulates the
functionality of update_from_json into a validation call
- To avoid discrepancy of validation standards between modules, validation
uses the from_json method implemented to each field in xblock.
* Different Response in advanced settings ajax requests
- After receiving a POST ajax request, course.py calls
validate_and_update_from_json, and sends a json object of either:
1) valid course metadata model
2) error objects
* Error Messages shown in validation-error-modal
- error objects passed through ajax are shown in a separate modal.
66 lines
2.5 KiB
Python
66 lines
2.5 KiB
Python
from functools import wraps
|
|
import json
|
|
from django.core.serializers import serialize
|
|
from django.core.serializers.json import DjangoJSONEncoder
|
|
from django.db.models.query import QuerySet
|
|
from django.http import HttpResponse, HttpResponseBadRequest
|
|
|
|
|
|
def expect_json(view_function):
|
|
"""
|
|
View decorator for simplifying handing of requests that expect json. If the request's
|
|
CONTENT_TYPE is application/json, parses the json dict from request.body, and updates
|
|
request.POST with the contents.
|
|
"""
|
|
@wraps(view_function)
|
|
def parse_json_into_request(request, *args, **kwargs):
|
|
# cdodge: fix postback errors in CMS. The POST 'content-type' header can include additional information
|
|
# e.g. 'charset', so we can't do a direct string compare
|
|
if "application/json" in request.META.get('CONTENT_TYPE', '') and request.body:
|
|
request.json = json.loads(request.body)
|
|
else:
|
|
request.json = {}
|
|
|
|
return view_function(request, *args, **kwargs)
|
|
|
|
return parse_json_into_request
|
|
|
|
|
|
class JsonResponse(HttpResponse):
|
|
"""
|
|
Django HttpResponse subclass that has sensible defaults for outputting JSON.
|
|
"""
|
|
def __init__(self, object=None, status=None, encoder=DjangoJSONEncoder,
|
|
*args, **kwargs):
|
|
if object in (None, ""):
|
|
content = ""
|
|
status = status or 204
|
|
elif isinstance(object, QuerySet):
|
|
content = serialize('json', object)
|
|
else:
|
|
content = json.dumps(object, cls=encoder, indent=2, ensure_ascii=False)
|
|
kwargs.setdefault("content_type", "application/json")
|
|
if status:
|
|
kwargs["status"] = status
|
|
super(JsonResponse, self).__init__(content, *args, **kwargs)
|
|
|
|
|
|
class JsonResponseBadRequest(HttpResponseBadRequest):
|
|
"""
|
|
Subclass of HttpResponseBadRequest that defaults to outputting JSON.
|
|
Use this to send BadRequestResponse & some Json object along with it.
|
|
|
|
Defaults:
|
|
dictionary: empty dictionary
|
|
status: 400
|
|
encoder: DjangoJSONEncoder
|
|
"""
|
|
def __init__(self, obj=None, status=400, encoder=DjangoJSONEncoder, *args, **kwargs):
|
|
if obj in (None, ""):
|
|
content = ""
|
|
else:
|
|
content = json.dumps(obj, cls=encoder, indent=2, ensure_ascii=False)
|
|
kwargs.setdefault("content_type", "application/json")
|
|
kwargs["status"] = status
|
|
super(JsonResponseBadRequest, self).__init__(content, *args, **kwargs)
|