rrb_bbr
rrb_bbr

Reputation: 3056

Setting up Mimetype when using TemplateView in Django

Does anyboy know how do I set the desired mimetype when using TemplateView, as in:

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

In this case, I want to set the mimtype as "text/plain"

Upvotes: 31

Views: 10817

Answers (8)

nsantana
nsantana

Reputation: 2050

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'),

Upvotes: 1

sacabuche
sacabuche

Reputation: 2849

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'
    ....

Upvotes: 44

dd42
dd42

Reputation: 138

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

Upvotes: 0

Venelin Stoykov
Venelin Stoykov

Reputation: 184

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.

Upvotes: 4

Erik
Erik

Reputation: 479

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)

Upvotes: 1

Meilo
Meilo

Reputation: 3418

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')),

Upvotes: 19

Jay Leadbetter
Jay Leadbetter

Reputation: 11

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)

Upvotes: 1

Soviut
Soviut

Reputation: 91595

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

Upvotes: 1

Related Questions