想用装饰器打开pymongo数据库连接
Looking to open pymongo database connection with decorator
@api.route('/api/get_contacts')
def get_contacts():
with pymongo.MongoClient(f"mongodb+srv://{mongo_username}:{mongo_password}@dev.glstt.mongodb.net/xxxx?retryWrites=true&w=majority") as document:
看太多了。我想把它变成:
@api.route('/api/get_contacts')
@mongo
def get_contacts():
问题是,我不是很懂装饰器。
所以,这就是我到目前为止所做的:
def mongo(f):
@wraps(f)
def wrap (*args,**kwargs):
with pymongo.MongoClient(f"mongodb+srv://{mongo_username}:{mongo_password}@dev.glstt.mongodb.net/xxx?retryWrites=true&w=majority") as document:
return f(document)
return wrap
不确定我需要做什么才能让装饰器在代码前添加 'with operator',并传递 x,然后将文档返回给路由函数。
装饰器的工作原理基本上是用 decorator(function)
替换您的函数。例如:
@decorator
def my_function():
pass
等于
def my_function():
pass
my_function = decorator(my_function)
这意味着您可以 return 来自装饰器的可调用函数,每次您使用参数调用它时,它都会使用特定参数调用装饰函数。
例如:
import functools
def decorator(decorated_function):
@functools.wraps(decorated_function) # This means that the function that returns from this decorator, "wrapper", will keep the decorated_function's name, `__doc__` argument and more.
def wrapper(*args, **kwargs):
"""
Every time you will call the function that returned from the decorator, this function will be called with the particular arguments in args and kwargs.
"""
return decorated_function(*args, **kwargs) + 10
return wrapper
@decorator
def func(n):
return n * 2
result = func(2) # here we called the function `wrapper`, the result is func(2) + 10, as we did when we called the function.
print(result) # 14
我们也可以 print(func)
结果会是这样的
<function func at 0x7f5eb16b0040>
,如果我们不使用 functools.wraps
:<function decorator.<locals>.wrapper at 0x7fba9ba0f040>
.
现在回答你的问题,
当你堆叠装饰器时,
@c
@b
@a
def func(): pass
顺序是
c(b(a(func)))
因此,名为 mongo
的函数应该从 api.route('/api/get_contacts')
获取参数“request”。 (我不知道这是什么框架,所以我无法预测这个框架是否将请求作为函数参数提供)。
如果框架不将请求作为参数传递:
def mongo(f):
@functools.wraps(f)
def wrap():
with pymongo.MongoClient(f"mongodb+srv://{mongo_username}:{mongo_password}@dev.glstt.mongodb.net/xxx?retryWrites=true&w=majority") as document:
return f(document)
return wrap
如果是:
def mongo(f):
@functools.wraps(f)
def wrap(request):
# do something with the request
with pymongo.MongoClient(f"mongodb+srv://{mongo_username}:{mongo_password}@dev.glstt.mongodb.net/xxx?retryWrites=true&w=majority") as document:
return f(document)
return wrap
然后它允许你这样做:
@api.route('/api/get_contacts')
@mongo
def get_contacts(document):
pass
@api.route('/api/get_contacts')
def get_contacts():
with pymongo.MongoClient(f"mongodb+srv://{mongo_username}:{mongo_password}@dev.glstt.mongodb.net/xxxx?retryWrites=true&w=majority") as document:
看太多了。我想把它变成:
@api.route('/api/get_contacts')
@mongo
def get_contacts():
问题是,我不是很懂装饰器。 所以,这就是我到目前为止所做的:
def mongo(f):
@wraps(f)
def wrap (*args,**kwargs):
with pymongo.MongoClient(f"mongodb+srv://{mongo_username}:{mongo_password}@dev.glstt.mongodb.net/xxx?retryWrites=true&w=majority") as document:
return f(document)
return wrap
不确定我需要做什么才能让装饰器在代码前添加 'with operator',并传递 x,然后将文档返回给路由函数。
装饰器的工作原理基本上是用 decorator(function)
替换您的函数。例如:
@decorator
def my_function():
pass
等于
def my_function():
pass
my_function = decorator(my_function)
这意味着您可以 return 来自装饰器的可调用函数,每次您使用参数调用它时,它都会使用特定参数调用装饰函数。
例如:
import functools
def decorator(decorated_function):
@functools.wraps(decorated_function) # This means that the function that returns from this decorator, "wrapper", will keep the decorated_function's name, `__doc__` argument and more.
def wrapper(*args, **kwargs):
"""
Every time you will call the function that returned from the decorator, this function will be called with the particular arguments in args and kwargs.
"""
return decorated_function(*args, **kwargs) + 10
return wrapper
@decorator
def func(n):
return n * 2
result = func(2) # here we called the function `wrapper`, the result is func(2) + 10, as we did when we called the function.
print(result) # 14
我们也可以 print(func)
结果会是这样的
<function func at 0x7f5eb16b0040>
,如果我们不使用 functools.wraps
:<function decorator.<locals>.wrapper at 0x7fba9ba0f040>
.
现在回答你的问题, 当你堆叠装饰器时,
@c
@b
@a
def func(): pass
顺序是
c(b(a(func)))
因此,名为 mongo
的函数应该从 api.route('/api/get_contacts')
获取参数“request”。 (我不知道这是什么框架,所以我无法预测这个框架是否将请求作为函数参数提供)。
如果框架不将请求作为参数传递:
def mongo(f):
@functools.wraps(f)
def wrap():
with pymongo.MongoClient(f"mongodb+srv://{mongo_username}:{mongo_password}@dev.glstt.mongodb.net/xxx?retryWrites=true&w=majority") as document:
return f(document)
return wrap
如果是:
def mongo(f):
@functools.wraps(f)
def wrap(request):
# do something with the request
with pymongo.MongoClient(f"mongodb+srv://{mongo_username}:{mongo_password}@dev.glstt.mongodb.net/xxx?retryWrites=true&w=majority") as document:
return f(document)
return wrap
然后它允许你这样做:
@api.route('/api/get_contacts')
@mongo
def get_contacts(document):
pass