2012-01-04 27 views
32

Tôi đã thực hiện một số mã hóa với Chai. Nó thực sự đơn giản và phù hợp với nhu cầu của tôi. Tuy nhiên, tôi đã gắn bó khi tôi cố gắng đưa ứng dụng vào một lớp học:Khuôn khổ chai và OOP, sử dụng phương pháp thay vì chức năng

import bottle 
app = bottle 

class App(): 
    def __init__(self,param): 
     self.param = param 

    # Doesn't work 
    @app.route("/1") 
    def index1(self): 
     return("I'm 1 | self.param = %s" % self.param) 

    # Doesn't work 
    @app.route("/2") 
    def index2(self): 
     return("I'm 2") 

    # Works fine 
    @app.route("/3") 
    def index3(): 
     return("I'm 3") 

Có thể sử dụng các phương pháp thay vì chức năng trong chai không?

+0

tại sao không bottleCBV https://github.com/techchunks/bottleCBV – Adeel

Trả lời

36

Mã của bạn không hoạt động vì bạn đang cố định tuyến đến các phương pháp không bị ràng buộc. Các phương thức không ràng buộc không có tham chiếu đến self, làm thế nào chúng có thể, nếu trường hợp của App chưa được tạo?

Nếu bạn muốn định tuyến với các phương pháp lớp học, trước tiên bạn phải khởi tạo lớp học của bạn và sau đó bottle.route() với các phương pháp trên đối tượng đó như sau:

import bottle   

class App(object): 
    def __init__(self,param): 
     self.param = param 

    def index1(self): 
     return("I'm 1 | self.param = %s" % self.param) 

myapp = App(param='some param') 
bottle.route("/1")(myapp.index1) 

Nếu bạn muốn gắn bó định nghĩa các tuyến đường gần các trình xử lý, bạn có thể làm một cái gì đó như thế này:

def routeapp(obj): 
    for kw in dir(app): 
     attr = getattr(app, kw) 
     if hasattr(attr, 'route'): 
      bottle.route(attr.route)(attr) 

class App(object): 
    def __init__(self, config): 
     self.config = config 

    def index(self): 
     pass 
    index.route = '/index/' 

app = App({'config':1}) 
routeapp(app) 

Đừng làm phần bottle.route() trong App.__init__(), bởi vì bạn sẽ không thể tạo ra hai trường hợp của App lớp.

Nếu bạn thích cú pháp của trang trí hơn thiết lập thuộc tính index.route=, bạn có thể viết một trang trí đơn giản:

def methodroute(route): 
    def decorator(f): 
     f.route = route 
     return f 
    return decorator 

class App(object): 
    @methodroute('/index/') 
    def index(self): 
     pass 
+0

Điều đó rất hữu ích, Cảm ơn bạn Skirmantas! –

+3

Lưu ý rằng 'bottle.route (attr.route, attr)' sẽ không hoạt động như dự định; bạn muốn 'bottle.route (attr.route) (attr)' (bởi vì bottle.route() là một trình trang trí, trả về một cuộc gọi, sau đó tiêu thụ '(attr)'). – larsks

+0

Cảm ơn bạn đã lưu ý! Sửa lỗi. – Ski

20

Dưới đây hoạt động độc đáo cho tôi :) đối tượng Khá định hướng và dễ dàng để làm theo.

from bottle import Bottle, template 

class Server: 
    def __init__(self, host, port): 
     self._host = host 
     self._port = port 
     self._app = Bottle() 
     self._route() 

    def _route(self): 
     self._app.route('/', method="GET", callback=self._index) 
     self._app.route('/hello/<name>', callback=self._hello) 

    def start(self): 
     self._app.run(host=self._host, port=self._port) 

    def _index(self): 
     return 'Welcome' 

    def _hello(self, name="Guest"): 
     return template('Hello {{name}}, how are you?', name=name) 

server = Server(host='localhost', port=8090) 
server.start() 
3

tôi mất @Skirmantas câu trả lời và sửa đổi nó một chút để cho phép cho các đối số từ khóa trong trang trí, giống như phương pháp, bỏ qua, vv:

def routemethod(route, **kwargs): 
    def decorator(f): 
     f.route = route 
     for arg in kwargs: 
      setattr(f, arg, kwargs[arg]) 
     return f 
    return decorator 

def routeapp(obj): 
    for kw in dir(obj): 
     attr = getattr(obj, kw) 
     if hasattr(attr, "route"): 
      if hasattr(attr, "method"): 
       method = getattr(attr, "method") 
      else: 
       method = "GET" 
      if hasattr(attr, "callback"): 
       callback = getattr(attr, "callback") 
      else: 
       callback = None 
      if hasattr(attr, "name"): 
       name = getattr(attr, "name") 
      else: 
       name = None 
      if hasattr(attr, "apply"): 
       aply = getattr(attr, "apply") 
      else: 
       aply = None 
      if hasattr(attr, "skip"): 
       skip = getattr(attr, "skip") 
      else: 
       skip = None 

      bottle.route(attr.route, method, callback, name, aply, skip)(attr) 
2

thử loại này, làm việc cho tôi, tài liệu cũng là khá tốt để bắt đầu với ...

https://github.com/techchunks/bottleCBV 
24

Bạn phải mở rộng lớp Bottle. Đó là các trường hợp là các ứng dụng web WSGI.

from bottle import Bottle 

class MyApp(Bottle): 
    def __init__(self, name): 
     super(MyApp, self).__init__() 
     self.name = name 
     self.route('/', callback=self.index) 

    def index(self): 
     return "Hello, my name is " + self.name 

app = MyApp('OOBottle') 
app.run(host='localhost', port=8080) 

Điều mà hầu hết các ví dụ ngoài kia đang làm, bao gồm cả các câu trả lời trước đó cung cấp cho câu hỏi này, tất cả đều tái sử dụng "ứng dụng mặc định", chứ không phải tạo riêng của họ, và không sử dụng sự tiện lợi của đối tượng định hướng và kế thừa.

+0

nếu bạn có hàng tá tuyến đường thì sao? –

+0

@ Alex-Bogdanov bạn phải xác định các tuyến đường của bạn theo cách này hay cách khác. Bạn có thể có các ký tự đại diện trong các tuyến đường của mình, cho phép bạn gọi một phương thức và cung cấp cho nó một tham số dựa trên tuyến đường bạn đã sử dụng. Điều này cho phép bạn có ít định nghĩa tuyến đường hơn cho các tuyến đường thực tế có thể. – jpcgt

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