我的问题是一般的问题,但具体来说我的应用程序是Django的login_required装饰器.
我很好奇是否有办法检查视图/函数是否有特定的装饰器(在这种情况下是login_required装饰器)
我将用户注销后重定向,如果当前页面上有login_required装饰器,我想重定向到主页面.到目前为止,我的搜索没有得到任何结果.
我在几个例子中注意到我看到这样的事情:
# Comments explaining code i think
@innerclass
Run Code Online (Sandbox Code Playgroud)
要么:
def foo():
"""
Basic Doc String
"""
@classmethod
Run Code Online (Sandbox Code Playgroud)
谷歌搜索并没有让我走得太远,只是对这是什么的一般定义.另外我在python文档中找不到任何东西.
这些怎么办?
我有一个对象层次结构,其中几乎所有方法都是类方法.它看起来如下:
class ParentObject(object):
def __init__(self):
pass
@classmethod
def smile_warmly(cls, the_method):
def wrapper(kls, *args, **kwargs):
print "-smile_warmly - "+kls.__name__
the_method(*args, **kwargs)
return wrapper
@classmethod
def greetings(cls):
print "greetings"
class SonObject(ParentObject):
@classmethod
def hello_son(cls):
print "hello son"
@classmethod
def goodbye(cls):
print "goodbye son"
class DaughterObject(ParentObject):
@classmethod
def hello_daughter(cls):
print "hello daughter"
@classmethod
def goodbye(cls):
print "goodbye daughter"
if __name__ == '__main__':
son = SonObject()
son.greetings()
son.hello_son()
son.goodbye()
daughter = DaughterObject()
daughter.greetings()
daughter.hello_daughter()
daughter.goodbye()
Run Code Online (Sandbox Code Playgroud)
给定的代码输出如下:
greetings
hello son
goodbye son
greetings
hello daughter …Run Code Online (Sandbox Code Playgroud) 我可以创建一个枚举类RockPaperScissors,使ROCK.value == "rock"and ROCK.beats == SCISSORS,where ROCK和SCISSORS均为常量RockPaperScissors吗?
我已经创建了一堆函数,除了所有这些函数之外我需要非常相似,但我讨厌有这么多的try和除了子句和每个函数内部相同的代码.例如:
import sys
import random
def foo():
num=random.random()
try:
if num>0.5: print 'OK'
elif num>0.25: raise NameError('Too Small')
else: raise KeyboardInterrupt
except NameError:
print "%s had a NameError" % sys._getframe().f_code.co_name
except:
print "%s had a different Error" % sys._getframe().f_code.co_name
def bar():
num=random.random()
try:
if num>0.8: print 'OK'
elif num>0.6: raise NameError('Too Small')
else: raise KeyboardInterrupt
except NameError:
print "%s had a NameError" % sys._getframe().f_code.co_name
except:
print "%s had a different Error" % sys._getframe().f_code.co_name
Run Code Online (Sandbox Code Playgroud)
"try"之后的代码对于函数是不同的,但是"except"之后的代码是相同的.我想整合除语句之外的那些,这样它们就不会让我的代码看起来如此狭窄.有没有办法做到这一点?
对于这个抽象的问题,我回到了我的CLOS(Common Lisp对象系统)时代.
我正在扩大问题以澄清:
在我看来,Python装饰器有点像CLOS中的"around"方法.
根据我的记忆,CLOS中的"around"方法是一个包装同名主要方法/函数的方法/函数. 它也会遍历子类. 这是一些语法(我抓住了我的书).
所有这些方法 这将是一个类中:
(defmethod helloworld ()
(format t "Hello World"))
Run Code Online (Sandbox Code Playgroud)
也可以在方法之前和之后(我为了完整而投入):
(defmethod helloworld :before ()
(format t "I'm executing before the primary-method"))
(defmethod helloworld :after ()
(format t "I'm executing after the primary-method"))
Run Code Online (Sandbox Code Playgroud)
最后是around方法(注意这个方法看起来像装饰器):
(defmethod helloworld :around ()
(format t "I'm the most specific around method calling next method.")
(call-next-method)
(format t "I'm the most specific around method done calling next method."))
Run Code Online (Sandbox Code Playgroud)
我相信输出将是:
I'm the most specific around method …Run Code Online (Sandbox Code Playgroud) 我正在使用django-registration,我正在尝试连接其信号以自动创建UserProfile.
信号定义:
from django.dispatch import Signal
# A new user has registered.
user_registered = Signal(providing_args=["user", "request"])
Run Code Online (Sandbox Code Playgroud)
信号由django-registration发送:
def register(self, request, **kwargs):
"""
Create and immediately log in a new user.
"""
username, email, password = kwargs['username'], kwargs['email'], kwargs['password1']
User.objects.create_user(username, email, password)
# authenticate() always has to be called before login(), and
# will return the user we just created.
new_user = authenticate(username=username, password=password)
login(request, new_user)
signals.user_registered.send(sender=self.__class__,
user=new_user,
request=request)
return new_user
Run Code Online (Sandbox Code Playgroud)
我的信号连接:
from registration.signals import *
from core.models import UserProfile
from …Run Code Online (Sandbox Code Playgroud) 在我的Flask-App中,我定义了一个这样的视图函数:
@app.route("/some/restricted/stuff")
@login_required
def main():
return render_template("overview.html",
stuff = getstuff() )
Run Code Online (Sandbox Code Playgroud)
装饰器被定义为:
def login_required(something):
@wraps(something)
def wrap(*args, **kwargs):
if "some_admin_name" in session:
return something(*args, **kwargs)
else:
flash("\"You shall not pass!\" - Gandalf")
return redirect(url_for("login"))
return wrap
Run Code Online (Sandbox Code Playgroud)
我基本上只是复制粘贴,因为我发现了一些使用此代码的来源,但没有解释.
很容易理解代码的作用:它允许我使用在app.route()之后和main()之前为每个请求调用的装饰器,允许我执行诸如检查活动登录之类的东西.
所以,作为一个Flask/Python新手,我只想知道这是如何起作用的,尤其是:
- 什么是"某事"的论点?这是请求吗?!
- 什么是args和kwargs(关键字参数?)?
- 为什么我必须在方法中包装一个方法来将其用作装饰器?
- 这只适用于烧瓶吗?还有其他情况可以派上用场吗?
为什么以下两个脚本不等同?
(取自另一个问题:了解Python装饰器)
def makebold(fn):
def wrapped():
return "<b>" + fn() + "</b>"
return wrapped
def makeitalic(fn):
def wrapped():
return "<i>" + fn() + "</i>"
return wrapped
@makebold
@makeitalic
def hello():
return "hello world"
print hello() ## returns <b><i>hello world</i></b>
Run Code Online (Sandbox Code Playgroud)
并有装饰装饰:
def makebold(fn):
def wrapped():
return "<b>" + fn() + "</b>"
return wrapped
@makebold
def makeitalic(fn):
def wrapped():
return "<i>" + fn() + "</i>"
return wrapped
@makeitalic
def hello():
return "hello world"
print hello() ## TypeError: wrapped() takes no …Run Code Online (Sandbox Code Playgroud) 我想在函数中实现一个可选的记录器.就像是:
def foo(arg1, arg2, arg3, logger=None):
logger = logger or (lambda *x: None)
...
self.logger.debug("The connection is lost.")
Run Code Online (Sandbox Code Playgroud)
我想在记录器存在的情况下进行日志记录.否则,记录器的调试将不起作用.
基本上,实现它的简单方法是将每个调试语句嵌套在一个if logger块中,但是当有许多调试语句时它似乎很乱.