![0d7ca6a1dd281e97e07c5e303f86ee9a.png](https://img-blog.csdnimg.cn/img_convert/0d7ca6a1dd281e97e07c5e303f86ee9a.png)
前言
这几个月用Django框架做了一个分享python学习的网站:我的数据生活
想在上线前给网站加一些功能作为装饰,在逛api的时候发现了’历史上的今天‘,本来以为很简单就可以搞定,却没想到做了很久,原因应该是自己对django理解还不够深吧,特通过这篇文章记录这一功能的实现过程。本文主要讲后端实现,不讨论前端代码对该功能的美化。
API获取
首先,我们先申请API,我是在聚合数据上申请的,该API是免费的(但每天调用次数只能100次),链接如下:
https://www.juhe.cn/docs/api/id/63
关于API的调用我们只要看一下产品文档,基本就懂了:
![2b02ffb6285439cc406ecf2615e7291b.png](https://img-blog.csdnimg.cn/img_convert/2b02ffb6285439cc406ecf2615e7291b.png)
参数只有四个,key就是申请接口后系统给你的Appkey,v默认1.0,我们只要获取当前的月和日就可以进行调用了,目前代码如下:
import
返回结果如下:
![8b61b9d33e1d8fda1010edf7910a57b1.png](https://img-blog.csdnimg.cn/img_convert/8b61b9d33e1d8fda1010edf7910a57b1.png)
我么可以看到返回结果有很多,但不是所有的结果都有img_url(如id=19510423),我们最终要得到一组图片和与之匹配的描述,所以我们对结果进行筛选,选择第一个包含图片的时间并返回,附加代码如下:
length
后端代码(该方法后来多次测试后,放弃)
这样我们就返回了所需要的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']
我们除了定义了必要的描述和图片地址之外还定义了时间(设置自动生成),为了方便排序,也为了我们能在数据库中快速看到某一天的数据。随后:
![b86726a082ece1a54753850295668e66.png](https://img-blog.csdnimg.cn/img_convert/b86726a082ece1a54753850295668e66.png)
makemigrations
migrate
这样我们打开Navicat,会看到已经生成数据表:
![08817205dfd31153b65876fff4f98548.png](https://img-blog.csdnimg.cn/img_convert/08817205dfd31153b65876fff4f98548.png)
后端最终代码
在后端导入一些需要的文件和库,然后写如下代码
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>
网页中的显示如图,大家可以在通过前端代码进行一些优化。
![79e113dc696872e71a494509d6030bbb.png](https://img-blog.csdnimg.cn/img_convert/79e113dc696872e71a494509d6030bbb.png)
后记
其他有趣API的调用:
贝特西:通过爬虫爬取2000名明星照片进行颜值评测,你心中的男/女神有多少评分?zhuanlan.zhihu.com![b3f4b9c05ee1905e9c0d5117f24a7fff.png](https://img-blog.csdnimg.cn/img_convert/b3f4b9c05ee1905e9c0d5117f24a7fff.png)
如果发现了一些优化方法或bug我会在这里补充。
如果本文对您有启发或价值的话,记得点赞关注哦!