天天看點

Python裝飾器、Django自定義登入驗證

裝飾器是一個很著名的設計模式,經常被用于有切面需求的場景,較為經典的有插入日志、性能測試、事務處理等。

裝飾器其實就是一個工廠函數,它接受一個函數為參數,然後傳回一個新函數,其閉包中包含了原函數

1、簡單裝飾器:

def deco(func):
    def wrapper():
        print "start"
        func() #調用函數
        print "end"
    return wrapper

@deco
def myfun():
    print "run"

myfun()
           

由于裝飾器函數傳回的是原函數的閉包wrapper,實際上被裝飾後的函數就是wrapper,其運作方式就和wrapper一樣。相當于:

myfun=deco(myfun)

2、裝飾任意參數的函數:

def deco(func):
    def warpper(*args,**kw):
        print "start"
        func(*args,**kw)
        print "end"
    return warpper
	
@deco
def myfun1(param1):
    print "run with param %s"%(param1)
	
@deco
def myfun2(param1,param2):
    print "run with param %s and %s"%(param1,param2)
	
myfun1("something")
myfun2("something","otherthing")

# start
# run with param something
# end
# start
# run with param something and otherthing
# end
           

 3、帶參數的裝飾器

裝飾器接受一個函數作為參數,這個毋庸置疑。但是有時候我們需要裝飾器接受另外的參數。此時需要再加一層函數,實際上是定義了一個生成裝飾器的工廠函數,調用它,搭配需要的參數,來傳回合适的裝飾器

def log(text):
    def deco(func):
        def wrapper(*args,**kw):
            print text
            func(*args,**kw)
            print text + " again"
        return wrapper
    return deco
	
@log("hello")
def myfun(message):
    print message
	
myfun("world")

# hello
# world
# hello again
           

log=log("hello"),把傳回的deco函數指派給log,此時log相當于其包含text=“hello”的閉包

myfun=log(myfun),相當于把myfun傳入了deco函數,并且傳回wrapper,并指派給myfun,此時myfun相當于其裝飾後的閉包。

整體來看是myfun=log("hello")(myfun)

4、裝飾器帶類參數

class locker:  
    def __init__(self):  
        print("locker.__init__() should be not called.")
	
	@staticmethod  
    def acquire():  
        print("locker.acquire() called.(這是靜态方法)")
		
	@staticmethod  
    def release():  
        print("  locker.release() called.(不需要對象執行個體)")
		
def deco(cls):  
    '''''cls 必須實作acquire和release靜态方法'''
	def _deco(func):  
        def __deco(): 
			print("before %s called [%s]." % (func.__name__, cls))  
            cls.acquire()  
            try:  
                return func()  
            finally:  
                cls.release()
		return __deco  
    return _deco
	
@deco(locker)  
def myfunc():  
    print(" myfunc() called.")
	
myfunc()  
myfunc()
           

 5、django自定義裝飾器實作登入驗證

def Check_Login(func):  #自定義登入驗證裝飾器
    def warpper(request,*args,**kwargs):
        is_login = request.session.get('IS_LOGIN', False)
        if is_login:
            func(request,*args,**kwargs)
        else:
            return HttpResponseRedirect("/polls/login_user")
    return warpper

def login_user(request):
    if request.method == 'POST':
        form = LoginForm(request.POST)
        if form.is_valid():
            all_data = form.clean()   #擷取post資料,例如 {'username': u'yang1', 'password': 111}
            exist = User.objects.filter(username = all_data['Form_username'],password = all_data['Form_password']).first()
            if exist:
                request.session['IS_LOGIN'] = True  #設定session的随機字段值
                request.session['uname'] = exist.username   #設定uname字段為登入使用者
                return HttpResponseRedirect('/polls/home')
            else:
                return HttpResponse("賬戶或密碼錯誤")
    else:
        form = LoginForm()
    return render(request, 'polls/login_user.html', {'form': form})

@Check_Login
def home(request):
        username = request.session.get('uname', False)   #擷取登入使用者名
        return render(request, 'polls/home.html', {'username': username}) #使用者名渲染到前端頁面
           

轉載于:https://www.cnblogs.com/honey-badger/p/8978168.html