如何让 Flask 应用通过 URL 输入解析 JSON?即:website/RedMango 打开一个 RedMango JSON 对象的页面

How to make a Flask app parse JSON by URL input? ie: website/RedMango opens a page of a RedMango JSON object

为了澄清问题,使用 Flask URL converter how would one parse the json at this website by entering a url such as: https://ds-med-cabinet.herokuapp.com/strainjson/Purple-Kush 以便当用户访问 /Purple-Kush 网站时仅显示 json 对象?本网站仅用于构建一个 API 用于教育目的,因此我将不胜感激任何有关通过 URL 输入解析整个 json 的任何想法,很可能使用 Flask URL 转换器或任何其他实用方法。非常感谢您的时间和考虑。这是我试过的代码,作为 Flask URL 转换器文档的模型:

# Directory.py



# Import

from os import path
import pandas as pd
from flask import Blueprint, render_template
from werkzeug.routing import BaseConverter


# Make Blueprint for __init__.py

Directory = Blueprint("Directory", __name__)


# Import Leafly csv

file_name = path.join(path.dirname(__file__), "Leafly.csv")

df = pd.read_csv(file_name)

strains = df['Strain']



# Custom converter

class ListConverter(BaseConverter):

    def to_python(self, value):
        return value.split('+')

    def to_url(self, values):
        return '+'.join(BaseConverter.to_url(value)
                        for value in values)


# Flask Url-converter

@Directory.route('/<strain>')
def strain_url(strain):
    """Show the json object for the given strain."""
    strain = []
    for strain in strains:
        strain

    return render_template('json.html', strain=strain)
# __init__.py



# Imports

from flask import Flask
from web_app.routes.Directory import Directory, ListConverter
from web_app.routes.GET_PUT_API import GET_PUT_API


# Create Flask app

def create_app():
    
    app = Flask(__name__)

    app.register_blueprint(Directory)
    app.register_blueprint(GET_PUT_API)

    app.url_map.converters['list'] = ListConverter
    
    return app

if __name__ == "__main__":
    my_app = create_app()
    my_app.run(debug=True)

for 循环中的菌株是来自数据的 csv 版本的每个菌株的列表,正在渲染的 json.html 是 html 对象的 json 文件正在 this website 渲染。此代码和 /whateveristypedintheurl 只是呈现网站上共享的所有数据(因为 html 文件已经充满了 json 对象,并且没有任何内容被解析)。再次感谢您查看此内容。

Ps。如果尝试通过创建 Flask 应用程序来复制它,您可以找到 csv here 为 cannabis.csv(我将 named 切换为 Leafly.csv)并且您可以将 df 转换为 json 通过使用以下代码:

# dftojson.py


# Imports

from os import path
import csv
import json


file_path = r'C:\Users\johnj\OneDrive\Documents\Lambda\BuildWeek3\data-science\cannabis.csv'

csvfile = open(file_path, encoding="utf8")
jsonfile = open('cannabis.json', 'w')


fieldnames = ("Strain", "Type", "Rating", "Effects", "Flavor"," Description")
reader = csv.DictReader(csvfile, fieldnames)
for row in reader:
    json.dump(row, jsonfile)
    jsonfile.write('\n')

我将 cannabis.json 中的 json 复制并粘贴到一个新的 json.html 文件中(或者只是更改文件扩展名),然后像这样添加路由:

# Directory.py



# Strain JSON Page

@Directory.route("/strainjson")
def df():
    return render_template("json.html")

如果我非常理解你的担忧,那么分为两部分:

  • 创建 Custom URL Converter(参考 tutorial and doc )以获得 columnsterms 的 2 个单独的 lists,遵循这些模式:
(venv) C:\Python37\myapps\flask\cannabis>flask routes
Endpoint            Methods  Rule
------------------  -------  -----------------------------
api.index           GET      /api/
api.index           GET      /api/<list:cols>
api.index           GET      /api/<list:cols>/<list:terms>
  • pandas 一起读取 cannabis.csv 文件 (download) 您根据 list of columns combined[=81= 得到的数据过滤数据] 带有 可选 list of terms

目前 第 1 部分 已解决,我有点卡在 pandas

我已经尽力了,这就是我如何设置一个有效的 Flask 应用程序演示:

cannabis
.. cannabis

.... api
      __init__.py
      views.py

.... errors
      __init__.py
      views.py

.... __init__.py
.... cannabis.py
.... utils.py

.. tests
.. venv
.. cannabis.csv
.. .flaskenv

/.flaskenv

FLASK_APP=cannabis:create_app()
FLASK_ENV=development
FLASK_DEBUG=0

/cannabis/__init __.py

from .cannabis import create_app

/cannabis/cannabis.py

from flask import Flask

from .utils import ListConverter


