2012-01-04 12 views
32

He hecho algunos códigos con Bottle. Es realmente simple y se ajusta a mis necesidades. Sin embargo, llegué palo cuando trataba de envolver la aplicación en una clase:Estructura de botella y OOP, utilizando el método en lugar de la función

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") 

¿Es posible utilizar métodos en lugar de funciones en la botella?

+0

por qué no bottleCBV https://github.com/techchunks/bottleCBV – Adeel

Respuesta

36

Su código no funciona porque está intentando enrutar a métodos no enlazados. Los métodos no vinculados no tienen una referencia a self, ¿cómo podrían, si instancia de App no se ha creado?

Si desea crear una ruta métodos de clase, primero tiene que inicializar su clase y luego bottle.route() a métodos en ese objeto, así:

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) 

Si usted quiere meter las definiciones de las rutas de cerca de los manipuladores, se puede hacer algo como esto:

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) 

no hacer la parte bottle.route() en App.__init__(), porque no va a ser capaz de crear dos instancias de App clase.

Si te gusta la sintaxis de decoradores más de establecer atributo de index.route=, puede escribir un decorador simple:

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

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

Eso es muy útil, gracias Skirmantas! –

+3

Tenga en cuenta que 'bottle.route (attr.route, attr)' no funcionará como se esperaba; usted quiere 'bottle.route (attr.route) (attr)' (porque bottle.route() es un decorador, que devuelve un invocable, que luego consume '(attr)'). – larsks

+0

¡Gracias por la nota! Arreglado. – Ski

20

siguiente funciona muy bien para mí :) objeto Muy orientado y fácil de seguir.

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

Tomé respuesta @Skirmantas y modificar un poco para permitir argumentos de palabra clave en el decorador, como método, saltar, etc:

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

probar esto, trabajado para mí, la documentación es también bastante decente para empezar con ...

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

hay que extender la clase Bottle. Sus instancias son aplicaciones 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) 

Lo que la mayoría de los ejemplos por ahí están haciendo, incluyendo las respuestas proporcionadas con anterioridad a esta pregunta, son todos reutilizar la "aplicación por defecto", no la creación de su propia, y no usar la conveniencia de la orientación a objetos y la herencia.

+0

¿y si tienes una docena de rutas? –

+0

@ Alex-Bogdanov tiene que definir sus rutas de una forma u otra. Puede tener comodines en sus rutas, lo que le permite llamar a un método y darle un parámetro basado en la ruta que utilizó. Esto le permite tener menos definiciones de ruta que las posibles rutas reales. – jpcgt

Cuestiones relacionadas