如何使用API来构建一个Superhero的应用程序

76 阅读7分钟

与超级英雄API合作

应用程序编程接口是一种软件中间件,它位于两个应用程序之间,允许它们进行通信和交换数据。

因此,这种中间软件能够在两个应用程序之间进行数据传输。例如,其他软件可以使用一个API来与一个特定的框架通信。

超级英雄API是一个应用编程接口,提供关于漫画宇宙中的超级英雄列表的数据和信息。

这包括他们的身体能力、传记信息、职业、力量统计、与其他英雄的联系以及在电影中的出现。

本文通过在一个Django应用程序中消费其数据来探索超级英雄的API。首先,我们将创建一个Django应用程序,列出漫画世界中所有的超级英雄。每个超级英雄都会有自己的页面来展示他的特点。

前提条件

  • 代码编辑器,最好是[Visual Studio Code]。
  • 对[Django]框架的良好理解。
  • [超级英雄的API密钥]。
  • 对[CSS]和[HTML]有一些基本的了解。

项目设置

每个Django项目都需要其虚拟环境来存储项目的所有需求和依赖性。

出于这个原因,我们将为我们的项目创建一个虚拟环境。执行下面的命令来创建一个虚拟环境,并将其称为superhero

virtualenv superhero

接下来,将目录改为包含虚拟环境的文件夹,然后用下面的命令启动虚拟环境。

source superhero/bin/activate

安装Django

现在我们已经激活了虚拟环境,我们需要在虚拟环境中安装Django以及所有其他使用该应用程序所需的依赖项。

执行下面的命令来安装Django。

pip install Django

该命令负责使用Pip获取Django软件包,并将其安装在虚拟环境中。

接下来,执行下面的命令,在当前工作目录下创建一个新的Django项目。

Django-admin startproject superheroes

现在的项目文件夹结构应该如下图所示。

├── superheroes
│   ├── __init__.py
│   ├── asgi.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── manage.py
└── .superhero/

在下一步,我们将安装requestsRequests 是一个简单的HTTP库,用于使用Python发送HTTP请求。

这个库允许人们向HTTP请求传递不同的参数,包括头文件、表单数据和多部分文件。此外,它还可以让人们从JSON格式的请求中获取响应数据。

在终端运行以下命令来安装requests 库。

pip install requests

然后,我们可以运行pip freeze > requirements.txt ,将虚拟环境中的所有需求复制到一个名为requirements.txt 的新文件。

创建应用程序

成功执行上述步骤后,我们需要使用Django命令创建应用程序。

Django中的应用程序是主项目的子项目。因此,举例来说,一个网站可能有news ,作为一个独立的应用程序,而不是portfolio 。对Django来说,这可能是两个不同的子应用程序。

要创建一个应用程序,请执行以下命令。

django-admin startapp heroes

该命令将创建一个新的heroes 应用程序,包括视图、模型、URL、模板迁移。该应用程序的文件夹概览如下所示。

├── heroes
│   ├── __pycache__
│   ├── migrations
│   ├── templates
│   ├── __init__.py
│   ├── admin.py
│   ├── models.py
│   ├── tests.py
│   ├── urls.py
│   └── views.py

关于URL的工作

通用资源定位器是指定系统中特定资源的路径。全站的导航在url.py 文件中。

一旦指定了一个URL,要执行的函数就会从view.py 文件中获取。

这个函数告诉Django要渲染的模板的位置。我们将有两个路径,分别指定默认主页和一个英雄页面。

urls.py 文件中,添加以下片段。

from Django.URLs import path
from . import views
from Django.conf import settings
from Django.conf.URLs.static import static

urlpatterns = [
    path('', views.homepage, name='index'),
    path('single-hero/<int:id>', views.single_hero, name='single-hero'),
]+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

single-hero 路径有一个额外的参数<int:id> ,它指定了超级英雄的ID,其细节将被查看。

在视图上工作

views.py 文件包含了所有在访问特定路径时要执行的函数。由于我们使用requests 和render方法,我们需要将它们导入到views.py 文件中。

from Django.shortcuts import render
import requests

我们在这个文件中会有两个函数。第一个函数将是homepage() 。这个函数将接收请求并使用requests 库从API网址中获取所有的超级英雄。接下来,它将超级英雄的列表转换为json,然后将其传递给模板渲染。

def homepage(request):
    res = requests.get('https://akabab.github.io/superhero-api/api/all.json')
    heroes = res.json()
    context = {'heros': heroes}
    return render(request, 'homepage.html', context)