def create_app():
    """Create a Flask application using the app factory pattern."""

    app = Flask(__name__)
    app.url_map.converters['list'] = ListConverter

    """Register blueprints."""
    from .errors import bp as errors_bp
    app.register_blueprint(errors_bp)

    from .api import bp as api_bp
    app.register_blueprint(api_bp, url_prefix='/api')

    
    return app

/cannabis/utils.py

from werkzeug.routing import BaseConverter

class ListConverter(BaseConverter):

    def to_python(self, values):
        return values.split('+')

    def to_url(self, values):
        return '+'.join(value for value in values)

对于 to_url() 函数我认为你不需要 BaseConverter.to_url(value) 否则你会遇到错误:

[..]
File "C:\Python37\myapps\flask\cannabis\cannabis\utils.py", line 11, in <genexpr>
    return '+'.join(BaseConverter.to_url(term) for term in terms)
TypeError: to_url() missing 1 required positional argument: 'value'

/cannabis/api/__init __.py

from .views import bp

/cannabis/api/views.py

from flask import Blueprint, jsonify

bp = Blueprint('api', __name__)

@bp.route('/', defaults={'cols': [], 'terms': []})
@bp.route('/<list:cols>', defaults={'terms': []})
@bp.route('/<list:cols>/<list:terms>')
def index(cols, terms):

    cols_a = []
    for col in cols:
        if col: cols_a.append(col)

    terms_a = []
    for term in terms:
        if term: terms_a.append(term)

    # we need list of cols so we can filter data for list of terms within the list of cols
    if not cols_a and terms_a:
        return jsonify(message="Please choose at least one column")
        
    kws = []
    kws.append(cols_a)
    kws.append(terms_a)


    # form the moment just make sure we get the 2 lists/arrays
    # then filter data with pandas using the combination of 2 lists then convert to json and return result
    # .. WORKING ..
   
    return jsonify(message="api index page", kws=kws)

/cannabis/errors/__init __.py

from .views import bp

/cannabis/errors/views.py

from flask import Blueprint, jsonify
from werkzeug.exceptions import HTTPException

bp = Blueprint('errors', __name__)

@bp.app_errorhandler(HTTPException)
def handle_exception(e):
    return jsonify(code=e.code,
                   name=e.name,
                   description=e.description)

现在您可以 运行 Flask 应用并使用不同的 URL 进行一些测试:

no given columns and terms lists, default : return non-filtered data
http://localhost:5000/api/
{"kws":[[],[]],"message":"api index page"}

1 column is given , return data with only the give column
http://localhost:5000/api/Strain
{"kws":[["Strain"],[]],"message":"api index page"}

N columns are given , return data with only the give N columns
http://localhost:5000/api/Strain+Rating
{"kws":[["Strain","Rating"],[]],"message":"api index page"}

notice this url with extra optional '+', it works.
http://localhost:5000/api/Strain++++Rating++Flavor
{"kws":[["Strain","Rating","Flavor"],[]],"message":"api index page"}

N columns and M terms are given , return data with only the give N columns and  filtered rows that contains M terms (CHECK how to use this with pandas)
http://localhost:5000/api/Strain++Rating++Flavor/Purple-Kush++5+++Blackberry+++
{"kws":[["Strain","Rating","Flavor"],["Purple-Kush","5" "Blackberry"]],"message":"api index page"}


notice this url when no column is given.
http://localhost:5000/api/+/Purple-Kush
{"message":"Please add at least one column"}

other url, return non-filtered data
http://localhost:5000/api/+++/+++
{"kws":[[],[]],"message":"api page"}


[..]

我会在完成实施后更新我的代码 pandas..

其他资源: flask jsonify 对比 python json dumpsjson.dumps vs flask.jsonify

这是我想到的。我是根据这篇文章构建的:Medium article on using CSV with Flask。例如,在 URL 本地,您可以键入 ' 5Th-Element' 应该显示为 JSON 格式。在 return 上添加 jsonify 将有助于解决 API 问题。

import csv
from os import path
from flask import Flask, render_template, Blueprint, jsonify, json


# Make Blueprint for __init__.py

  ParseURL = Blueprint("ParseURL", __name__)

# Import Leafly csv

  file_name = path.join(path.dirname(__file__), "Leafly.csv")


# route to display single dictionary list item as JSON object

@APP.route('/<strain>')
def strain_url(strain):
    '''
    Parameters: name of strain from database as a string.
    For loops the cannabis.csv file, creating a dictionary.
    Returning only the strain that was given as a parameter.
    '''
    with open('cannabis.csv') as csv_file:
        data = csv.reader(csv_file, delimiter=',')
        dict_strain = {}
        for row in data:
            if row[0] == strain:
                dict_strain = {
                    "strain": row[0],
                    "type": row[1],
                    "rating": row[2],
                    "effects": row[3],
                    "flavor": row[4],
                    "description": row[5]
                }
                break
    return jsonify(dict_strain)