通过Django Class Based Views发送文件 [英] Send a file through Django Class Based Views

查看:213
本文介绍了通过Django Class Based Views发送文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们为我们的大部分项目使用基于类的视图。当我们尝试创建CSV Mixin时,我们遇到了一个问题,允许用户将几乎任何页面的信息作为CSV文件导出。我们的特殊问题涉及到CSV文件,但我相信我的问题是通用的,足以与任何文件类型相关。



我们遇到的问题是视图的响应正在尝试去模板(比如从django.views.generic import TemplateView 中的)。我们在 urls.py 文件中指定模板。

  url r'^ $',MyClassBasedView.as_view(template_name ='my_template.html'))

您强制响应绕过模板,只返回标准的 HttpResponse ?我猜你需要重写一个方法,但我不知道哪一个方法。



任何建议?


$ b $编辑1:看来我不清楚我们正在努力做什么。我已经呈现了一个页面(通过基于类的视图),用户将看到信息的报告。我需要放置一个按钮导出到CSV供用户按下,它将导出他们的页面上的信息,并将CSV下载到他们的机器上。



将视图重写为基于方法的视图不是一种选择。我们处理几乎所有基于类的视图类型(DetailView,ListView,TemplateView,View,RedirectView等)。

解决方案

当您需要为相同的数据提供不同的响应时,这是一个通用问题。您想要插入的点是当上下文数据已经解决但响应尚未构建时。



基于类的视图解析为 TemplateResponseMixin 有几个属性和类方法来控制响应对象的构造方式。不要被认为这个名字意味着只有HTML响应或需要模板处理的响应才能通过这种设计来促进。解决方案的范围可以是创建基于 TemplateResponse 类或创建一个可重用的mixin,为 render_to_response 方法。



代替编写自定义响应类,开发人员更经常提供自定义的 render_to_response 方法在视图类或单独的混合,因为它是非常简单和直接了解发生了什么。您将嗅探请求数据以查看是否需要构建一些不同类型的响应,如果不是,您将简单地委派给默认实现来呈现模板响应。



以下是一个这样的实现可能如下所示:

  import csv 
from django.http import HttpResponse
from django.utils.text import slugify
from django.views.generic import TemplateView


class CSVResponseMixin(object )

如果
CSV导出选项在请求中提供,那么从上下文数据构造CSV响应的通用mixin

def render_to_response(self,context,** response_kwargs):

如果请求创建CSV响应,否则返回默认的
模板响应

#如果我们需要返回CSV导出
如果self.request.GET.get('export','')中的'csv':
response = HttpResponse(content_type ='text / csv')
response ['Content-Disposition'] ='attachment; filename =%s.csv'%slugify(context ['title'])

writer = csv.writer(response)
#从上下文写入数据
对于上下文['items']中的项目:
writer.writerow(item)

返回响应
#按照以往一样的业务
else:
return super(CSVResponseMixin,self).render_to_response(context,** response_kwargs):

还可以看到可能需要一个更精细的设计与自定义响应类。虽然这适用于为自定义响应类型添加特别支持,但如果您希望支持五种不同的响应类型,则它不会很好地扩展。



在这种情况下,您将创建并测试单独的响应类,然后编写一个 CustomResponsesMixin 类,该类将了解所有响应类并提供自定义 render_to_response 只配置 self.response_class 的方法,并将所有其他代码委托给响应类。


We use class based views for most of our project. We have run into an issue when we try and create a CSV Mixin that will allow the user to export the information from pretty much any page as a CSV file. Our particular problem deals with CSV files, but I believe my question is generic enough to relate to any file type.

The problem we are having is that the response from the view is trying to go to the template (say like from django.views.generic import TemplateView). We specify the template in the urls.py file.

url(r'^$', MyClassBasedView.as_view(template_name='my_template.html'))

How can you force the response to bypass the template and just return a standard HttpResponse? I'm guessing you'll need to override a method but I'm not sure which one.

Any suggestions?

EDIT1: It appears that I was unclear as to what we are trying to do. I have rendered a page (via a class based view) and the user will see reports of information. I need to put in a button "Export to CSV" for the user to press and it will export the information on their page and download a CSV on to their machine.

It is not an option to rewrite our views as method based views. We deal with almost all class based view types (DetailView, ListView, TemplateView, View, RedirectView, etc.)

解决方案

This is a generic problem when you need to provide different responses for the same data. The point at which you would want to interject is when the context data has already been resolved but the response hasn't been constructed yet.

Class based views that resolve to the TemplateResponseMixin have several attributes and class methods that control how the response object is constructed. Do not be boxed into thinking that the name implies that only HTML responses or those that need template processing can only be facilitated by this design. Solutions can range from creating custom, reusable response classes which are based on the behavior of the TemplateResponse class or creating a reusable mixin that provides custom behavior for the render_to_response method.

In lieu of writing a custom response class, developers more often provide a custom render_to_response method on the view class or separately in a mixin, as it's pretty simple and straightforward to figure out what's going on. You'll sniff the request data to see if some different kind of response has to be constructed and, if not, you'll simply delegate to the default implementation to render a template response.

Here's how one such implementation might look like:

import csv
from django.http import HttpResponse
from django.utils.text import slugify
from django.views.generic import TemplateView


class CSVResponseMixin(object):
    """
    A generic mixin that constructs a CSV response from the context data if
    the CSV export option was provided in the request.
    """
    def render_to_response(self, context, **response_kwargs):
        """
        Creates a CSV response if requested, otherwise returns the default
        template response.
        """
        # Sniff if we need to return a CSV export
        if 'csv' in self.request.GET.get('export', ''):
            response = HttpResponse(content_type='text/csv')
            response['Content-Disposition'] = 'attachment; filename="%s.csv"' % slugify(context['title'])

            writer = csv.writer(response)
            # Write the data from the context somehow
            for item in context['items']:
                writer.writerow(item)

            return response
        # Business as usual otherwise
        else:
            return super(CSVResponseMixin, self).render_to_response(context, **response_kwargs):

Here's where you can also see when a more elaborate design with custom response classes might be needed. While this works perfectly for adding ad-hoc support for a custom response type, it doesn't scale well if you wanted to support, say, five different response types.

In that case, you'd create and test separate response classes and write a single CustomResponsesMixin class which would know about all the response classes and provide a custom render_to_response method that only configures self.response_class and delegates everything else to the response classes.

这篇关于通过Django Class Based Views发送文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