# coding: utf-8
"""
Views
=====
A TemplateView that allows to set
* desired output format
* `Content-Disposition` on the response using ``output_name``
* output file name
Usage examples
---------------
Directly in ``urls.py``::
  urlpatterns = [
      path('', views.IndexView.as_view(), name="appy-examples"),
      path('pdf/simple', AppyTemplateView.as_view(
          template_name='examples/simple.odt'), name='pdf-simple'),
      path('odt/simple', AppyTemplateView.as_view(
          template_name='examples/simple.odt', output_type='odt'), name='odt-simple'),
      path('odt/context', views.OdtContextView.as_view(), name='odt-context'),
      path('pdf/context', views.PdfContextView.as_view(), name='pdf-context'),
  ]
Or in ``views.py`` as::
  class PdfContextView(AppyTemplateView):
      template_name = 'examples/context.odt'
      def get_context_data(self, **kwargs):
          context = super().get_context_data(**kwargs)
          context['name'] = 'Sandro'
          return context
  class OdtContextView(PdfContextView):
      output_type = 'odt'
.. autoclass:: AppyTemplateView
   :members:
.. autoclass:: AppyTemplateMixin
   :members:
"""
import os
from django.views.generic import TemplateView
from django.core.exceptions import ImproperlyConfigured
from django.template.response import TemplateResponse
class AppyTemplateResponse(TemplateResponse):
    # We need to get to the render function so we can add optional flags
    # output_format and external
    # output_format is particularly needed to avoid getting to the converter odt => odt
    def __init__(self, request, template, context=None, content_type=None,
                 status=None, charset=None, using=None, output_format=None, external=None):
        super().__init__(request, template, context, content_type, status, charset, using)
        self.output_format = output_format
        self.external = external
    @property
    def rendered_content(self):
        """Return the freshly rendered content for the template and context
        described by the TemplateResponse.
        This *does not* set the final content of the response. To set the
        response content, you must either call render(), or set the
        content explicitly using the value of this property.
        """
        template = self.resolve_template(self.template_name)
        context = self.resolve_context(self.context_data)
        content = template.render(
            context, self._request, output_format=self.output_format, external=self.external)
        return content
[documenti]class AppyTemplateMixin:
    """Mixin that tries to be smart understanding how to handle an
    OpenDocument File as far as:
    :content_type: desumed from ``output_format``
    :output_name: desumed from ``template_name`` and ``output_format``
    """
    #: the content type used in the response
    content_type = None
    content_type_map = {
        'pdf': 'application/pdf',
        'odt': 'application/vnd.oasis.opendocument.text',
        'ods': 'application/vnd.oasis.opendocument.spreadsheet',
    }
    #: the desired output type: pdf, odt, ods are supported
    output_format = 'pdf'
    #: the desired output name. Default is built using template_name and
    #: changing the suffix according to the output_format
    output_file_name = None
    response_class = AppyTemplateResponse
    #: forces/blocks use of external service for conversion if POD_CONVERTER is defines
    external = None
[documenti]    def get_output_name(self):
        """Return the output_file_name or build a suitable one"""
        if self.output_file_name:
            return self.output_file_name
        basename = os.path.basename(self.template_name)
        base, ext = os.path.splitext(basename)
        return f'{base}.{self.output_format}' 
[documenti]    def get_content_type(self):
        """Return the deesired output_format according"""
        try:
            return self.content_type or self.content_type_map[self.output_format]
        except KeyError:
            raise ImproperlyConfigured(
                """You must set eather content_format or output_format (pdf, odt, ods)"""
            ) 
[documenti]    def render_to_response(self, context, **response_kwargs):
        """
        Return a response, using the `response_class` for this view, with a
        template rendered with the given context.
        Pass response_kwargs to the constructor of the response class.
        """
        response_kwargs.setdefault('content_type', self.get_content_type())
        response_kwargs['output_format'] = self.output_format
        response_kwargs['external'] = self.external
        output_file_name = self.get_output_name()
        response = self.response_class(
            request=self.request,
            template=self.get_template_names(),
            context=context,
            using=self.template_engine,
            **response_kwargs
        )
        response['Content-Disposition'] = f'attachment; filename="{output_file_name}"'
        return response  
[documenti]class AppyTemplateView(AppyTemplateMixin, TemplateView):
    """A templateView that just need a template_name and an output_format"""
    pass