【问题标题】:Passing objects through Flask URL's通过 Flask URL 传递对象
【发布时间】:2018-04-20 12:20:03
【问题描述】:

我正在使用 Flask 开发一个站点,该站点从 API 中提取数据,将其处理为 JSON,然后根据需要在整个站点中动态加载它。我在正确匹配 URL 时遇到问题,同时有效地加载我需要的数据。

这是我的主文件:

import requests
from flask import Flask, render_template

app = Flask(__name__)

url = 'https://omgvamp-hearthstone-v1.p.mashape.com/cards'
myHeaders={
  "X-Mashape-Key": 'key-here',
  "Accept": "application/json"
}
r = requests.get(url, headers=myHeaders)
cards = r.json()
badSets = ['Promo', 'Hall of Fame', 'Tavern Brawl', 'Hero Skins', '    Missions', 'Credits', 'System', 'Debug']

@app.route('/')
def index():
    return render_template('index.html', cards=cards, badSets=badSets)


@app.route('/<setName>', methods=['GET'])
def set(setName):
    return render_template('set.html', cards=cards, setName=setName, badSets=badSets)


@app.route('/<setName>/<cardName>', methods=['GET'])
def individualCard(setName, cardName):
    return render_template('card.html', cards=cards, setName=setName, cardName=cardName, badSets=badSets)

首先,我宁愿不必向每个 html 页面传递我的所有数据。有什么方法可以只提取需要的部分而忽略其余部分?

其次,我想传递一个字典对象,即

if card['name'] == card[setName][--index--][cardName]:
    pass card object to html page here

这是如何实现的,是否可以不必对我的所有数据使用 for 循环?

如果需要,我很乐意加载我的 html 页面。

【问题讨论】:

  • 你能举个例子,你处理的 JSON 是什么样的,也许是你工作流程的简短描述,例如你的路线是用来做什么的?也许只有我一个人,但我很难理解你的问题是什么。
  • @bgse 我很欣赏你的评论。 JSON 的格式为 print(cards['Basic'][0]) 给我 {'cardId': 'GAME_004', 'dbfId': '1740', 'name': 'AFK', 'cardSet': ' Basic', 'type': 'Enchantment', 'text': 'Your turn are short.', 'playerClass': 'Neutral', 'locale': 'enUS'} 其中 ['Basic'] 是我的集合我试图在索引从包含在基本的子字典中拉出一张单独的卡片时进行遍历。该网站的目标是类似于 Mythicspoiler.com,但以在线纸牌游戏《炉石传说》为基础。显示套装和卡片的位置。
  • 这是我从中提取 API 的网站:hearthstoneapi.com 如果这可以帮助解释更多关于我正在尝试做的事情...
  • 所以您的应用程序或多或少是一个卡片浏览器,用户可以在其中从一组列表中选择一组卡片,然后从所选集合中选择一张特定卡片?并且您希望避免将 individualCard() 中的所有 json 数据传递给模板以在那里查找卡片,而只需传递您通过参数提取的单个卡片。这样说对吗?
  • 是的,这或多或少是我想要做的。

标签: python html web flask


【解决方案1】:

假设您解析的 json 数据的基本结构如下所示(带有字典列表的字典):

{
  "Basic": [{"cardId": 4711, ...}, {"cardId": 4712, ...}, ...],
  "Fancy": [...],
  ...
}

你可以重写:

@app.route('/<setName>', methods=['GET'])
def set(setName):
    cardset = cards.get(setName)
    return render_template('set.html', cardset=cardset)

这会根据上面假设的数据结构,通过字典键提取我们正在查找的卡片集。

然后在模板中,而不是cardName,传递cardId并重写另一条路由:

@app.route('/<setName>/<cardId>', methods=['GET'])
def individualCard(setName, cardId):
    cardset = cards.get(setName)
    matches = [x for x in cardset if x['cardId'] == cardId]
    card = matches[0]
    return render_template('card.html', card=card)

这使用list comprehension 从我们选择的cardset 中提取matches 的列表(具有我们正在寻找的cardId 的所有内容),并且应该是一个包含单个元素的列表。我们将第一个元素返回给模板进行渲染。

现在这显然不会做任何错误检查,例如我们传递的字典键可能是错误的并且找不到,cardId 可能找不到,或者更有趣的是,我们传递的 cardId 可能有多个结果.

但这将是如何处理此问题的一般思路。

另外请注意,为了清楚起见,我在示例中省略了 badSets,我假设这是被禁止的卡组,或用于测试目的。

对于这种情况,您可能希望在查找集合之前先检查字典键,并显示错误页面或其他内容:

@app.route('/<setName>', methods=['GET'])
def set(setName):
    if setName in badSets:
        return render_template('error.html')
    cardset = cards.get(setName)
    return render_template('set.html', cardset=cardset)

免责声明:这纯粹是凭记忆而来的,而且已经晚了,所以这里或那里可能会有错误......

【讨论】:

  • 感谢您的回答。我自己有点累,但我一定会在早上阅读并测试一下。
  • 我很好奇你为什么使用 cardId 而不是 cardName
  • 所以,我能够让它与 cardName 一起使用。我认为用户输入他们想要查看的卡片的 URL 会更容易访问。我很好奇您是否可以帮助我为我的模板构建 href。目前,它是 {% for card in cardset %} {% if ('img') in card %} {% if ('collectible') in card %}

    {{ car​​d['name'] }} 但在某个地方,我想我在链接时丢失了 setName。

猜你喜欢
  • 1970-01-01
  • 2017-04-03
  • 2011-05-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多