这几个月用Django框架做了一个关于数据分析的网站,想在上线前给网站加一些功能作为装饰,在逛api的时候发现了』历史上的今天『,本来以为很简单就可以搞定,却没想到做了很久,原因应该是自己对django理解还不够深吧,特通过这篇文章记录这一功能的实现过程。本文主要讲后端实现,不讨论前端代码对该功能的美化。
首先,我们先申请API,我是在聚合数据上申请的,该API是免费的(但每天调用次数只能100次),链接如下:
https://www.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]
我们除了定义了必要的描述和图片地址之外还定义了时间(设置自动生成),为了方便排序,也为了我们能在资料库中快速看到某一天的数据。随后:
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我会在这里补充。
如果本文对您有启发或价值的话,记得点赞关注哦!