Example #1
0
    def render_oembed(self, oembed_resource, original_url, template_dir=None, context=None):
        """
        Render the oembed resource and return as a string.
        
        Template directory will always fall back to 'oembed/[type].html', but
        a custom template dir can be passed in using the kwargs.
        
        Templates are given two context variables:
        - response: an OEmbedResource
        - original_url: the url that was passed to the consumer
        """
        if not context.get("request", False):
            provided_context = context or Context()
            context = RequestContext(mock_request())
            context.update(provided_context)

        # templates are named for the resources they display, i.e. video.html
        template_name = "%s.html" % oembed_resource.type

        # set up template finder to fall back to the link template
        templates = [os.path.join("oembed", template_name), "oembed/link.html"]

        # if there's a custom template dir, look there first
        if template_dir:
            templates.insert(0, os.path.join("oembed", template_dir, template_name))

        template = select_template(templates)

        context.push()
        context["response"] = oembed_resource
        context["original_url"] = original_url
        rendered = template.render(context)
        context.pop()

        return rendered.strip()  # rendering template may add whitespace
Example #2
0
def add_todo(request):
    if request.method == 'POST':
        todo_obj = Todo(description=request.POST.get('job'))
        todo_obj.save()
        return HttpResponseRedirect('/todo')
    else:
        data = RequestContext(request)
        return render(request, 'add_todo.html', data.pop())
Example #3
0
    def render_oembed(self,
                      oembed_resource,
                      original_url,
                      template_dir=None,
                      context=None):
        """
        Render the oembed resource and return as a string.
        
        Template directory will always fall back to 'oembed/[type].html', but
        a custom template dir can be passed in using the kwargs.
        
        Templates are given two context variables:
        - response: an OEmbedResource
        - original_url: the url that was passed to the consumer
        """
        provided_context = context or Context()
        context = RequestContext(context.get("request") or mock_request())
        context.update(provided_context)

        # templates are named for the resources they display, i.e. video.html
        template_name = '%s.html' % oembed_resource.type

        # set up template finder to fall back to the link template
        templates = [os.path.join('oembed', template_name), 'oembed/link.html']

        # if there's a custom template dir, look there first
        if template_dir:
            templates.insert(
                0, os.path.join('oembed', template_dir, template_name))

        template = select_template(templates)

        context.push()
        context['response'] = oembed_resource
        context['original_url'] = original_url
        rendered = template.render(context)
        context.pop()

        return rendered.strip()  # rendering template may add whitespace
Example #4
0
 def render_html(self, obj, context=None):
     """
     Generate the 'html' attribute of an oembed resource using a template.
     Sort of a corollary to the parser's render_oembed method.  By default,
     the current mapping will be passed in as the context.
     
     OEmbed templates are stored in:
     
     oembed/provider/[app_label]_[model].html
     
     -- or --
     
     oembed/provider/media_video.html
     """        
     provided_context = context or Context()
     context = RequestContext(mock_request())
     context.update(provided_context)
     
     context.push()
     context[self._meta.context_varname] = obj
     rendered = render_to_string(self._meta.template_name, context)
     context.pop()
     return rendered
    def render_html(self, obj, context=None):
        """
        Generate the 'html' attribute of an oembed resource using a template.
        Sort of a corollary to the parser's render_oembed method.  By default,
        the current mapping will be passed in as the context.
        
        OEmbed templates are stored in:
        
        oembed/provider/[app_label]_[model].html
        
        -- or --
        
        oembed/provider/media_video.html
        """
        provided_context = context or Context()
        context = RequestContext(mock_request())
        context.update(provided_context)

        context.push()
        context[self._meta.context_varname] = obj
        rendered = render_to_string(self._meta.template_name, context)
        context.pop()
        return rendered
