原代码是基于Django1.8,这里改用Django2.1,值得注意的一点是,书中很多地方是用元组包含数据,而Django默认模板中是使用字典,因为用元组导致过TemplateDoesNotExist报错,就统一改成跟默认模板一样用字典。
placeholder.py文件内容
import os
import sys
import hashlib
from django.conf import settings
from django.core.wsgi import get_wsgi_application
from django.http import HttpResponse, HttpResponseBadRequest
from django import forms
from io import BytesIO
from PIL import Image, ImageDraw
from django.views.decorators.http import etag
from django.urls import reverse
from django.shortcuts import render
from django.urls import path
from django.core.cache import cache
DEBUG = os.environ.get('DEBUG', 'on') == 'on'
SECRET_KEY = os.environ.get('SECRET_KEY', '!32!0g1$-o7r4te5jc2&b@7w8c6*xf75&)=k!%3o9(g6jm4&g-')
ALLOWED_HOSTS = os.environ.get('ALLOWED_HOSTS', 'localhost').split(',')
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
settings.configure(
DEBUG=DEBUG,
SECRET_KEY=SECRET_KEY,
ALLOWED_HOSTS=ALLOWED_HOSTS,
ROOT_URLCONF=__name__,
MIDDLEWARE=[
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
],
INSTALLED_APPS=[
'django.contrib.staticfiles',
],
TEMPLATES=[
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
# 要用[]而不是(),不然会出现TemplateDoesNotExist报错
'DIRS': [os.path.join(BASE_DIR, 'templates')],
},
],
STATICFILES_DIRS=[
os.path.join(BASE_DIR, 'static'),
],
STATIC_URL='/static/',
)
application = get_wsgi_application()
class ImageForm(forms.Form):
height = forms.IntegerField(min_value=1, max_value=2000)
width = forms.IntegerField(min_value=1, max_value=2000)
def generate(self, image_format='PNG'):
height = self.cleaned_data['height']
width = self.cleaned_data['width']
key = '{}.{}.{}'.format(width, height, image_format)
content = cache.get(key)
if content is None:
image = Image.new('RGB', (width, height))
draw = ImageDraw.Draw(image)
text = '{} X {}'.format(width, height)
textwidth, textheight = draw.textsize(text)
if textwidth < width and textheight < height:
texttop = (height - textheight) // 2
textleft = (width - textwidth) // 2
draw.text((textleft, texttop), text, fill=(255, 255, 255))
content = BytesIO()
image.save(content, image_format)
content.seek(0)
cache.set(key, content, 60*60)
return content
def generate_etag(request, width, height):
content = 'Placeholder: {0} x {1}'.format(width, height)
return hashlib.sha1(content.encode('utf-8')).hexdigest()
@etag(generate_etag)
def placeholder(request, width, height):
form = ImageForm({'height': height, 'width': width})
if form.is_valid():
image = form.generate()
return HttpResponse(image, content_type='image/png')
else:
return HttpResponseBadRequest('Invalid Image Request')
def index(request):
example = reverse('placeholder', kwargs={'width': 50, 'height': 50})
print(example)
context = {
'example': request.build_absolute_uri(example),
}
return render(request, 'home.html', context)
urlpatterns = [
path('', index, name='homepage'),
path('image/<int:width>x<int:height>/', placeholder, name='placeholder'),
]
if __name__ == '__main__':
from django.core.management import execute_from_command_line
execute_from_command_line(sys.argv)
home.html文件内容
{% load staticfiles %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Django Placeholder Images</title>
<link rel="stylesheet" href="{% static 'site.css' %}" type="text/css">
</head>
<body>
<h1>Django Placeholder Images</h1>
<p>This server can be used for serving placeholder images for any web page.</p>
<p>To request a placeholder image of a given width and height simply include an image with the source pointing to
<b>/image/<width>x<height>/</b>on this server such as:</p>
<pre><img src="{{ example }}" ></pre>
<h2>Examples</h2>
<ul>
<li><img src="{% url 'placeholder' width=50 height=50 %}"></li>
<li><img src="{% url 'placeholder' width=100 height=50 %}"></li>
<li><img src="{% url 'placeholder' width=50 height=100 %}"></li>
</ul>
</body>
</html>
site.css文件内容
body{
text-align: center;
}
ul{
list-style: none;
}
li{
display: inline-block;
}