2011-01-08 31 views
20
# /test{.format} no longer seems to work... 
config.add_route('test', '/test.{ext}', view='ms.views.test') 

views.py:Có cách nào tốt hơn để chuyển đổi giữa đầu ra HTML và JSON trong Kim tự tháp không?

from pyramid.response import Response 
from pyramid.renderers import render 

import json 

def test(request): 
    extension = request.matchdict['ext'] 
    variables = {'name' : 'blah', 'asd' : 'sdf'} 

    if extension == 'html': 
     output = render('mypackage:templates/blah.pt', variables, request=request) 

    if extension == 'json': 
     output = json.dumps(variables) 

    return Response(output) 

Có một cách dễ dàng hơn để làm điều này? Với giá treo, nó đơn giản:

def test(self, format='html'): 
    c.variables = {'a' : '1', 'b' : '2'} 

    if format == 'json': 
     return json.dumps(c.variables) 

    return render('/templates/blah.html') 

Tôi nghi ngờ tôi đang tiếp cận sai cách này ...?

+0

Khiếu nại của bạn là gì? Bạn có phàn nàn rằng kim tự tháp có API khác nhau từ giá treo? Nếu bạn không thích API của kim tự tháp, tại sao không quay trở lại Giá treo? –

+0

Pyramid có sử dụng middleware không? Tại sao bạn không thể hiển thị JSON dựa trên những gì người dùng yêu cầu? Làm bên trong khung nhìn trực tiếp, nằm trong cuốn sách của tôi, một giải pháp bị lỗi. Nếu có thể, hãy tận dụng lợi thế trên phần mềm trung gian. – Anders

Trả lời

6

Đây có phải là những gì bạn đang tìm kiếm không? Cột trụ và Kim tự tháp có các API khác nhau. Vì vậy, họ sẽ khác nhau. Bạn có thể làm cho chúng tương tự hơn một chút, nhưng bạn không thể làm cho chúng giống nhau.

def test(request): 
    extension = request.matchdict['ext'] 
    variables = {'name' : 'blah', 'asd' : 'sdf'} 

    if extension == 'json': 
     return Response(json.dumps(variables)) 

    return Response(render('mypackage:templates/blah.pt', variables, request=request)) 
+0

+1 đó là bản dịch một đến một ví dụ của OP. –

+0

@Tom Willis: không thể là câu hỏi thực sự. Có thể không? –

51

Tôi nghĩ, cách tốt hơn là thêm cùng một chế độ xem hai lần với trình kết xuất khác biệt. Giả sử chúng ta có quan điểm như sau:

def my_view(request): 
    return {"message": "Hello, world!"} 

Bây giờ trong cấu hình của chúng tôi, chúng tôi có thể thêm quan điểm tương tự hai lần:

from pyramid.config import Configurator 
config = Configurator() 
config.add_route('test', '/test', my_view, renderer="templates/my_template.mako") 
config.add_route('test', '/test', my_view, renderer="json", xhr=True) 

Những gì chúng ta có bây giờ:

  1. Xem my_view sẽ làm cho mẫu "templates/my_template.mako" với dict trả lại được cung cấp dưới dạng ngữ cảnh nếu chúng tôi sẽ trỏ trình duyệt của chúng tôi đến url /test.
  2. Nếu chúng tôi sẽ yêu cầu XHR với my_view sẽ được gọi lại, nhưng giờ đây lệnh trả về sẽ được mã hóa dưới dạng JSON và được truyền lại cho người gọi (vui lòng read docs về việc kiểm tra xem yêu cầu đã được thực hiện qua XHR) chưa.

Ý tưởng cùng chúng ta có thể sử dụng để xác định tuyến đường khác nhau nhưng với quan điểm tương tự gắn liền với chúng:

from pyramid.config import Configurator 
config = Configurator() 
config.add_route('test', '/test', my_view, renderer="templates/my_template.mako") 
config.add_route('test_json', '/test.json', my_view, renderer="json") 

Bây giờ /test sẽ kích hoạt mẫu vẽ, nhưng /test.json sẽ trở lại chuỗi chỉ JSON mã hóa.

Bạn có thể đi xa hơn và làm cho cử cho các renderer ngay qua accept đối số của add_router phương pháp:

from pyramid.config import Configurator 
config = Configurator() 
config.add_route('test', '/test', my_view, renderer="templates/my_template.mako") 
config.add_route('test', '/test', my_view, renderer="json", accept="application/json") 

Nếu yêu cầu đi kèm với giá trị tiêu đề Accept thiết lập để application/json JSON sẽ được trả lại, mẫu nếu không bạn bị trả lại.

Lưu ý, thao tác này sẽ chỉ hoạt động nếu bạn có các định dạng dữ liệu được xác định trước mà bạn muốn mã hóa phản hồi từ chế độ xem của mình nhưng đó là trường hợp thông thường. Trong trường hợp bạn cần gửi đi động, bạn có thể trang trí các chế độ xem của mình với đối số decorate của add_route sẽ chọn trình kết xuất phù hợp với quy tắc của bạn.