Example #6
0
class GenericView(http.HttpResponse):
    """A class-based view.

    This class provides a generic framework for implementing a class-based
    view. By default it permits ``GET`` requests, and will automatically
    handle conditional requests, controlled through ``If-Modified-Since`` and
    ETag request headers.

    This class works by subclassing ``HttpResponse``. When called, the view is
    instantiated with the request instance and url parameters, just like a
    Django view function. The request is handled by the initializer and the
    result of the instantiation is the response to the given request.

    """
    methods = ('GET',)

    def __init__(self, request, *args, **kwargs):
        super(GenericView, self).__init__()

        self.context = RequestContext(request)

        obj = self.setup(request, *args, **kwargs)

        if not obj:
            obj = self.conditional_dispatch(request, *args, **kwargs)

        if isinstance(obj, http.HttpResponse):
            self._update(obj)
        else:
            self.content = obj

    def _update(self, response):
        """
        Merge another `HttpResponse` into this instance.

        This method copies the attributes from the given response to this
        instance, with the exceptions of the ``_headers`` and ``cookies``
        dictionaries. Instead these members' ``update()`` methods are used,
        preserving headers and cookies present in this response but not the
        argument.

        """
        self._charset = response._charset
        self._is_string = response._is_string
        self._container = response._container
        self._headers.update(response._headers)
        self.cookies.update(response.cookies)
        self.status_code = response.status_code
        self.content = response.content

        if self.status_code == 405:
            self.content = 'Allowed methods: %s' % self['Allow']

    def dispatch(self, request, *args, **kwargs):
        """
        This method dispatches the request to the appropriate method based on
        the HTTP request method.
        """
        allowed, response = self._check_request_allowed(request, *args, **kwargs)
        if not allowed:
            return response

        if not hasattr(self, request.method.lower()) or \
           not callable(getattr(self, request.method.lower())):
            raise Exception("Allowed view method %s does not exist." % request.method.lower())
        return getattr(self, request.method.lower())(request, *args, **kwargs)

    def _check_request_allowed(self, request, *args, **kwargs):
        """
        This method determines whether the user is allowed to perform the request
        method that was sent to the server.
        """
        if request.method.lower() not in (method.lower() for method in self.methods):
            return False, http.HttpResponseNotAllowed(self.methods)
        return True, None

    def conditional_dispatch(self, request, *args, **kwargs):
        """
        Dispatches the request or returns an `HttpResponseNotModified`
        instance, as appropriate.

        For ``GET``, ``HEAD``, and ``PUT`` requests, this method calls its
        instance's `etag()` and `last_modified()` methods, then checks
        whether a the appropriate preconditions are satisfied before
        continuing.

        """
        allowed, response = self._check_request_allowed(request, *args,
                                                        **kwargs)
        if not allowed:
            return response

        if request.method not in ('GET', 'HEAD', 'PUT'):
            return self.dispatch(request, *args, **kwargs)

        last_modified = str(self.last_modified(request, *args, **kwargs))
        etag = self.etag(request, *args, **kwargs)

        if request.method in ('GET', 'HEAD'):
            # Get HTTP request headers
            if_modified_since = request.META.get('HTTP_IF_MODIFIED_SINCE', None)
            if_none_match = request.META.get('HTTP_IF_NONE_MATCH', None)
            if if_none_match:
                if_none_match = parse_etags(if_none_match)

            # Calculate "not modified" condition
            not_modified = (if_modified_since or if_none_match) and \
                           (not if_modified_since or \
                            last_modified == if_modified_since) and \
                           (not if_none_match or etag in if_none_match)

            # Create appropriate response
            if not_modified:
                response = http.HttpResponseNotModified()
            else:
                response = self.dispatch(request, *args, **kwargs)
        else: # method == 'PUT'
            # Get the HTTP request headers
            if_match = request.META.get('HTTP_IF_MATCH', None)
            if_unmodified_since = request.META.get('HTTP_IF_UNMODIFIED_SINCE', None)
            if if_match:
                if_match = parse_etags(if_match)

            # Calculate "modified" condition
            modified = (if_unmodified_since \
                        and last_modified != if_unmodified_since) or \
                       (if_match and etag not in if_match)

            # Create appropriate response
            if modified:
                response = http.HttpResponse(status=412) # precondition failed
            else:
                response = self.dispatch(request, *args, **kwargs)
        return response

    def last_modified(self, request, *args, **kwargs):
        """
        Returns a value representing the last modification timestamp of the
        view.

        To support ``If-Modified-Since`` headers, return a timestamp
        representing the last-modified date of the view. This may be based on
        a physical file timestamp, or the last modified element of the view
        being published.

        """
        return None

    def etag(self, request, *args, **kwargs):
        """
        Returns a value used as the ETag for the view.

        To support ``If-None-Match`` ETag HTTP headers, return an appropriate
        ETag here.

        """
        return None

    def get(self, request, *args, **kwargs):
        """
        Handles ``GET`` requests.

        Override this method to handle ``GET`` requests, returning an
        `HttpResponse` instance.

        """
        return http.HttpResponse()

    def setup(self, request, *args, **kwargs):
        """
        Called for all invocation of the view to set up the view prior to
        dispatching to the appropriate handler.

        Subclasses can override this method which is invoked after the class
        has been initialized but prior to the dispatch to the ``GET``,
        ``POST``, etc. handler.

        """
        pass

    def render_to_response(self, template, more_context=None, **kwargs):
        """
        A shortcut method that runs the `render_to_response` Django shortcut.

        It will apply the view's context object as the context for rendering
        the template. Additional context variables may be passed in, similar
        to the `render_to_response` shortcut.

        """
        if more_context:
            self.context.push()
            self.context.update(more_context)
        if self.context.get('mobile'):
            template = ('mobile/' + template, template)
        results = render_to_response(template, context_instance=self.context, **kwargs)
        if more_context:
            self.context.pop()
        return results
