Python 蟒蛇3“;“类别工厂”示例:API(令牌).MyClass()

Python 蟒蛇3“;“类别工厂”示例:API(令牌).MyClass(),python,design-patterns,factory,Python,Design Patterns,Factory,我正在为API编写一个python REST客户端 API需要身份验证,我希望在同一个脚本上运行多个API客户端对象 我当前的API代码如下所示: class-RestAPI: 定义初始化(self,id): self.id=id self.fetch() def提取(自): requests.get(self.url+self.id,auth=self.apikey) 类别购买(重新分类): url='1〕http://example.com/purchases/' 类别发票(发票): url

我正在为API编写一个python REST客户端

API需要身份验证,我希望在同一个脚本上运行多个API客户端对象

我当前的API代码如下所示:

class-RestAPI:
定义初始化(self,id):
self.id=id
self.fetch()
def提取(自):
requests.get(self.url+self.id,auth=self.apikey)
类别购买(重新分类):
url='1〕http://example.com/purchases/'
类别发票(发票):
url='1〕http://example.com/invoices/'
...
我想这样使用API:

api\u admin=api('adminmytoken')
api_user=api('usertoken')
…
金额=api_管理采购(2)。金额
api_用户。购买(2)。金额增加,因为api_用户未获得此购买的授权
问题是,每个对象都需要知道它是apikey,这取决于我要使用的客户端

在我看来,这种模式就像一个“类工厂”:RestAPI的所有类都需要知道所提供的令牌


在不手动为每个模型提供令牌的情况下,如何能够干净地做到这一点?

我认为这里的问题是您的设计有点落后。继承可能不是这里的关键。我可以做的是将api令牌作为用户类上的参数,然后将其传递给Rest接口上的实例级绑定:

class用户:
定义初始化(self,id,api_键,**kwargs):
self.\u rest=接口(id、api\u键、**kwargs)
def购买(自身、部分参数):
#接口本身进行实际的腿部工作,
#您只需使用APIUser通过接口调用函数
返回自我。_rest.fetch('PURCHASE',some_arg)
类接口:
方法={
#您需要的呼叫(类url)
‘购买’:(购买,’https://myexample.com/purchases'),
“发票”:(发票,”https://myexample.com/invoices'),
#在此处添加更多方法
}
定义初始化(self、id、key):
self.id=id
self.key=key
self.session=requests.session()
def_fetch(self、method、*args、**kwargs):
#做一些方法去获取数据
尝试:
#使用接口查找类对象
#你可能需要也可能不需要
_类,url=self.methods[method]
除KeyError外,如e:
raise VALUERROR(f“获取不支持的方法,应为”
来自e的f“{'\n.join(self.methods)}”)
headers=kwargs.pop('headers',{})
#我不确定这里的实际接口,也许你可以调用
#获取元数据的url,以使用第一个。。。
req=requests.Request(_class.http_方法,url+self.id,auth=self.key,headers=headers)。prepare()
resp=self.session.send(请求)
#这将提前提高401
针对_状态的相应提升_()
#可能您的对象使用了响应中的元数据
params=resp.json()
#仅当用户应该看到业务对象时才返回它
返回类(*args,**kwargs,**params)
类别购买:
http_方法='GET'
定义初始化(self,*args,**kwargs):
#使用json传递的参数在此处进行一些设置
#从api
user=APIUser(“令牌”、“密钥”)#这是我的用户会话
some_purchase=user.purchase(2)#将在请求会话中引发401未经授权的错误
admin=APIUser(“admintoken”、“adminkey”)#管理会话
部分采购=管理采购(2)
#返回一个购买对象
多少钱
您可能希望这样做的原因如下:

  • 如果你不被允许看到它,你就无法取回它
  • 现在rest接口控制着谁看到了什么,这与用户对象本身密不可分,而其他所有类都不需要知道发生了什么
  • 您可以在一个位置更改url(如果需要)
  • 您的业务对象只是业务对象,它们不需要做任何其他事情
  • 通过分离出您的对象实际上是什么,您仍然只需要向用户类传递一次api键和令牌。该接口绑定在实例上,仍然为同一脚本中的多个用户提供了灵活性


    您还可以得到显式调用的模型。如果您试图获取一个模型,您必须调用它,这时接口可以强制您进行身份验证。您不再需要业务对象强制您的身份验证

    谢谢您的回复。但是,当我有许多模型(例如:帐户、购买、发票)时,这真的很麻烦。当我想要“获取”一个模型时,我需要始终传递api_键,这似乎不太实用。@Frank也许这更实用一点。有很多方法可以做到这一点,上面的示例可能需要进行一些改进,但这样你就把api调用层与其他层分开了。我同意
    Account
    Purchase
    Invoice
    不需要api键read about@stovfl:I需要,但我不认为在给定上下文的情况下(在本例中:
    api\u admin
    api\u user
    )可以使用具有不同结果的同一类变量。“具有不同结果的类变量”:没错,也许我误解了你的问题。扩展你的例子,看看你的意图。我不认为继承是一条路要走。工厂可能是正确的答案,但每个对象都不应该知道apikey。如果有的话,应该有一个接口知道apikey和低级调用。然后,您的对象使用接口获取信息,而他们对api_键一无所知