Python学习之路--Flask+MongoDB搭建Restful Server

在开发客户端的时候总是需要网络请求的,之前用过java的,node的,感觉都不是非常的方便。再加上机器学习越来越火,索性就用python来开发下web。

1 准备

1.1 Flask

python的主流web框架有django和flask,这里使用了flask。flask是python编写的轻量级 Web 应用框架。

1.2 MongoDB

  • MongoDB 是一个基于分布式文件存储的数据库。由 C++ 语言编写。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。
  • MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。

数据库的命令行简单操作:

mongo
> show dbs
admin    0.078GB
config   0.078GB
local    0.078GB
todoApp  0.078GB
> use todoApp
switched to db todoApp
> show collections
accounts
device
device1
system.indexes
user
> db.user.find()
{ "_id" : ObjectId("5a4874bd377863486d2bbd62"), "name" : "test1", "password" : "123456" }
{ "_id" : ObjectId("5a487b143778634acfa46901"), "name" : "test2", "password" : "123456", "device" : ObjectId("5a43a35e37786301612a7b33"), "devices" : [ ObjectId("5a43a35e37786301612a7b33"), ObjectId("5a43a36937786301612a7b34"), ObjectId("5a43a37f37786301752f889c"), ObjectId("5a45ce5a3778631d5636391f") ], "emdevices" : [ { "_id" : ObjectId("5a43a35e37786301612a7b33"), "devicename" : "device1", "macaddr" : "00:11:22:33:44:55" }, { "_id" : ObjectId("5a43a36937786301612a7b34"), "devicename" : "device1", "macaddr" : "00:11:22:33:44:55" }, { "_id" : ObjectId("5a43a37f37786301752f889c"), "devicename" : "device1", "macaddr" : "00:11:22:33:44:55" }, { "_id" : ObjectId("5a45ce5a3778631d5636391f"), "devicename" : "test3", "macaddr" : "00:11:22:33:44:55" } ] }
> db.device.find()
{ "_id" : ObjectId("5a41e13337786350a4d19faf"), "_updated" : ISODate("2017-12-26T05:42:11Z"), "devicename" : "test1", "macaddr" : "00:11:22:33:44:55", "_created" : ISODate("2017-12-26T05:42:11Z"), "_etag" : "b3fd2a4b62fc803529a5315a25ed7777e1c6229e" }
{ "_id" : ObjectId("5a41e2a237786350c4876f7d"), "_updated" : ISODate("2017-12-26T05:48:18Z"), "devicename" : "test2", "macaddr" : "11:11:22:33:44:55", "_created" : ISODate("2017-12-26T05:48:18Z"), "_etag" : "3dee3f048406c5eb5a591164ea9a4b5e2f6c2309" }
{ "_id" : ObjectId("5a41e2aa37786350c4876f7e"), "_updated" : ISODate("2017-12-26T05:48:26Z"), "devicename" : "test3", "macaddr" : "22:11:22:33:44:55", "_created" : ISODate("2017-12-26T05:48:26Z"), "_etag" : "ed88bc3d176d7645782ab2bcc7c30536d221f425" }
{ "_id" : ObjectId("5a41e35c377863510233e7ca"), "_updated" : ISODate("2017-12-26T05:51:24Z"), "devicename" : "test1", "macaddr" : "12:11:22:33:44:55", "_created" : ISODate("2017-12-26T05:51:24Z"), "_etag" : "04a2bf47976ff6dfce3447ca8ea18fcefd8025ae" }

1.3 各种包的安装

利用python的pip需要安装flask, mongengine等。

2 项目实践

先看下整个工程的目录结构,分为app,controllers和models。类似于mvc,其中view在这里还没有,主要是一些api,view的工作都是给客户端来实现的。

.
├── app
│   └── __init__.py
├── config.json
├── controllers
│   ├── __init__.py
│   ├── tasks.py
│   └── users.py
├── models
│   ├── device.py
│   ├── __init__.py
│   └── user.py
└── run.py

2.1 app模块

init.py是初始化的使用用到的。这里是创建了flask,主要在controller中使用,以及创建了mongodb,在models中使用。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from flask import Flask
from flask_mongoengine import MongoEngine

app = Flask(__name__)

app.config['MONGODB_SETTINGS'] = {
    'db':   'todoApp',
    'host': '127.0.0.1',
    'port': 27017
}

#app.config.from_pyfile('config.json')
db = MongoEngine(app)