Example #7
0
class BaseHandler(object):
    formclass = None
    model = None
    path = '/'
    template_ns = None

    def __init__(self, request, instance=None, post=False, rest=[],
                 path=None, kw={}):
        """
            request
                The original (django) request
            instance
                A coerced instance. Can be a dictionary if the handler
                supports multiple models
            post
                True if it's a POST request
            rest
                Unresolved path components
            path
                Original path (url-pattern path?) OBSOLETE XXX
            **kw
                Arguments from the urlpattern. Also contains the instance
        """
        self.request = request
        self.context = RequestContext(request)

        self.update_context(request)

        if isinstance(instance, dict):
            self.instance = None
            ## initialize all multimodel instances to None
            if isinstance(self.model, dict):
                for k in self.model:
                    setattr(self, k, None)
            for k, v in instance.iteritems():
                setattr(self, k, v)
                self.context[k] = v
        else:
            self.instance = instance
            self.context['instance'] = self.instance
        self.post = post
        self.rest = rest
        self.path = path or self.path
        self.kw = kw

        ## instance can be a dict, depending on it in general is
        ## deprecated. Access self.instance directly, which has been
        ## unmapped
        self.verify_access(instance)

        self.messages = {}
        self.context['piggyback'] = {}

        if self.formclass:
            if post:
                if instance:
                    self.form = self.formclass(data=request.POST,
                                               instance=self.instance)
                else:
                    self.form = self.formclass(data=request.POST)
            else:
                if self.instance:
                    self.form = self.formclass(instance=self.instance)
                else:
                    self.form = self.formclass()
        else:
            self.form = None
        self.context['form'] = self.form
        for a in dir(self):
            m = getattr(self, a)
            if isinstance(m, (types.FunctionType, types.MethodType)) and \
               getattr(m, 'contextified', False):
                self.context[a] = m

    def pre_handler(self):
        """ invoked before an operation """

    def post_handler(self):
        """ invoked after an operation """

    def update_context(self, request):
        """ hook to add more stuff into context """
        pass

    def verify_access(self, instance):
        """ verify if user has access to object in current context """
        ## return self.forbidden() if not
        return True

    def set_message(self, type, message):
        self.messages[type] = message

    def get_message(self, type):
        return self.messages.get(type, '') or self.request.REQUEST.get(type, '')

    @context
    def user(self):
        return self.request.user

    @context
    def info_message(self):
        return self.get_message('info')

    @context
    def success_message(self):
        return self.get_message('success')

    @context
    def warning_message(self):
        return self.get_message('warning')

    @context
    def error_message(self):
        return self.get_message('error')

    @property
    def site(self):
        return get_current_site(self.request)

    @context
    def url(self, *elements):
        ### XXX obsolete ?
        # XXX is_secure / https
        p = "http://%s/" % self.site.domain

        if self.path.strip('/'):
            p += self.path + '/' # must end in slash

        if elements:
            p += "/".join(elements) # shouldn't (?) need to end in slash
        return p

    @property
    def var(self):
        """ allows you to do 
                self.var.some_key
            in stead of
                self.request.REQUEST.get(some_key)
            raises AttributeError if some_key does not exist
        """
        class wrapper(object):
            def __init__(self, request):
                self.request = request

            def __getattr__(self, key):
                _marker = object()
                value = self.request.REQUEST.get(key, _marker)
                if value is _marker:
                    raise AttributeError(key)
                return value
        return wrapper(self.request)

    def vars(self, key, default=None):
        return self.request.REQUEST.get(key, default)

    def piggyback(self, *arguments):
        """ The piggyback can be used to store arguments that need to
            survive redirects and formposts """
        piggyback = self.context['piggyback']
        for argument in arguments:
            if argument in self.request.REQUEST:
                piggyback[argument] = self.request.REQUEST[argument]

    @classmethod
    def coerce(cls, i):
        if isinstance(cls.model, dict):
            if not isinstance(i, dict):
                i = {'instance': i}

            ## a "multi model"
            res = {}
            for (k, v) in i.iteritems():
                try:
                    res[k] = cls.model[k].objects.get(id=int(v))
                except KeyError:
                    ## ignore, it will be passed as a "kw" entry, and can
                    ## be used in create contexts, see remark below about
                    ## not able to fetch an instance
                    pass
                    # raise RuntimeError("No model defined for " + k)
                except ValueError:
                    return None
                except cls.model[k].DoesNotExist:
                    ## can't call self.notfound since we're a classmethod
                    raise NotFound()
            return res

        if isinstance(i, dict):
            ## we're handed a dict but the handler only supports a single
            ## model. Fetch the instance from the dict
            i = i.get('instance')

            ## if we were not able to fetch an instance value, there's
            ## nothing to coerce. E.g. when doing a create on
            ## POST /foo/123/bar which would create a new bar under foo 123
            if not i:
                return None

        try:
            return cls.model.objects.get(id=int(i))
        except ValueError:
            return None
        except cls.model.DoesNotExist:
            ## can't call self.notfound since we're a classmethod
            raise NotFound()

    def redirect(self, url, permanent=False, hash=None,
                 piggyback=False, **kw):
        args = kw.copy()
        if piggyback:
            args.update(self.context['piggyback'])
        ## encode args values to utf8
        encoded = {}
        for (k, v) in args.iteritems():
            if isinstance(v, unicode):
                v = v.encode('utf8')
            encoded[k] = v
        args = urllib.urlencode(encoded)
        if args:
            if '?' in url: # it already has args
                url = url + "&" + args
            else:
                url = url + "?" + args
        if hash:
            url += "#" + hash
        raise Redirect(url, permanent=permanent)

    @classmethod
    def notfound(cls):
        raise NotFound()

    @classmethod
    def forbidden(cls):
        raise Forbidden()

    @classmethod
    def badrequest(cls):
        raise BadRequest()

    @classmethod
    def servererror(cls):
        raise ServerError()

    def get_template(self, t):
        return loader.get_template(t)

    def render_template(self, t, **kw):
        template_path = t
        if self.template_ns:
            template_path = os.path.join(self.template_ns, t)
        self.context.push()
        self.context.update(kw)
        t = self.get_template(template_path)
        result = t.render(self.context)
        self.context.pop()

        ## angularjs fix
        result = result.replace("<[", "{{").replace("]>", "}}")
        return result

    def template(self, t, **kw):
        return HttpResponse(self.render_template(t, **kw))