Python-接口开发入门
<p><strong>一、开发接口的作用:</strong></p><p>1、mock接口:模拟一些接口。有一些有关联的接口,在别的接口没有开发好的时候,需要用这个接口,就可以写一个假接口,返回想要的结果来模拟这个接口。</p>
<p>2、知道服务端的开发逻辑,有助于测试;</p>
<p>3、比如不想让其他人看很多数据库中的数据,可以通过接口只返回一部分数据。</p>
<p><strong>二、开发一个接口</strong></p>
<p>1、flask是一个轻量级的开发框架</p>
<p>__name__:代表当前这个python文件</p>
<p>server = flask.Flask(__name__) :把当前这个python文件,当做一个服务</p>
<p><img src="https://img2018.cnblogs.com/blog/1348269/201907/1348269-20190718190908883-1594903785.png"></p>
<p><strong>2、一个无需传参数的get接口</strong></p>
<p>其中,‘index’是接口的路径。</p>
<p>method如果不写,默认为get。如果需要支持多种,可以写成['get','post']</p>
<p>port是端口号,默认为5000。debug=True,这样改了代码之后,不需要重启服务,会自动重启。</p>
<p><img src="https://img2018.cnblogs.com/blog/1348269/201907/1348269-20190718192149449-1413962687.png"></p>
<p>先运行,然后用postman调用该接口,如下</p>
<p><img src="https://img2018.cnblogs.com/blog/1348269/201907/1348269-20190718192901127-271780281.png"></p>
<p>可以看到,中文的编码之后的,想显示中文,按照下图方法即可</p>
<p><img src="https://img2018.cnblogs.com/blog/1348269/201907/1348269-20190718193139574-1342504059.png"></p>
<p><strong>3、一个post接口</strong></p>
<p> 开发一个注册接口,请求参数为:username和passwd。如果数据库中有该用户,就返回用户已存在。如果该用户不存在,就在数据库插入一条数据,返回注册成功。</p>
<p>下面的代码需要连接数据库,连接数据库部分省略了。</p>
<p> <img src="https://img2018.cnblogs.com/blog/1348269/201907/1348269-20190718200623262-1124250358.png"></p>
<p> 为了让其他人也可以访问这个接口,可以用如下方法:</p>
<p><img src="https://img2018.cnblogs.com/blog/1348269/201907/1348269-20190731143753750-634378040.png"></p>
<p>host=0.0.0.0表示只要在同一个局域网,别人访问的时候,用你的ip就可以访问了。ip指的是电脑的ip。<br>假如电脑的ip是10.2.88.122,那么别人电脑访问10.2.88.122:8999/reg即可。</p>
<p><strong>三、开发接口目录</strong></p>
<p>目录结构如下</p>
<p><img src="https://img2018.cnblogs.com/blog/1348269/201907/1348269-20190731152519993-696164704.png"></p>
<p>主目录命名为my_api,可以根据实际情况命名</p>
<p>bin:可执行文件,即启动程序</p>
<p>config:配置文件</p>
<p>data:放置一些数据,如sql、入参等</p>
<p>lib:主逻辑</p>
<p>logs:log</p>
<p>readme:一些说明</p>
<p>我们把上面的代码分到各个目录里面</p>
<p>1、配置文件config-setting.py</p>
<p>存放一些常量,如数据库的信息,redis的信息,端口号等</p>
<p><img src="https://img2018.cnblogs.com/blog/1348269/201907/1348269-20190731153502950-999264187.png"></p>
<p> 2、lib目录下tools.py</p>
<p>tools文件里写了怎么操作sql和redis</p>
<p>倒入setting里的信息,需要把my_api加到环境变量里。</p>
<p>在my_api文件夹上右击,选择mark directory as ->Source Root</p>
<p>导入setting</p>
<p>如果常量太多,则可以直接from config import setting</p>
<p>使用时,setting.MYSQL_INFO。用setting加点的方法。</p>
<p><img src="https://img2018.cnblogs.com/blog/1348269/201907/1348269-20190731153616779-1559842481.png"></p>
<p> 3、lib目录下interface.py</p>
<p>这里写接口的主逻辑</p>
<p><img src="https://img2018.cnblogs.com/blog/1348269/201907/1348269-20190731173921911-1192211322.png"></p>
<p>4、bin目录下start.py</p>
<p> 先从interface中导入server,从setting中导入端口号。</p>
<p>启动程序时,只需运行start.py即可</p>
<p><img src="https://img2018.cnblogs.com/blog/1348269/201907/1348269-20190731174054943-1101281690.png"></p>
<p><strong> 四、有cookie,有依赖关系的接口开发</strong></p>
<p>1、目录结构同上,其中操作tools.py如下</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> redis,hashlib
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> pycharm帮你加环境变量</span><span style="color: rgba(0, 128, 0, 1)">
#</span><span style="color: rgba(0, 128, 0, 1)"> 在主目录my_api单击右键,Mark dictionary as 选sources root</span>
<span style="color: rgba(0, 0, 255, 1)">from</span> config.setting <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> REDIS_INFO
</span><span style="color: rgba(0, 0, 255, 1)">def</span> op_redis(k,v=None,time=<span style="color: rgba(0, 0, 0, 1)">None):
r </span>= redis.Redis(**<span style="color: rgba(0, 0, 0, 1)">REDIS_INFO)
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> v:
r.set(k,v,time)
res </span>= <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">ok</span><span style="color: rgba(128, 0, 0, 1)">'</span>
<span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)">:
res </span>=<span style="color: rgba(0, 0, 0, 1)"> r.get(k)
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> res:
res </span>=<span style="color: rgba(0, 0, 0, 1)"> res.decode()
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> res
</span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> my_md5(s):
md </span>=<span style="color: rgba(0, 0, 0, 1)"> hashlib.md5()
md.update(s.encode())
</span><span style="color: rgba(0, 0, 255, 1)">return</span> md.hexdigest()</pre>
</div>
<p>2、要求:(1)登录成功后,把cookie写入redis,其中key为 wind_session:username,value为session。 session生成规则是“username+当前时间(年月日时分秒格式)”组成的字符串进行md5加密(2)posts接口获取到要发表的文章的标题和内容,用session判断用户的登录状态,如果是登录状态,则文章可以发表,并写入redis。</p>
<p>分析:</p>
<p>(1)首先说登录接口,我们需要先生成session,然后存放到redis里。session按照要求,生成方式如下</p>
<p><img src="https://img2018.cnblogs.com/blog/1348269/201908/1348269-20190809165736211-1534913322.png"></p>
<p>写入redis直接调用tools里面的op_redis即可,过期时间这里是随便设置的6000s</p>
<p><img src="https://img2018.cnblogs.com/blog/1348269/201908/1348269-20190809165943478-738890586.png"></p>
<p>还有一步就是cookie</p>
<p><img src="https://img2018.cnblogs.com/blog/1348269/201908/1348269-20190809170136911-1618007626.png"></p>
<p>完整的登录代码如下。这里主要是为了说明cookie,因此没有对登录进行复杂的校验。最后会有完整的代码和运行结果,如果看的云里雾里,可以先看下运行结果。</p>
<p><img src="https://img2018.cnblogs.com/blog/1348269/201908/1348269-20190809172236408-1923705348.png"></p>
<p> (2)posts接口,需要获取到cookie,然后和redis中存的进行对比,如果一致,说明是登录状态,可以发表文章。</p>
<p> 获取cookie用下面的方法</p>
<p><img src="https://img2018.cnblogs.com/blog/1348269/201908/1348269-20190809171611686-737437676.png"></p>
<p>我们可以打印出来,看一下cookie的格式,如下,是字典格式。因此取session时,按照字典取值的方法即可。</p>
<p> <img src="https://img2018.cnblogs.com/blog/1348269/201908/1348269-20190809171649946-838750598.png"></p>
<p>对我们有用的cookie是以wind_session为开头的,其他的cookie我们不用关注。因此我们只选出这部分,取出session值,和redis中对比。</p>
<p>步骤为:</p>
<p>A、if语句中,是我们取到的cookie,从中提取出用户名和session。</p>
<p>B、从redis中取出对应用户的session</p>
<p>C、两者对比</p>
<p>D、如果是登录状态,返回文章发表成功,并且把文章写入redis。</p>
<p> <img src="https://img2018.cnblogs.com/blog/1348269/201908/1348269-20190809171937467-1770297982.png"></p>
<p> (3)完整代码</p>
<p>interface.py:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> flask,time,json
</span><span style="color: rgba(0, 0, 255, 1)">from</span> lib <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> tools
</span><span style="color: rgba(0, 0, 255, 1)">from</span> config <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> setting
server </span>= flask.Flask(<span style="color: rgba(128, 0, 128, 1)">__name__</span><span style="color: rgba(0, 0, 0, 1)">)
@server.route(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">/login</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> login():
username </span>= flask.request.values.get(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">username</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
pwd </span>= flask.request.values.get(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">pwd</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">if</span> username == <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">wind</span><span style="color: rgba(128, 0, 0, 1)">'</span> <span style="color: rgba(0, 0, 255, 1)">and</span> pwd == <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">123456</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">:
session_id </span>= tools.my_md5(username+time.strftime(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">%Y%m%d%H%M%S</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">))
key </span>= <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">wind_session:%s</span><span style="color: rgba(128, 0, 0, 1)">'</span>%<span style="color: rgba(0, 0, 0, 1)">username
tools.op_redis(key,session_id,</span>6000<span style="color: rgba(0, 0, 0, 1)">)
res </span>= {<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">session_id</span><span style="color: rgba(128, 0, 0, 1)">'</span>:session_id,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">error_code</span><span style="color: rgba(128, 0, 0, 1)">'</span>:0,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">msg</span><span style="color: rgba(128, 0, 0, 1)">'</span>:<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">登录成功</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">login_time</span><span style="color: rgba(128, 0, 0, 1)">'</span>:time.strftime(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">%Y%m%d%H%M%S</span><span style="color: rgba(128, 0, 0, 1)">'</span>)}<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">给用户返回的信息</span>
json_res = json.dumps(res,ensure_ascii=False)<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">返回结果为json格式</span>
res = flask.make_response(json_res) <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">cookie 构造成返回结果的对象</span>
res.set_cookie(key,session_id,6000)<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">最后的数字是cookie的失效时间</span>
<span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> res
@server.route(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">/posts</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> posts():
</span><span style="color: rgba(0, 0, 255, 1)">print</span>(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">all_cookies</span><span style="color: rgba(128, 0, 0, 1)">'</span>,flask.request.cookies) <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">字典形式</span>
cookies = flask.request.cookies <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">获取到所有的cookie</span>
username = <span style="color: rgba(128, 0, 0, 1)">''</span> <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">定义这两个变量是为了在没有传cookie时用的</span>
session = <span style="color: rgba(128, 0, 0, 1)">''</span>
<span style="color: rgba(0, 0, 255, 1)">for</span> cookie <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> cookies:
</span><span style="color: rgba(0, 0, 255, 1)">if</span> cookie.startswith(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">wind_session</span><span style="color: rgba(128, 0, 0, 1)">'</span>): <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">判断cookie以syz_session开头的话,取到它</span>
username = cookie<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">或者username = key session = value</span>
session = cookies.get(cookie) <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">调用接口时,用户传的session</span>
redis_session = tools.op_redis(username) <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">从redis中获取的</span>
<span style="color: rgba(0, 0, 255, 1)">if</span> redis_session == session:<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">判断传过来的session和redis中存的一样</span>
title = flask.request.values.get(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">title</span><span style="color: rgba(128, 0, 0, 1)">'</span>) <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">获取文章标题</span>
content = flask.request.values.get(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">content</span><span style="color: rgba(128, 0, 0, 1)">'</span>) <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">获取文章内容</span>
article_key = <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">article:%s</span><span style="color: rgba(128, 0, 0, 1)">'</span>%title <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">key以article开头</span>
tools.op_redis(article_key,content) <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">把文章写入redis</span>
res = {<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">msg</span><span style="color: rgba(128, 0, 0, 1)">'</span>:<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">文章发表成功!</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">code</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">:0}
</span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)">:
res </span>= {<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">msg</span><span style="color: rgba(128, 0, 0, 1)">'</span>:<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">用户未登录</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">code</span><span style="color: rgba(128, 0, 0, 1)">'</span>:2009<span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> print('username:',username)</span>
<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> print('session:',session)</span>
<span style="color: rgba(0, 0, 255, 1)">return</span> json.dumps(res,ensure_ascii=False)</pre>
</div>
<p>运行结果:</p>
<p>1、login接口</p>
<p><img src="https://img2018.cnblogs.com/blog/1348269/201908/1348269-20190809170811067-1660355796.png"></p>
<p>框起来的,是本次运行的cookie</p>
<p><img src="https://img2018.cnblogs.com/blog/1348269/201908/1348269-20190809170835828-1046208927.png"></p>
<p>redis里如下</p>
<p><img src="https://img2018.cnblogs.com/blog/1348269/201908/1348269-20190809170954653-728203641.png"></p>
<p>2、posts接口</p>
<p><img src="https://img2018.cnblogs.com/blog/1348269/201908/1348269-20190809171126602-1907403046.png"></p>
<p>redis中</p>
<p><img src="https://img2018.cnblogs.com/blog/1348269/201908/1348269-20190809171211167-83268299.png"></p>
<p><strong> 五、配置环境变量的方法</strong></p>
<p>以上接口开发时,我们调用自己写的方法,是通过先把new_api文件夹mark as source root。这样在pycharm运行是没问题的,但是如果我们把代码在其他设备上使用,或者直接用命令行启动,就会有问题。</p>
<p>直接在命令行运行如下,会发现很多模块是找不到的。</p>
<p><img src="https://img2018.cnblogs.com/blog/1348269/201908/1348269-20190813164801735-384104257.png"></p>
<p>如果把new_api添加到环境变量,就可以运行。</p>
<p>方法一:直接把new_api的路径添加到环境变量,但是这种方法不灵活,一旦文件换了位置,或者换个设备,需要重新修改路径</p>
<p><img src="https://img2018.cnblogs.com/blog/1348269/201908/1348269-20190813165031553-26765873.png"></p>
<p>方法二:自动获取路径,添加到环境变量</p>
<p> __file__:获取当前路径,这个路径分隔符是“/”,不能直接添加到环境变量</p>
<p> os.path.abspath(__file__):当前路径,分隔符是"\",可以直接添加到环境变量</p>
<p>os.path.dirname():取上一级目录</p>
<p>这里完整的添加环境变量方法为:</p>
<p><img src="https://img2018.cnblogs.com/blog/1348269/201908/1348269-20190813165816678-2132770301.png"></p>
<p>添加之后,就可以直接用命令行启动服务了。</p>
<p> </p><br><br>
来源:https://www.cnblogs.com/zhxwind/p/11202629.html
頁:
[1]