下一个函数将被称为single_hero ,它也处理请求和一个特定超级英雄的ID。

我们可以按照相同的网址,但用不同的ID来获取其他超级英雄的详细信息。检索到超级英雄的数据后,响应被转换为JSON,传递给single-hero.html 模板。

def single_hero(request, id):
    response = requests.get(f"https://akabab.github.io/superhero-api/api/id/{id}.json")
    response.raise_for_status()  # raises exception when not a 2xx response
    if response.status_code != 204:     
        hero = response.json()
        context = {'hero': hero}
    return render(request, 'single-hero.html', context)

在模板上工作

模板包含将被渲染的用户界面文件。我们正在设计三个模板文件,其中包括从视图传来的数据。

第一个文件将包含所有页面的统一组件,如导航栏和页脚,而其余两个文件将根据它们显示的数据而变化。

基础模板

基本模板包含所有页面所需的片段。此外,我们还指定了我们的项目所需的CSS和JavaScript文件的链接。

所有其他模板都是对基础模板的扩展。创建一个名为base.html 的新文件,然后添加下面的片段。

{% load static %}

<html>    
    <head>
        <meta charset="UTF-8">
        <link rel="stylesheet" href="{% static 'main.css' %}">
        <link rel="stylesheet" href="{% static 'det.css' %}">
        <link rel="stylesheet" href="{% static 'fav.css' %}">
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
        <title>Home</title>
    </head>

    <body>
        <header>
            <div class="app-name center"><a href='index.html'>SuperHeroApp</a></div>
        </header>

        {% block content %}
        <!-- Begin Page Content -->
    
        <!-- /.container-fluid -->
        {% endblock %}
        
        <script type="text/javascript" src="../scripts/index.js"></script>
    </body>
</html>

所有超级英雄模板

这个模板是包含所有超级英雄的列表、他们的名字以及访问各个超级英雄的链接的html文件。首先,在templates 文件夹中创建一个名为homepage.html 的新文件。在该文件中,添加以下片段。

{% extends 'base.html' %}
{% load static %}
{% block content %}


 <!-- Main Search results -->
 <div id="result-container">
    <div id='results'>
        {% for hero in heros %}
        <div class="card-container center" id="data-id">
            <div class="card-img-container">
                <!-- the super hero image -->
                <img src="{{hero.images.sm}}"> //the super hero image
            </div>
            <!-- superhero name -->
            <div id="details_btn" class="card-name">{{hero.name}}</div> 
            <div class="card-btns">
                <a href="{% url 'single-hero' hero.id %}"><button class="btn primary">View</button></a>
            </div>
        </div>
        {% endfor %}

    </div>
</div>

{% endblock %}

我们使用一个for循环来浏览从API获取的超级英雄列表。然后我们显示名字、图片和一个按钮,以进入每个超级英雄的特定页面。

单一超级英雄页面

这个页面是由def single_hero(request, id) 函数渲染的。在这个页面上,我们访问一个单一超级英雄的所有属性。

模板文件夹中,创建一个名为single-hero.html 的新文件,然后添加下面的片段来显示超级英雄的图像。

{% extends 'base.html' %}
{% load static %}
{% block content %}

<div class="container">
    <!-- A navigation bar -->
    <div id="top-bar" style="color: #02a86b;">
        <div><a href="#powerstats">Powerstats</a></div>
        <div><a href="#appearance-target">Appearance</a></div>
        <div><a href="#biography-target">Biography</a></div>
        <div><a href="#occupation-target">Occupation</a></div>
        <div><a href="#connections-target">Connections</a></div>
    </div>
    <div id='data-container'>
        <!-- Image of the hero -->
        <div id="image">
            <img width="400" height="400" src="{{hero.images.sm}}">
        </div>
        <div id="detail-container">
            <!-- powerstatts -->
            <!-- Appearance -->
            <!-- Biography -->
            <!-- occupation -->
            <!-- connections -->
        </div>
    </div>
</div>

{% endblock %}

