[Django]-Setting up Mimetype when using TemplateView in Django

44πŸ‘

βœ…

For Django >= 1.5

TemplateView accepts a content_type argument.

Coping example from @Meilo

urlpatterns = patterns('',
    url(r'^test\.txt$', TemplateView.as_view(template_name='staticpages/test.html', content_type='text/plain')),

For Django < 1.5

I think that just calling TemplateView.as_view() is not posible but maybe i missed it (from the source),
but you can do your own class

class TextTemplateView(TemplateView):
    def render_to_response(self, context, **response_kwargs):
        response_kwargs['content_type'] = 'text/plain'
        return super(TemplateView, self).render_to_response(context, **response_kwargs)

You can take a look to:

django.template.response => TemplateResponse
django.views.generic.base => TemplateView

And if you need something more dynamic:

from django.utils.decorators import classonlymethod


class ContentTypeTemplateView(TemplateView):

    @classonlymethod
    def as_view(cls, content_type='text/plain', **initargs):
        setattr(cls, 'content_type', content_type)
        return super(ContentTypeTemplateView, cls).as_view(**initargs)

    def render_to_response(self, context, **response_kwargs):
        response_kwargs['content_type'] = self.content_type
        return super(ContentTypeTemplateView, self).render_to_response(context, **response_kwargs)


urlpatterns = patterns('',
    url(r'^$', ContentTypeTemplateView.as_view(content_type='text/plain',
                                               template_name='staticpages/test.html'),
        name='index'),
)

Using a Mixin

from django.core.exceptions import ImproperlyConfigured


class ContentTypeMixin(object):

    content_type = None

    def render_to_response(self, context, **response_kwargs):
        if not self.content_type:
            raise ImproperlyConfigured(
                "MimeTypeMixin rquires a definition of content_type")
        response_kwargs['content_type'] = self.content_type
        return super(ContentTypeMixin, self).render_to_response(context,
                                                             **response_kwargs)


class MyTxtView(ContentTypeMixin, TemplateView):
    content_type = 'text/plain'
    ....
πŸ‘€sacabuche

19πŸ‘

In Django 1.5 the content_type argument in the TemplateView adds the same functionality that was in the function-based view before. That makes it easier to set the desired mimetype:

urlpatterns = patterns('',
    url(r'^test\.txt$', TemplateView.as_view(template_name='staticpages/test.html', content_type='text/plain')),
πŸ‘€Meilo

4πŸ‘

I know that you ask for setting a content type with TemplateView, but I will give you different answer which I think that will be more clean and can be used in Django versions lower than 1.5.

    url(r'^robots\.txt$', 'django.shortcuts.render', kwargs={
        'template_name': 'robots.txt',
        'content_type': 'text/plain',
    })

With this approach you don’t need to import anything or to subclass TemplateView and make ugly overwrites of some methods. You can simply use the old technique with function based views.

1πŸ‘

The best way to do it is to subclass TemplateView and override the render_to_response() method:

class StaticPagesTest(TemplateView):
    template_name = 'staticpages/test.html'

    def render_to_response(self, context, **kwargs):
        return super(StaticPagesTest, self).render_to_response(context,
                     mimetype='text/plain', **kwargs)

1πŸ‘

If you don’t want to extend the TemplateView, you can extend the TemplateResponse to set the mimetype:

from django.template.response import TemplateResponse

class TextResponse(TemplateResponse):
    def __init__(self, *args, **kwargs):
        kwargs['mimetype'] = 'text/plain'
        return super(TextResponse, self).__init__(*args, **kwargs)

Then pass it as the template_class to the TemplateView

urlpatterns = patterns('django.views.generic.simple',
    (r'^robots\.txt$', TemplateView.as_view(template_name='robots.txt', response_class=TextResponse)),
)
πŸ‘€Soviut

1πŸ‘

I know this is solved for 1.5, but the application I am working in is 1.4.

I had an issue with two url patterns in a row using sacabuche’s answer:

url(r'^playlist1\.m3u$', ContentTypeTemplateView.as_view(template_name='playlist1.m3u', content_type='audio/x-mpegurl')),
url(r'^playlist2\.pls$', ContentTypeTemplateView.as_view(template_name='playlist2.pls', content_type='audio/x-scpls'))

I found playlist1 would return the correct template, but with playlist2’s content type! Playlist2 was ok. Adding a 3rd url pattern with a content-type of β€˜foo’ would cause all playlist views to return with content-type β€˜foo’.

I ended up using the render method instead with good results:

urls:

url(r'^playlist1\.m3u$', 'content_type_to_template', {'template_name': 'playlist1.m3u', 'content_type': 'audio/x-mpegurl'}),
url(r'^playlist2\.pls$', 'content_type_to_template', {'template_name': 'playlist2.pls', 'content_type':'audio/x-scpls'})

views:

from django.shortcuts import render

def content_type_to_template(request, template_name='', content_type='text/plain'):
    return render(request, template_name, content_type=content_type)
πŸ‘€Erik

1πŸ‘

A simple example of how change content type of a TemplateView:

#views.py
from django.views.generic import TemplateView

class HomeView(TemplateView):
    template_name = "home/index.html"
    content_type = 'text/html'

# urls.py
url(r'^home/$', HomeView.as_view(), name='home_page'),
πŸ‘€nsantana

0πŸ‘

url(r'^test/(?P<template>.*)', lambda request, template: TemplateView.as_view(template_name=template)(request)),
πŸ‘€dd42

Leave a comment