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
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())
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
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
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
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))