Advertisement
eduardoperezl

views.py

Jun 2nd, 2016
76
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 11.41 KB | None | 0 0
  1. """Django views implementing the XBlock workbench.
  2.  
  3. This code is in the Workbench layer.
  4.  
  5. """
  6.  
  7. import json
  8. import logging
  9. import mimetypes
  10.  
  11. from django.http import HttpResponse, Http404
  12. from django.shortcuts import redirect, render_to_response
  13. from django.views.decorators.csrf import csrf_exempt, ensure_csrf_cookie
  14.  
  15. from xblock.core import XBlock, XBlockAside
  16. from xblock.django.request import webob_to_django_response, django_to_webob_request
  17. from xblock.exceptions import NoSuchUsage
  18.  
  19. from .models import XBlockState
  20. from .runtime import WorkbenchRuntime, reset_global_state
  21. from .scenarios import get_scenarios
  22. from xblock.plugin import PluginMissingError
  23.  
  24. # Imports for google drive api
  25. import requests
  26. import httplib2
  27. from oauth2client import client
  28. from apiclient import discovery
  29.  
  30. log = logging.getLogger(__name__)
  31. scen_id = 'drivepy.0'
  32.  
  33. # We don't really have authentication and multiple students, just accept their
  34. # id on the URL.
  35. def get_student_id(request):
  36.     """Get the student_id from the given request."""
  37.     student_id = request.GET.get('student', 'student_1')
  38.     return student_id
  39.  
  40.  
  41. # ---- Views -----
  42.  
  43. def index(_request):
  44.     """Render `index.html`"""
  45.     the_scenarios = sorted(get_scenarios().items())
  46.     return render_to_response('workbench/index.html', {
  47.         'scenarios': [(desc, scenario.description) for desc, scenario in the_scenarios]
  48.     })
  49.  
  50.  
  51. @ensure_csrf_cookie
  52. def show_scenario(request, scenario_id, view_name='student_view', template='workbench/block.html'):
  53.     """
  54.    Render the given `scenario_id` for the given `view_name`, on the provided `template`.
  55.  
  56.    `view_name` defaults to 'student_view'.
  57.    `template` defaults to 'block.html'.
  58.  
  59.    """
  60.     if scenario_id == 'drivepy.0':
  61.         scen_id = 'drivepy.0'
  62.     elif scenario_id == 'drivepy.1':
  63.         scen_id = 'drivepy.1'
  64.     else:
  65.         scen_id = ''
  66.  
  67.     if scenario_id == scen_id:
  68.         if 'credentials' not in request.session:
  69.             return redirect('http://drivepython.10.0.2.186.xip.io:8020/oauth2callback')
  70.         credentials = client.OAuth2Credentials.from_json(request.session['credentials'])
  71.         if credentials.access_token_expired:
  72.             return redirect('http://drivepython.10.0.2.186.xip.io:8020/oauth2callback')
  73.         else:
  74.             http_auth = credentials.authorize(httplib2.Http())
  75.             drive_service = discovery.build('drive', 'v3', http_auth)
  76.             files = drive_service.files().list(q="'root' in parents",fields="nextPageToken, files(id, name, mimeType, trashed, webViewLink, fileExtension)").execute()
  77.             items = files.get('files', [])
  78.  
  79.             student_id = get_student_id(request)
  80.             log.info("Start show_scenario %r for student %s", scenario_id, student_id)
  81.  
  82.             try:
  83.                 scenario = get_scenarios()[scenario_id]
  84.             except KeyError:
  85.                 raise Http404
  86.  
  87.             usage_id = scenario.usage_id
  88.             runtime = WorkbenchRuntime(student_id)
  89.             block = runtime.get_block(usage_id)
  90.             render_context = {
  91.                 'activate_block_id': request.GET.get('activate_block_id', None),
  92.                 'files': items
  93.             }
  94.             frag = block.render(view_name, render_context)
  95.             log.info("End show_scenario %s", scenario_id)
  96.             return render_to_response('drivepy/drivepy.html', {
  97.                 'scenario': scenario,
  98.                 'block': block,
  99.                 'body': frag.body_html(),
  100.                 'head_html': frag.head_html(),
  101.                 'foot_html': frag.foot_html(),
  102.                 'student_id': student_id,
  103.                 'files': items
  104.             })
  105.     else:
  106.         student_id = get_student_id(request)
  107.         log.info("Start show_scenario %r for student %s", scenario_id, student_id)
  108.  
  109.         try:
  110.             scenario = get_scenarios()[scenario_id]
  111.         except KeyError:
  112.             raise Http404
  113.  
  114.         usage_id = scenario.usage_id
  115.         runtime = WorkbenchRuntime(student_id)
  116.         block = runtime.get_block(usage_id)
  117.         render_context = {
  118.             'activate_block_id': request.GET.get('activate_block_id', None)
  119.         }
  120.  
  121.         frag = block.render(view_name, render_context)
  122.         log.info("End show_scenario %s", scenario_id)
  123.         return render_to_response(template, {
  124.             'scenario': scenario,
  125.             'block': block,
  126.             'body': frag.body_html(),
  127.             'head_html': frag.head_html(),
  128.             'foot_html': frag.foot_html(),
  129.             'student_id': student_id
  130.         })
  131.  
  132. def user_list(_request):
  133.     """
  134.    This will return a list of all users in the database
  135.    """
  136.     # We'd really like to do .distinct, but sqlite+django does not support this;
  137.     # hence the hack with sorted(set(...))
  138.     users = sorted(
  139.         user_id[0]
  140.         for user_id in set(XBlockState.objects.values_list('user_id'))
  141.     )
  142.     return HttpResponse(
  143.         json.dumps(users, indent=2),
  144.         content_type='application/json',
  145.     )
  146.  
  147. # View for the user authentication
  148. def oauth2callback(request):
  149.     flow = client.flow_from_clientsecrets('/var/www/credentials/client_secrets.json', scope='https://www.googleapis.com/auth/drive', redirect_uri='http://drivepython.10.0.2.186.xip.io:8020/oauth2callback')
  150.     if 'code' not in request.GET:        
  151.         auth_uri = flow.step1_get_authorize_url()
  152.         return redirect(auth_uri)
  153.     else:
  154.         auth_code = request.GET.get('code')
  155.         credentials = flow.step2_exchange(auth_code)
  156.         request.session['credentials'] = credentials.to_json()
  157.         return redirect("http://drivepython.10.0.2.186.xip.io:8020/scenario/"+scen_id)
  158.  
  159. # View for create new File
  160. def new(request):
  161.     credentials = client.OAuth2Credentials.from_json(request.session['credentials'])
  162.     http_auth = credentials.authorize(httplib2.Http())
  163.     drive_service = discovery.build('drive', 'v3', http_auth)
  164.     if 'folder_id' in request.GET:
  165.         folder_id = request.GET.get('folder_id')
  166.     else:
  167.         folder_id = 'root'
  168.  
  169.     # Metadata of the new file to create
  170.     file_metadata = {
  171.     'mimeType' : 'application/vnd.google-apps.'+request.GET.get('type'),
  172.     'parents': [ folder_id ]
  173.     }
  174.  
  175.     # Create New File
  176.     file = drive_service.files().create(body=file_metadata, fields='id, webViewLink').execute()
  177.     file_url = file.get("webViewLink")
  178.  
  179.     # Obtain Updated List of Files
  180.     files = drive_service.files().list(q="'{0}' in parents".format(folder_id), fields="nextPageToken, files(id, name, mimeType, trashed, webViewLink, fileExtension)").execute()
  181.     items = files.get('files', [])
  182.     if request.GET.get('folder_id'):
  183.         # Render view to create a file into a Folder        
  184.         student_id = get_student_id(request)
  185.         try:
  186.             scenario = get_scenarios()[scen_id]
  187.         except KeyError:
  188.             raise Http404
  189.  
  190.         usage_id = scenario.usage_id
  191.         runtime = WorkbenchRuntime(student_id)
  192.         block = runtime.get_block(usage_id)
  193.         render_context = {
  194.             'activate_block_id': request.GET.get('activate_block_id', None)
  195.         }
  196.         frag = block.render('student_view', render_context)
  197.  
  198.         return render_to_response('drivepy/folder.html', {
  199.             "folder_id": folder_id,
  200.             "file_url": request.GET.get('file_url'),
  201.             'head_html': frag.head_html(),
  202.             'foot_html': frag.foot_html(),
  203.             'files': items
  204.         })
  205.     return redirect('http://drivepython.10.0.2.186.xip.io:8020/scenario/'+scen_id, file_url=file_url)
  206.  
  207. # View for obtain the files of a Folder
  208. def folder(request):
  209.     folder_id = request.GET.get('id')
  210.     folder_name = request.GET.get('name')
  211.     credentials = client.OAuth2Credentials.from_json(request.session['credentials'])  
  212.     http_auth = credentials.authorize(httplib2.Http())
  213.     drive_service = discovery.build('drive', 'v3', http_auth)
  214.     files = drive_service.files().list(q="'{0}' in parents".format(folder_id), fields="nextPageToken, files(id, name, mimeType, trashed, webViewLink, fileExtension)").execute()
  215.     items = files.get('files', [])
  216.  
  217.     student_id = get_student_id(request)
  218.     try:
  219.         scenario = get_scenarios()[scen_id]
  220.     except KeyError:
  221.         raise Http404
  222.  
  223.     usage_id = scenario.usage_id
  224.     runtime = WorkbenchRuntime(student_id)
  225.     block = runtime.get_block(usage_id)
  226.     render_context = {
  227.         'activate_block_id': request.GET.get('activate_block_id', None)
  228.     }
  229.     frag = block.render('student_view', render_context)
  230.  
  231.     return render_to_response('drivepy/folder.html', {
  232.         "files": items,
  233.         "folder_name": folder_name,
  234.         "folder_id": folder_id,
  235.         "file_url": request.GET.get('file_url'),
  236.         'head_html': frag.head_html(),
  237.         'foot_html': frag.foot_html(),
  238.         'files': items
  239.     })
  240.  
  241. def handler(request, usage_id, handler_slug, suffix='', authenticated=True):
  242.     """The view function for authenticated handler requests."""
  243.     if authenticated:
  244.         student_id = get_student_id(request)
  245.         log.info("Start handler %s/%s for student %s", usage_id, handler_slug, student_id)
  246.     else:
  247.         student_id = "none"
  248.         log.info("Start handler %s/%s", usage_id, handler_slug)
  249.  
  250.     runtime = WorkbenchRuntime(student_id)
  251.  
  252.     try:
  253.         block = runtime.get_block(usage_id)
  254.     except NoSuchUsage:
  255.         raise Http404
  256.  
  257.     request = django_to_webob_request(request)
  258.     request.path_info_pop()
  259.     request.path_info_pop()
  260.     result = block.runtime.handle(block, handler_slug, request, suffix)
  261.     log.info("End handler %s/%s", usage_id, handler_slug)
  262.     return webob_to_django_response(result)
  263.  
  264.  
  265. def aside_handler(request, aside_id, handler_slug, suffix='', authenticated=True):
  266.     """The view function for authenticated handler requests."""
  267.     if authenticated:
  268.         student_id = get_student_id(request)
  269.         log.info("Start handler %s/%s for student %s", aside_id, handler_slug, student_id)
  270.     else:
  271.         student_id = "none"
  272.         log.info("Start handler %s/%s", aside_id, handler_slug)
  273.  
  274.     runtime = WorkbenchRuntime(student_id)
  275.  
  276.     try:
  277.         block = runtime.get_aside(aside_id)
  278.     except NoSuchUsage:
  279.         raise Http404
  280.  
  281.     request = django_to_webob_request(request)
  282.     request.path_info_pop()
  283.     request.path_info_pop()
  284.     result = block.runtime.handle(block, handler_slug, request, suffix)
  285.     log.info("End handler %s/%s", aside_id, handler_slug)
  286.     return webob_to_django_response(result)
  287.  
  288.  
  289. def package_resource(_request, block_type, resource):
  290.     """
  291.    Wrapper for `pkg_resources` that tries to access a resource and, if it
  292.    is not found, raises an Http404 error.
  293.    """
  294.     try:
  295.         xblock_class = XBlock.load_class(block_type)
  296.     except PluginMissingError:
  297.         try:
  298.             xblock_class = XBlockAside.load_class(block_type)
  299.         except PluginMissingError:
  300.             raise Http404
  301.     try:
  302.         content = xblock_class.open_local_resource(resource)
  303.     except Exception:  # pylint: disable-msg=broad-except
  304.         raise Http404
  305.     mimetype, _ = mimetypes.guess_type(resource)
  306.     return HttpResponse(content, content_type=mimetype)
  307.  
  308.  
  309. @csrf_exempt
  310. def reset_state(request):
  311.     """Delete all state and reload the scenarios."""
  312.     log.info("RESETTING ALL STATE")
  313.     reset_global_state()
  314.     referrer_url = request.META['HTTP_REFERER']
  315.  
  316.     return redirect(referrer_url)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement