abilian.web.views.base — Abilian 0.1 documentation

# Source code for abilian.web.views.base

    # coding=utf-8
    """
    """
    from __future__ import absolute_import

    from werkzeug.exceptions import HTTPException
    from flask import request, g, json, jsonify, render_template_string, redirect
    from flask.views import MethodView as BaseView

    from ..action import actions

    class Redirect(HTTPException):
      pass

    class View(BaseView):
      """
      Base class to use for all class based views.

      The view instance is accessible in :data:`g <flask.g>` and is set in
      :meth:`actions context <abilian.web.action.ActionRegistry.context>`.
      """

      def dispatch_request(self, *args, **kwargs):
        meth = getattr(self, request.method.lower(), None)
        # if the request method is HEAD and we don't have a handler for it
        # retry with GET
        if meth is None and request.method == 'HEAD':
          meth = getattr(self, 'get', None)
          assert meth is not None, 'Unimplemented method %r' % request.method

        g.view = actions.context['view'] = self
        try:
          args, kwargs = self.prepare_args(args, kwargs)
          return meth(*args, **kwargs)
        except Redirect as exc:
          return exc.response

      def prepare_args(self, args, kwargs):
        """
        If view arguments need to be prepared it can be done here.

        A typical use case is to take an identifier, convert it to an object
        instance and maybe store it on view instance and/or replace
        identifier by object in arguments.
        """
        return args, kwargs

      def redirect(self, url):
        """
        Shortcut all call stack and return response.

        usage: `self.response(url_for(...))`
        """
        raise Redirect(response=redirect(url))

    _JSON_HTML = u'''
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="utf-8">
      <link rel="stylesheet" href="{{ url_for('abilian_static', filename="highlightjs/default.min.css") }}" />
    </head>
    <body>
      <pre>
      <code class="json">
    {{ content }}
      </code>
      </pre>

      <script src="{{ url_for('abilian_static', filename="highlightjs/highlight.min.js")  }}" ></script>
      <script>hljs.initHighlightingOnLoad();</script>
    </body>
    </html>
    '''

    class JSONView(View):
      """
      Base view for JSON GET.

      Renders as JSON when requested by Ajax, renders as HTML when requested
      from browser.
      """
      def prepare_args(self, args, kwargs):
        kwargs.update({k: v for k, v in request.args.items()})
        return args, kwargs

      def data(self, *args, **kwargs):
        """
        This method should return data to be serialized using JSON
        """
        raise NotImplemented

      def get(self, *args, **kwargs):
        data = self.data(*args, **kwargs)
        best_mime = request.accept_mimetypes.best_match(['text/html',
                                                         'application/json'])
        if best_mime == 'application/json':
          return jsonify(data)

        # dev requesting from browser? serve html, let debugtoolbar show up, etc...
        content = json.dumps(data, indent=2)
        return render_template_string(_JSON_HTML, content=content)