2012-04-18 23 views
2

在Django应用程序,我比的观点,其返回JSON屈指可数,与调用类似于:在Django中讨论内容的最小化模板数量是多少?

return HttpResponse(json.dumps(content), mimetype="application/json") 

我要开始创建视图返回HTML或JSON根据从Accept头请求。可能还有其他类型,但这些是主要类型。我也想让多个URL路由到这个视图;文件扩展名“.html”和“.json”有助于告诉客户在提出请求时应该使用哪种类型的Accept,并且我想避免使用“?format = json”反模式。

什么是正确的,祝福的方式来做到这一点在Django与最少的样板或重复的代码?

(编辑:修改你才能更好地遵循SO的社会准则。)

+0

同意。改写。 – Corbin 2012-04-18 00:22:01

回答

2

我认为一个class-based view mixin(django 1.3+)是最简单的方法来做到这一点。您的所有视图都将从包含逻辑的基类继承,并用相应的内容进行响应。

1

我想我可能不会在这里看到你的大图片,但是这是我会做什么:

有一个HTML模板您在请求html时进行渲染,并在请求json时保留您的json.dumps(content)。似乎很明显,但我认为我应该提及它。

设置你的网址发送给你"json"'html'。 :

(r'^some/path/(?P<url_path>.*)\.(?P<extension>html|json)$', 'some.redirect.view'), 
(r'^/(?P<extension>html|json)/AppName', include(MyApp)), 
# etc etc 

和您的看法:

def myRedirectView(request, url_path, extension): 

    view, args, kwargs = resolve("/" + extension + "/" + urlPath) 
    kwargs['request'] = request 

    return view(*args, **kwargs) 

我知道这是一个有点模糊,因为我还没有完全想通了,但它在那里我将开始。

0

我已经通过创建一个基于Django自己的generic.View类的通用视图类来解决这个问题,该类定义了一个装饰器'accept_types'。这会修改应用的视图,以便在指示的内容类型不在Accept头中时返回None。然后,get()方法(其由generic.View调度员调用)看起来像这样:

def get(self, request): 
    self.request = request  # For clarity: generic.View does this anyway 
    resultdata = { 'result': data, etc. } 
    return (
     self.render_uri_list(resultdata) or 
     self.render_html(resultdata) or 
     self.error(self.error406values()) 
     ) 

实际视图渲染器从而饰:

@ContentNegotiationView.accept_types(["text/uri-list"]) 
def render_uri_list(self, resultdata): 
    resp = HttpResponse(status=200, content_type="text/uri-list") 
    # use resp.write(...) to assemble rendered response body 
    return resp 

@ContentNegotiationView.accept_types(["text/html", "application/html", "default_type"]) 
def render_html(self, resultdata): 
    template = loader.get_template('rovserver_home.html') 
    context = RequestContext(self.request, resultdata) 
    return HttpResponse(template.render(context)) 

的(一次性的)声明装饰通用视图类如下所示:

class ContentNegotiationView(generic.View): 
    """ 
    Generic view class with content negotiation decorators and generic error value methods 

    Note: generic.View dispatcher assigns HTTPRequest object to self.request. 
    """ 

    @staticmethod 
    def accept_types(types): 
     """ 
     Decorator to use associated function to render the indicated content types 
     """ 
     def decorator(func): 
      def guard(self, values): 
       accept_header = self.request.META.get('HTTP_ACCEPT',"default_type") 
       accept_types = [ a.split(';')[0].strip().lower() 
            for a in accept_header.split(',') ] 
       for t in types: 
        if t in accept_types: 
         return func(self, values) 
       return None 
      return guard 
     return decorator 

(在装饰处理的参数应该一概而论 - 此代码的工作,但现在仍处于发展为我写这篇文章的实际代码是在GitHub https://github.com/wf4ever/ro-manager/tree/develop/src/roverlay/rovweb/rovserver,但在适当的时候应该分开一个单独的包。 HTH。)