要显示英雄的力量统计,在detail-container div中添加这块代码。

  <div class="detail-item">
    <!-- Powerstats bars -->
    <span class="anchor" id="powerstats"></span>
    <h4 id="powerstats">{{ hero.name }}'s' Powerstats</h4>
    <div id="stats-container">
        <table class="table table-bordered">
            <thead>
                <tr>
                <th>Metrics</th>
                <th>Measure</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>Intelligence</td>
                    <td>{{hero.powerstats.intelligence}}</td>
                </tr>
                <tr>
                    <td>Strength</td>
                    <td>{{hero.powerstats.strength}}</td>
                </tr>
                <tr>
                    <td>Speed</td>
                    <td>{{hero.powerstats.speed}}</td>
                </tr>
                <tr>
                    <td>Durability</td>
                    <td>{{hero.powerstats.durability}}</td>
                </tr>
                <tr>
                    <td>Power</td>
                    <td>{{hero.powerstats.combat}}</td>
                </tr>
            </tbody>
         </table>
    </div>
</div>

Single hero

要显示英雄的详细资料,我们要做的是:。

<div class="detail-item">
    <span class="anchor" id="appearance-target"></span>
    <h1>Appearance</h1>
    <section id="appearance">
        <table class="table table-bordered">
            <thead>
                <tr>
                    <th>Metrics</th>
                    <th>Measure</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>Gender</td>
                    <td>{{hero.appearance.gender }}</td>
                </tr>
                <tr>
                    <td>Race</td>
                    <td>{{hero.appearance.race}}</td>
                </tr>
                <tr>
                    <td>Height</td>
                    <td>{{hero.appearance.height}}</td>
                </tr>
                <tr>
                    <td>Weight</td>
                    <td>{{hero.appearance.weight}}</td>
                </tr>
            </tbody>
        </table>
    </section>
</div>

超级英雄的传记细节。

<div class="detail-item">
    <span class="anchor" id="biography-target"></span>
    <h1>Biography</h1>
    <section id="biography">
        <table class="table table-bordered">
            <thead>
                <tr>
                <th>Metrics</th>
                <th>Measure</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>Full Name</td>
                    <td>{{hero.biography.fullName }}</td>
                </tr>
                <tr>
                    <td>Alter Egos</td>
                    <td>{{hero.biography.alterEgos}}</td>
                </tr>
                <tr>
                    <td>Aliases</td>
                    <td>{{hero.biography.aliases}}</td>
                </tr>
                <tr>
                    <td>Place of Birth</td>
                    <td>{{hero.biography.placeOfBirth }}</td>
                </tr>
                <tr>
                    <td>First Appearance</td>
                    <td>{{hero.biography.firstAppearance }}</td>
                </tr>
                <tr>
                    <td>Publisher</td>
                    <td>{{hero.biography.publisher }}</td>
                </tr>
                <tr>
                    <td>Alignment</td>
                    <td>{{hero.biography.alignment }}</td>
                </tr>
            </tbody>
        </table>
    </section>
</div>

超级英雄的职业细节。

  <div class="detail-item">
    <span class="anchor" id="occupation-target"></span>
    <h1>Occupation</h1>
    <section id="occupation">
        <table class="table table-bordered">
            <thead>
                <tr>
                    <th>Metrics</th>
                    <th>Measure</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>Occupation</td>
                    <td>{{hero.work.occupation}}</td>
                </tr>
                <tr>
                    <td>Base</td>
                    <td>{{hero.work.base}}</td>
                </tr>
            </tbody>
        </table>
    </section>
</div>

连接细节。

<div class="detail-item">
    <span class="anchor" id="connections-target"></span>
    <h1>Connections</h1>
    <section id="connections">
        <table class="table table-bordered">
            <thead>
                <tr>
                    <th>Metrics</th>
                    <th>Measure</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>Group Affiliation</td>
                    <td>{{hero.connections.groupAffiliation}}</td>
                </tr>
                <tr>
                    <td>Relatives</td>
                    <td>{{hero.connections.relatives }}</td>
                </tr>
            </tbody>
            </table>
    </section>
</div>

Single hero2

静态文件夹

static文件夹包含项目所需的所有静态文件。这些文件包括图片、css、javascript和其他媒体文件

settings.py 文件中添加以下片段,以设置静态文件夹。

#at the beginning of the file
from pathlib import Path
import environ
import os


# at the end of the file
env = environ.Env()
environ.Env.read_env()

STATIC_URL = '/static/'

STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')

STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'static'),
)

最终的应用程序应该如下图所示。

All Heros

结论

Superhero API是一个简单且易于使用的中间件。本教程讨论了如何使用API来构建一个超级英雄的应用程序。

首先,我们获取了数据并在用户界面上进行了渲染。本教程应该为使用超级英雄API和其他带有Django框架的API提供一个开端。