2013-04-29 5 views
3

우리는 대부분의 프로젝트에 클래스 기반 뷰를 사용합니다. 우리는 사용자가 거의 모든 페이지의 정보를 CSV 파일로 내보낼 수있는 CSV Mixin을 만들려고 할 때 문제가 발생했습니다. 우리의 특별한 문제는 CSV 파일을 다룹니다. 그러나 제 질문은 어떤 파일 유형과도 관련이있을 정도로 일반적인 질문이라고 생각합니다.Django 클래스 기반 뷰를 통해 파일 전송

우리가 겪고있는 문제는보기의 응답이 템플릿 (예 : from django.views.generic import TemplateView)으로 이동하려고한다는 것입니다. 템플릿을 urls.py 파일로 지정합니다.

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

응답을 템플릿을 우회하여 강제로 HttpResponse 표준을 반환 할 수 있습니까? 나는 당신이 방법을 오버라이드 할 필요가있을 것이라고 추측하지만 어떤 것이 확실하지 않다.

제안 사항?

EDIT1 : 우리가하려는 일에 대해 분명하지 않았습니다. 나는 (클래스 기반보기를 통해) 페이지를 렌더링했고 사용자는 정보의 보고서를 볼 것입니다. 사용자가 누를 수 있도록 "CSV로 내보내기"버튼을 넣어야합니다. 그러면 해당 페이지의 정보가 내보내지고 CSV가 컴퓨터로 다운로드됩니다.

뷰를 메소드 기반보기로 다시 작성하는 옵션이 아닙니다. 우리는 거의 모든 클래스를 기반으로보기 유형 (DetailView, ListView에, TemplateView,보기, 만약 RedirectView 등)

+1

당신은 CSVResponseMixin 클래스를 생성 할 수 있으며'render_to_response' 메소드에는 CSV를 반환해야하는지 여부를 감지하는 데 필요한 로직이 포함되어 있습니다. 정상적으로 작동해야합니다. – dm03514

답변

10

당신이 필요로 할 때 이것은 일반적인 문제 동일한 데이터에 대해 다른 응답을 제공합니다. 삽입 할 시점은 컨텍스트 데이터가 이미 해결되었지만 응답이 아직 작성되지 않은 경우입니다.

TemplateResponseMixin으로 해석되는 클래스 기반보기에는 응답 개체 구성 방법을 제어하는 ​​여러 가지 특성과 클래스 메서드가 있습니다. HTML 응답 만 또는 템플릿 처리가 필요한 템플릿이이 디자인에 의해서만 촉진 될 수 있다는 것을 그 이름이 암시한다고 생각하면 안됩니다.솔루션은 TemplateResponse 클래스의 동작을 기반으로하는 사용자 지정 및 재사용 가능한 응답 클래스를 만드는 것부터 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): 
    """ 
    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): 

:

여기에 하나의 구현처럼 보일 수 있습니다 방법입니다. 이 기능은 맞춤 응답 유형에 대한 임시 지원을 추가하는 데 완벽하게 작동하지만 5 가지 응답 유형을 지원하려는 경우 확장되지 않습니다. 이 경우

작성하고 별도의 응답 클래스를 테스트에 대한 모든 응답 클래스를 알고 있고 사용자에게에만 응답 클래스에 다른 self.response_class 위임 모든 구성 render_to_response 방법을 제공하는 것이 하나의 CustomResponsesMixin 클래스를 작성할 것입니다.

1

어떻게 템플릿을 무시하고 단지 표준 HttpResponse에를 를 반환하는 응답을 강제로 처리?

이 경우는 TemplateView을 사용하는 데 어려움을 겪습니다. 반환하려는 항목이 템플릿 응답이 아니라면 다른보기 여야합니다. 그러나

...

난 당신이 메서드를 재정의해야합니다 같은데요하지만 어느 모르겠어요.

... 기존 TemplateView로 해킹 선호하는 경우에, 그래서 당신이되도록 get() 메서드를 재정의해야 할 것 ... ... 소스 코드에서

class TemplateView(TemplateResponseMixin, ContextMixin, View): 
    """ 
    A view that renders a template. This view will also pass into the context 
    any keyword arguments passed by the url conf. 
    """ 
    def get(self, request, *args, **kwargs): 
     context = self.get_context_data(**kwargs) 
     return self.render_to_response(context) 

주의 CSV를 반환 할 때 render_to_response()으로 전화하지 않습니다. 예를 들어 ...

class MyClassBasedView(TemplateView): 
    def get(self, request, *args, **kwargs): 
     if request.GET['csv'].lower() == 'true': 
      # Build custom HTTP response 
      return my_custom_response 
     else: 
      return TemplateView.get(request, *args, **kwargs) 

당신이 View의 모든 서브 클래스에 대한 일반적인 믹스 인이 필요하면, 나는 ... 당신이 뭔가를 할 수있을 것 같아요

class MyMixin(object): 
    def dispatch(self, request, *args, **kwargs): 
     if request.GET['csv'].lower() == 'true': 
      # Build custom HTTP response 
      return my_custom_response 
     else: 
      return super(MyMixin, self).dispatch(request, *args, **kwargs) 

class MyClassBasedView(MyMixin, TemplateView): 
    pass 
+0

이는 'TemplateView'에만 해당됩니다. 이것을 일반적으로 할 수있는 방법이 있습니까? 나는 템플리트 화 된 응답을 리턴 할 수 있도록 내 의견을 필요로한다. – Rico

+0

얼마나 일반적입니까? 'View'의 모든 서브 클래스? – Aya

+0

아마도. 우리는 실제로 메소드 기반보기로의 간단한 리다이렉션을 고려하고 있습니다. 클래스 기반보기에서는 너무 지저분 해 보입니다. 이것은 웹 사이트에 대한 일반적인 요구 사항처럼 보일 것입니다. 내가 처리 할 내장 믹스가 없다고 당혹 스럽습니다. 어쩌면 이것이 내 다음 오픈 소스 프로젝트 일 것입니다. 하하 – Rico

관련 문제