from __future__ import absolute_import import os import logging from django.contrib.staticfiles.storage import staticfiles_storage, HashedFilesMixin from django.contrib.staticfiles.finders import find as find_static from django.core.serializers.json import DjangoJSONEncoder from django.utils.safestring import mark_safe from django.utils.html import escapejs from django.conf import settings from react_render.core import render_component as render_core from react_render.core import DEFAULT_SERVICE_URL SERVICE_URL = getattr(settings, 'REACT_SERVICE_URL', DEFAULT_SERVICE_URL) FAIL_SAFE = getattr(settings, 'REACT_FAIL_SAFE', False) log = logging.getLogger('react-render-client') class RenderedComponent(object): def __init__(self, output, path_to_source, props, json_encoder): self.output = output self.path_to_source = path_to_source self.props = props self.json_encoder = json_encoder def __str__(self): return mark_safe(self.output) def __unicode__(self): return mark_safe(self.output) def render_props(self): if self.props: encoded = escapejs(self.json_encoder(self.props)) return mark_safe("JSON.parse('{0}')".format(encoded)) return '{}' def render_component(path_to_source, props=None, to_static_markup=False, json_encoder=None): if not os.path.isabs(path_to_source): # If its using the manifest staticfiles storage, to the hashed name. # eg. js/hello.js -> js/hello.d0bf07ff5f07.js if isinstance(staticfiles_storage, HashedFilesMixin): try: path_to_source = staticfiles_storage.stored_name(path_to_source) except ValueError: # Couldn't find it. pass # first, attempt to resolve at STATIC_ROOT if the file was collected abs_path = os.path.join(settings.STATIC_ROOT or '', path_to_source) if os.path.exists(abs_path): path_to_source = abs_path else: # Otherwise, resolve it using finders path_to_source = find_static(path_to_source) or path_to_source if json_encoder is None: json_encoder = DjangoJSONEncoder().encode try: html = render_core(path_to_source, props, to_static_markup, json_encoder, service_url=SERVICE_URL) except: if not FAIL_SAFE: raise log.exception('Error while rendering %s', path_to_source) html = '' return RenderedComponent(html, path_to_source, props, json_encoder)