Django学习--无状态的Web应用
2019-03-01 本文已影响0人
alue
这两天看了轻量级Django的前三章, 收获很多, 对于Django学习很有帮助. 这里利用书中第二章的例子,继续扩展最简单的Django应用, 完成一个占位图片服务器.
占位图片经常被用于应用程序原型搭建. 典型的占位图片服务器会接收一个指定大小的url, 并生成该图片. url可以携带其他信息, 本例子中只包含宽高.对服务器的所有的请求信息, 都包含在url中, 无需权限验证, 是一个很好的无状态应用示例.
该项目涉及的知识点有:
- url
- 利用
(?P<name>pattern)
方法设计url
- 利用
- 设计视图---生成特定尺寸的图片
- 用form验证尺寸
- 用pil生成图片
- 优化性能
- 后端缓存
-
etag
前端缓存
- 静态文件
- 配置参数
INSTALLED_APPS
TEMPLATES
STATICFILES_DIRS
STATIC_URL
- 添加html模版和css
- 配置参数
设计url
from django.conf.urls import url
urlpatterns = (
url(r'^image/(?P<width>[0-9]+)x(?P<height>[0-9]+)/$', placeholder, name='placeholder'),
url(r'^$', index, name='homepage'),
)
设计视图+优化性能(前后端缓存)
#--------------- 视图模块 ---------------------#
from django.http import HttpResponse, HttpResponseBadRequest
from django import forms
from io import BytesIO
from PIL import Image, ImageDraw
from django.core.cache import cache
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 = f'{width}.{height}.{image_format}'
content = cache.get(key)
if content is None:
image = Image.new('RGB', (width, height))
draw = ImageDraw.Draw(image)
text = f'{width}x{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
# 浏览器缓存(前端): etag 可以利用浏览器缓存技术
import hashlib
def generate_etag(request,width,height):
content = f'Placeholder:{width} x {height}'
return hashlib.sha1(content.encode('utf-8')).hexdigest()
from django.views.decorators.http import etag
@etag(generate_etag)
def placeholder(request, width, height):
# 传给视图的参数都是字符串,可以利用表单验证
form = ImageForm({'height': height, 'width': width})
if form.is_valid():
height = form.cleaned_data['height']
width = form.cleaned_data['width']
# 生成特定尺寸的图片
image = form.generate()
return HttpResponse(image, content_type='image/png')
else:
return HttpResponseBadRequest('Invalid Image Request')
# 主页视图
from django.shortcuts import reverse,render
def index(request):
example = reverse('placeholder',kwargs={'width':50,'height':50})
context = {
'example':request.build_absolute_uri(example)
}
return render(request,'home.html',context)
配置参数
#--------------- 参数配置 ---------------------#
import os, sys
from django.conf import settings
DEBUG = os.environ.get('DEBUG', 'on') == 'on'
SECRET_KEY = os.environ.get('SECRET_KEY', 'tu#z*sc)@7+%!s75-*ao(wje0^r0e%sw15t)$92dl*yn+_uh!(')
ALLOWED_HOSTS = os.environ.get('ALLOWED_HOSTS', 'localhost').split(',')
BASE_DIR = os.path.dirname(__file__)
settings.configure(
DEBUG=DEBUG,
SECRET_KEY=SECRET_KEY,
ALLOWED_HOSTS=ALLOWED_HOSTS,
ROOT_URLCONF=__name__,
INSTALLED_APPS=(
'django.contrib.staticfiles',
),
TEMPLATES = (
{
'BACKEND':'django.template.backends.django.DjangoTemplates',
'DIRS':(os.path.join(BASE_DIR,'templates'),),
},
),
STATICFILES_DIRS=(
os.path.join(BASE_DIR,'static'),
),
STATIC_URL = '/static/',
)
静态文件
将上述三段代码合并为一个placeholder.py
文件, 并在同级目录下新建两个文件templates/home.html
和static/cite.css
, 分别用于存放模板和样式. 这两个文件可以如下设计:
<!-- templates/home.html -->
{% load staticfiles %}
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Django 占位图片</title>
<link rel="stylesheet" href="{% static 'site.css' %}" type="text/css">
</head>
<body>
<h1>Django 占位图片</h1>
<p>{% lorem %}</p>
<p>用类似下面链接,访问占位图片:</p>
<pre>
< img src="{{example}}" >
</pre>
<h2>示例</h2>
<ul>
<li><img src="{% url 'placeholder' width=50 height=50 %}" alt="图片1"></li>
<li><img src="{% url 'placeholder' width=100 height=50 %}" alt="图片2"></li>
<li><img src="{% url 'placeholder' width=50 height=100 %}" alt="图片3"></li>
</ul>
</body>
</html>
//static/cite.css
body{
text-align: center;
}
ul{
list-style: none;
}
li{
display: inline-block;
}
结果展示
这样在命令行运行python placeholder.py runserver
, 打开http://localhost:8000/
, 即可看到下面的结果:
书中这个非常简短的例子, 综合应用了很多django框架知识, 值得认真学习总结. 下一篇, 将学习如何利用Django实现快速原型开发.