Inspiration-python-django in the development of plugins and filter decorators

Source: Internet
Author: User

Writing this essay is because today in the process of writing plug-ins and filtering methods of the wall, tossing for a long time finally found some problems, write down in order to make a memo.

After looking at the plug-in mechanism of xadmin, I also want to use this idea to extend the method of view in Kadmin.

For example, in a login view, the general logic is as follows:

classLoginView (baseadminview):" "Login View" "Auth_form=none#form Classes for authenticationLogin_template=None title=""    defUpdate_login_params (self,defaults):" "hooks for modifying parameters before executing the login view function" "return defaults@never_cachedefGet (self,request,*arg,**Kwargs): fromDjango.contrib.auth.viewsImportLogin Context=self.get_context (Request,*arg,**kwargs)#Gets the context of the parent classcontext.update ({'title': Self.title,'App_path': Request.get_full_path, REDIRECT_FIELD_NAME:request.get_full_path (),}) Defaults={            'Extra_context': Context,'Authentication_form': Self.auth_formorAdminauthenticationform,'Template_name': Self.login_templateor 'kadmin/views/login.html',        }
       defaults=

return login (request,**def Post (self,request,*arg,** return self.get (Request,*arg,**kwargs)

We want to be able to update the context before executing the login function through the Update_login_params method, and the plugin should be used to take over the execution of the method to make some modifications as needed.

Here are two ways of thinking:

1, filter the results of Update_login_params and return

2, the use of plug-in functions, control the execution of Update_login_params (generally live update_login_params execution results The incoming plug-in function is modified by the plugin function and then returned)

You can also use the plug-in function to take over the update_login_params and decide for yourself whether to execute update_login_params or perform some behavior before or after Update_login_params execution.

From the above two points, the plug-in is more flexible and free, the control range is larger, the second filter can only operate on the return value of Update_login_params and return.

1. Filter

Define Filter Adorner @filter_hook

defFilter_hook (func):#Filter Adorner    #used to re-process the returned value of the hook methodFunc_name=func.__name__@wraps (func)defInner_func (self,*arg,**Kwargs):ifGetAttr (Self,'Filters', None): Filter_infos=[(GetAttr (FI,' Priority', (), FI) forFiinchSelf.filtersifFi.__name__==Func_name] Filters=[fi forP,fiinchSorted (filter_infos,key=LambdaX:x[0],reverse=False)] Result=func (self,*arg,**Kwargs) forFiinchFilters:result=fi (self,result,*arg,**Kwargs)returnresultElse:            returnFunc (self,*arg,**Kwargs)returnInner_func

Source code Description: Traverse filters on the View object self to get the filter function, filter the result and return the result

For example, we can define a filter to add parentheses to the return value of Say_hello.

@set_attr (attr_name='__name__', value='say_hello')  def add_tag (self,result,o,*arg,**Kwargs):    return"(%s)  "%result
classPerson:name='Akun'Sex="Akun-male"Plugins=[maleplugin (Sex_num) forSex_numinchRange (4)] Filters=[Add_tag] @filter_hook @plugin_hookdefSay_hello (self,go,*arg,**Kwargs):Print("-----------Done--------")        return "Hello I am%s"%Self.nameif __name__=="__main__": P=Person ()Print(P.say_hello ('Go'))

Description: @set_attr is an adorner that is responsible for setting the property value of the function, since Filter_hook is looking for a function with the same name as the hook when looking for the filter function, so Add_tag __name__ must be set to Say_hello

2. Plugins

To define a plug-in adorner:

defPlugin_chain (funcs,token,func,*arg,**Kwargs):ifToken==-1:        returnfunc () @wraps (func)def_inner_func (): Wrap_func=Funcs[token] Arg_specs=Getargspec (Wrap_func) [0]ifLen (arg_specs) ==1: func ()returnWrap_func (*arg,**Kwargs)elifLen (arg_specs) >=2 andarg_specs[1]=="__": Back=funcElse: Back=func ()returnWrap_func (back,*arg,**Kwargs)returnPlugin_chain (funcs,token-1,_inner_func,*arg,**Kwargs)defPlugin_hook (func): Func_name=func.__name__@wraps (func)defMethod (self,*arg,**Kwargs): @wraps (func)def_inner_func ():returnFunc (self,*arg,**Kwargs)ifGetAttr (Self,'Plugins', None): Plugin_funcs=[(GetAttr (P,func_name), GetAttr (GetAttr (P,func_name),' Priority', 10))                       forPinchSelf.pluginsifGetAttr (p,func_name,none)]Print(Plugin_funcs)#to add a to the plug-in method in ascending orderPlugin_funcs=[p forP,priorityinchSorted (plugin_funcs,key=LambdaX:x[1],reverse=False)] returnPlugin_chain (Plugin_funcs,len (Plugin_funcs) -1,_inner_func,*arg,**Kwargs)Else:            returnFunc (self,*arg,**Kwargs)returnMethod

Source code Description: Similar to @filter_hook just, note

 wrap_func=funcs[token] arg_specs  =ge Targspec (Wrap_func) [0]  if  len (arg_specs) ==1: Func ()  return  wrap_func (*arg,**kwargs)  elif  len (arg_specs) >=2 and< /span> arg_specs[1]==  " : Back  =func  else  : Back  =func ()  
     
      return 
      Wrap_func (Back,*arg,**kwargs) 

If the parameter named "__" is used to receive the return value of the hook method, __ will be set as the method of the hook, that is, the method of the hook can be taken over by the plugin.

We define a plugin to print out hooks before executing say_hello.

class Beforehook:    @set_attr (attr_name='priority', value=6)      def Say_hello (self,__,o,*arg,**Kwargs):        print("Theback is%s "%        __"return __ (*arg,**kwargs)

Here __ or is set as the method of being hook

Inspiration-python-django in the development of plugins and filter decorators

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.