【问题标题】:Flask REST API record sender's IP addressFlask REST API 记录发送者的 IP 地址
【发布时间】:2021-01-20 01:33:39
【问题描述】:

我使用 Flask、SQLAlchemy 和 Marshmallow 创建了一个最小的 REST API。这是app.py文件:

from flask import Flask, request, jsonify
from flask_sqlalchemy import SQLAlchemy
from flask_marshmallow import Marshmallow
import os

# Initialize App
app = Flask(__name__)
basedir = os.path.abspath(os.path.dirname(__file__))

# Database Setup
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 'db.sqlite')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
# Init db
db = SQLAlchemy(app)
# Init marshmallow
ma = Marshmallow(app)


# Product Class/Model
class Product(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100), unique=True)
    description = db.Column(db.String(200))
    price = db.Column(db.Float)
    qty = db.Column(db.Integer)

    def __init__(self, name, description, price, qty):
        self.name = name
        self.description = description
        self.price = price
        self.qty = qty


# Product Schema
class ProductSchema(ma.Schema):
    class Meta:
        fields = ('id', 'name', 'description', 'price', 'qty')


# Init Schema
product_schema = ProductSchema()
products_schema = ProductSchema(many=True)


# Create Product
@app.route('/product', methods=['POST'])
def add_product():
    name = request.json['name']
    description = request.json['description']
    price = request.json['price']
    qty = request.json['qty']

    new_product = Product(name, description, price, qty)

    db.session.add(new_product)
    db.session.commit()

    return product_schema.jsonify(new_product)


# Get All Products
@app.route('/receive', methods=['GET'])
def get_products():
    all_products = Product.query.all()
    result = products_schema.dump(all_products)
    return jsonify(result)


# Run the Server
if __name__ == '__main__':
    app.run(debug=True)

我想通过GET方法提取发件人的IP地址。但是,发送者的 IP 不需要是 JSON 有效负载的一部分。

示例:POST

{
    "name": "Product 1",
    "description": "This is product 1",
    "price": 120.00,
    "qty": 100
}

获取

{
    "ip": "<whatever-the-ip>"
    "name": "Product 1",
    "description": "This is product 1",
    "price": 120.00,
    "qty": 100
}

如何在我的代码中实现此功能?我尝试使用request.remote_addr,但没有达到我的预期。

【问题讨论】:

  • remote_addr 有什么问题?这就是我使用的,我得到了正确的 IP、本地、生产等......你试过用 request.user_agent 仔细检查它吗?您可能会通过这种方式识别出请求不是来自正确的来源
  • 好的,那很好,但是我如何按照问题描述的方式在我的代码中实现它。
  • 基本上,你想将GET请求的IP添加到GET响应中?
  • 是的,所以当我发送一个 GET 请求时,输出将以问题所示的 JSON 格式抛出。

标签: rest flask sqlalchemy flask-sqlalchemy flask-restful


【解决方案1】:

您可以在返回之前以任何方式修改 GET 路由中的响应,我在序列化数据库结果后将请求的 IP 添加到响应中,如下所示:

# Get All Products
@app.route('/receive', methods=['GET'])
def get_products():
    all_products = Product.query.all()
    results = products_schema.dump(all_products)
    for product in results
        product.update({"ip": str(request.remote_addr)})
    return jsonify(results)

【讨论】:

  • 使用它运行时result.update({"ip": str(request.remote_addr)}) 抛出错误:AttributeError: 'list' object has no attribute 'update'
  • 哦,是的,我猜您要返回多个产品(“产品列表”,因此更新失败的原因)。正是为什么我建议将产品详细信息与您要返回的 IP 分开。或者,您必须遍历所有产品并使用 .update() 函数将 IP 单独添加到每个产品。
  • update 会将键值对添加到现有字典(一个产品)中。我编辑了我的答案,以便您可以遍历所有产品(来自您的数据库的列表),并将 IP 添加到所有产品。
猜你喜欢
  • 2023-04-11
  • 1970-01-01
  • 2013-02-05
  • 1970-01-01
  • 2014-07-22
  • 2017-12-05
  • 1970-01-01
  • 2011-04-15
相关资源
最近更新 更多