+3

+1 Tôi nghĩ điều này phản ánh tốt nhất cách "kim tự tháp" của việc làm. Nó linh hoạt, tách riêng các khung nhìn từ các trình kết xuất khiến cho các khung nhìn dễ dàng hơn khi kiểm tra đơn vị vì thay vì phân tích cú pháp một tài liệu html, bạn chỉ có thể tìm các giá trị trong từ điển. –

+0

Điều này có vẻ giống như một cách làm gọn gàng. Làm thế nào tôi sẽ đi về việc áp dụng phương pháp này để phương pháp xử lý của tôi? Tôi tìm thấy, trong tài liệu hướng dẫn, bạn có thể trang trí các chức năng với 'view_config' sẽ cho phép bạn đặt trình kết xuất đồ họa nhưng tôi không thể thấy tương đương với Công văn URL. – dave

+0

Không 'add_handler' hoạt động như thế này?Tôi chưa bao giờ làm việc với các trình xử lý, nhưng các trạng thái tài liệu, rằng "Bất kỳ đối số từ khóa bổ sung nào cũng được chuyển tới add_route." – andreypopp

2

Pyramid 's URL Dispatch là cơ chế rất mạnh mẽ và linh hoạt. Trước hết, chúng tôi sẽ viết mẫu url chính xác. Trong route pattern syntax chúng tôi có thể sử dụng regular expressions cho các điểm đánh dấu thay thế.

'/test{ext:\\..*}' 

Ở đây chúng ta có thể thấy đường dẫn url nên chứa. (dấu chấm) và sau đó là bất kỳ biểu tượng nào. Tất cả các biểu tượng bao gồm. (dấu chấm) sẽ nằm dưới khóa ext trong request.matchdict.

Tất nhiên, chúng ta có thể làm phức tạp các biểu thức chính quy để xác định những phần mở rộng có thể có:

'/test{ext:\\.(html|json)}' 

Sau đó chúng ta thêm đường với mô hình của chúng tôi:

config.add_route('test', 
       pattern='/test{ext:\\.(html|json)}') 

Bạn muốn thêm , chúng tôi có thể chỉ định tập hợp các tiện ích mở rộng bằng cách sử dụng custom predicates.

Để chỉ định tiện ích mở rộng mặc định, chúng tôi có thể sử dụng đơn giản pregenerator.

def default_extension(ext): 
    def pregenerator(request, elements, kw): 
     if 'ext' not in kw: 
      kw['ext'] = ext 

     return elements, kw 

    return pregenerator 

config.add_route('test', 
       pattern='/test{ext:\\.(html|json)}', 
       pregenerator=default_extension('.html')) 

request.route_path('test') 
# '/test.html' 
request.route_path('test', ext='.json') 
# '/test.json' 

Sau đó chúng tôi sẽ Traversal để giúp chúng tôi chuyển qua lại giữa htmljson đầu ra:

config.add_route('test', 
       '/test{ext:\\.(html|json)}', 
       pregenerator=default_extension('.html'), 
       traverse='{ext}') 

Với lập luận traverse trong add_route chúng tôi buộc ứng dụng của chúng tôi để được hybrid. Và chúng ta nên hiểu rằng nhà máy sẽ cung cấp bối cảnh cho quan điểm của chúng tôi không được chứa các khóa khớp với các phần mở rộng của chúng tôi. Nhà máy gốc mặc định không.

views.py:

from pyramid.view import view_config, view_defaults 


@view_defaults(route_name='test') 
class Test(object): 
    def __init__(self, request): 
     self.request = request 
     self.variables = { 
      'name': 'blah', 
      'asd': 'sdf' 
     } 

    @view_config(name='.html', renderer='mypackage:templates/blah.pt') 
    def html(request): 
     return { 
      'request': request, 
      'variables': self.variables 
     } 

    @view_config(name='.json', renderer='json') 
    def json(request): 
     return { 
      'request': request, 
      'variables': self.variables 
     } 

Dưới đây chúng tôi đã tạo class Test và ghi rõ tên đường cho nó. Và sau đó chúng tôi đã tách các phương thức theo tên của các tiện ích mở rộng của chúng tôi.

+0

Tôi thích sử dụng traversal để phân biệt hành vi trên các phần mở rộng khác nhau. Cấu hình xem có thể đơn giản hơn đáng kể. Nó có thể là một hàm duy nhất chấp nhận một yêu cầu được trang trí với 2 dòng '' view_config', cả hai đều có 'route_name', với' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' ' Nó làm cho ví dụ ít phức tạp hơn (chỉ 7 dòng mã). – Elmer

0

Hãy thử cách này:

def test(self, format='html'): 
    c.variables = {'a' : '1', 'b' : '2'} 

    if format == 'json': 
     return Response(json = c.variables) 

    return render_to_response('/templates/blah.html') 

Đây là giống nhất với ví dụ giá treo của bạn. Ngoài ra, nó cho thấy một số cách thân thiện hơn để hiển thị một mẫu hoặc một số JSON cho một phản hồi.

Các vấn đề liên quan