#数据库对应的模型
#import models

#api的业务逻辑
import controllers

2.2 models模块

先看下device,这里定义了两个字段,一个devicename,一个macaddr。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from app import db

# 类名定义 collection
class Device1(db.Document):
    # 字段
    devicename = db.StringField()
    macaddr = db.StringField()

    def __str__(self):
        return "devicename:{} - macaddr:{}".format(self.devicename, self.macaddr)

再看下User模型,首先这里定义了name,password和phone几个简单的字段,就不多讲了。
然后定义了device,devices以及emdevices。ReferenceField表示一个引用,最终会引用上述定义的device模板中的实际的数据库数据。而EmbeddedDocumentField则会把实际的数据存入到User中。举个例子,如果device的devicename为“test”。然后devices和emdevices中都可以找到device并且他的名字为"test"。而当把device的表中的devicename改为“test_change”。那么在devices中只是用了引用,所以devicename也改为了“test_change”,而emdevices则还是"test"。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from app import db
from models.device import Device1

# 类名定义 collection
class User(db.Document):
    # 字段
    name = db.StringField(max_length=30, required=True)
    password = db.StringField(max_length=30, min_length=6, required=True)
    phone = db.StringField()
    device = db.ReferenceField(Device1)
    devices = db.ListField(db.ReferenceField(Device1))
    emdevices = db.ListField(db.EmbeddedDocumentField('Device1'))

    def __str__(self):
        return "name:{} - phone:{}".format(self.name, self.phone)

2.3 controller模块

这里定义了两个接口,一个是POST的“/todo/api/v1/user”接口,用来保存user字段信息。一个是GET的“/todo/api/v1/user”接口,用来获取当前的user接口的信息,比较简单。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from app import app
from flask import Flask, jsonify, request, abort
from datetime import datetime
from models.user import User
from models.device import Device1

@app.route('/todo/api/v1/user', methods=['GET'])
def get_user():
    devices = Device1.objects().all()
    print devices

    user = User.objects(name="test2").first()
    print user

    #user.update(device=device)
    #user.update(devices=devices)
    #print device.devicename

    #user.update(emdevices=devices)

    return jsonify({'userinfo': User.objects.all()}), 201

@app.route('/todo/api/v1/user', methods=['POST'])
def create_user():
    if not request.json or not 'name' in request.json or not 'password' in request.json:
        print(request)
        abort(400)

    user = User(name=request.json['name'], password=request.json['password']).save();
    return jsonify({'userinfo': User.objects.all()}), 201

2.4 运行项目

python run.py

接着可以通过postman来测试接口。可以的话,就可以在客户端使用网络请求了。

3 Linux自启动

3.1 nginx反向代理

nginx反向代理,因为python flask默认的是ip:127.0.0.1,端口5000,所以需要反向代理到我们的服务器上,这样对应域名就可以使用了。

server {
    listen 3000; # 监听3000端口
    location / {
        proxy_pass http://127.0.0.1:5000; # 代理本机127.0.0.1:5000的服务
    }
    location /static {
        #alias /home/ubuntu/myproject/myblog/app/static; # 负载均衡
    }
}

关于nginx怎么设置这里就不一一介绍了。

3.2 gunicorn

使用gunicorn在多核服务器上,为了支持更多的并发访问并充分利用资源,可以使用更多的 gunicorn 进程。

3.3 supervisor

supervisor是一个用 Python 写的进程管理工具,可以很方便的用来在linux系统下启动、重启(自动重启程序)、关闭进程(不仅仅是 Python 进程)。
在/etc/supervisor/conf.d/目录下新建test.config文件,配置如下

 [program:Test]
 command=/usr/local/bin/gunicorn -c /etc/gunicorn/gun.conf --chdir /todoApp run:app

supervisorctl 一些命令:

help # 查看帮助
status # 查看程序状态
stop program_name # 关闭 指定的程序
start program_name # 启动 指定的程序
restart program_name # 重启 指定的程序
tail -f program_name # 查看 该程序的日志

上述配置只需要执行:

supervisorctl  start Test

就可以在后台启动进程了。

后续扩展

基本上这样就可以搭建一个简单的restful的server了。当然结合上jwt(java web token)则更好点。这个就后续扩展吧。

代码可以参考: github中的例子
更完整的项目:极客Go云监工服务端

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 猿与汪的秘密 设计师:白松林 返回首页