前言

这几个月用Django框架做了一个关于数据分析的网站,想在上线前给网站加一些功能作为装饰,在逛api的时候发现了』历史上的今天『,本来以为很简单就可以搞定,却没想到做了很久,原因应该是自己对django理解还不够深吧,特通过这篇文章记录这一功能的实现过程。本文主要讲后端实现,不讨论前端代码对该功能的美化。

API获取

首先,我们先申请API,我是在聚合数据上申请的,该API是免费的(但每天调用次数只能100次),链接如下:

juhe.cn/docs/api/id/63

关于API的调用我们只要看一下产品文档,基本就懂了:

参数只有四个,key就是申请介面后系统给你的Appkey,v默认1.0,我们只要获取当前的月和日就可以进行调用了,目前代码如下:

import requests
import json
import time

now = time.localtime(time.time())
month = str(now[1])
day = str(now[2])

request_url = http://api.juheapi.com/japi/toh?key=b045bc236ee5db0386edf145dc75b7b2&v=1.0
url = request_url+&month= + month + &day= +day
res = requests.get(url)
result = res.text
json_result = json.loads(result)
print(json_result)

返回结果如下:

我么可以看到返回结果有很多,但不是所有的结果都有img_url(如id=19510423),我们最终要得到一组图片和与之匹配的描述,所以我们对结果进行筛选,选择第一个包含图片的时间并返回,附加代码如下:

length = len(json_result[result])
for i in range(0,length):
img = json_result[result][i][pic]

if img:

des = json_result[result][i][des]

return (img,des)

后端代码(该方法后来多次测试后,放弃)

这样我们就返回了所需要的imgurl和对图片的简单概述,下面我们要把他们在前端显示出来,一开始尝试直接在视图函数中把图片返回到前端,在此之前我对代码进行了简单的整理,将以上功能定义在history_img()函数(该函数会返回图片的url)里,以便在视图函数中调用。视图函数中代码如下:

from io import BytesIO
from PIL import Image
import requests

def get_img(request):
img = history_img()
response = requests.get(img)
out = BytesIO()
image = Image.open(BytesIO(response.content))
image.save(out, png)
out.seek(0)

response = HttpResponse(content_type=image/png)
response.write(out.read())
response[content-length] = out.tell()
return response

在Django中,是无法直接返回一个图片数据的,我们先通过requests.get方法获取图片,再通过BytesIo来存储图片数据,再将其保存到response对象中并返回,在urls进行相关配置就可以在设定的url中看到图片了。

随后我们将前端的图像url变成{% url 上面定义的视图函数的url%}』,如图:

<img src="{% url api_transfer:get_img %}" alt="">

这样虽然可以在前端中显示了图片,但我们每次打开有该图片的页面就会请求一次api,而该api一天只能访问100次(好像开通会员就可以免费用,1年大约1000),每次载入的时间也会使网站载入的速度不流畅,所以以上方法失败,只能老老实实使用资料库存储。尽管如此,熟悉视图函数返回图片类型的方法仍是有意义的。

资料库的基本配置

资料库的类型可以根据个人喜好选择,我使用的是Mysql,为了连接资料库,需要在setting.py中进行如下配置:

DATABASES = {
default: {
ENGINE: django.db.backends.mysql,
NAME: xxx,
HOST:127.0.0.1,
USER:root,
PORT:3306,
PASSWORD:xxxxx,
}
}

各参数见名知意,这里不做解释,下面我们在models中定义数据表:

from django.db import models

# Create your models here.
class History_today(models.Model):
des = models.TextField()
image_url = models.URLField()
time = models.DateTimeField(auto_now_add=True)

class Meta:
ordering = [time]

我们除了定义了必要的描述和图片地址之外还定义了时间(设置自动生成),为了方便排序,也为了我们能在资料库中快速看到某一天的数据。随后:

点击进入manage.py,输入一下代码

makemigrations
migrate

这样我们打开Navicat,会看到已经生成数据表:

里面的数据是我做测试用的

后端最终代码

在后端导入一些需要的文件和库,然后写如下代码

try:
(img,des) = history_today()
except:
img =
history = History_today.objects.get(pk=1)
if history.image_url != img and img != :
History_today.objects.filter(pk=1).update(image_url = img,des = des)
def index(request):
history = History_today.objects.get(pk=1)
context = {

history:history,

}
return render(request,news/index.html,context=context)

利用try和except解决api调用超过100次后报错的问题如果图片与资料库最靠前数据图片不同(即新的一天到了)再对数据进行更新,将数据返回给前端,前端基本代码如下:

<div class="img">
<img src="{{ history.image_url }}" alt="">
</div>
<span class="desc">{{ history.des }}</span>

网页中的显示如图,大家可以在通过前端代码进行一些优化。

后记

如果发现了一些优化方法或bug我会在这里补充。

如果本文对您有启发或价值的话,记得点赞关注哦!


推荐阅读:
相关文章