Codice sorgente per thx.appy.views

# 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