5 圖片上傳和展示完善
阿新 • • 發佈:2018-11-16
回顧上節內容
- 使用資料庫的登入和註冊
- 使用資料庫保圖片 url 和展示
改進圖片上傳
路徑處理
對儲存的路徑和縮圖路徑,URL 的處理
photo.py
class ImageSave(object):
"""
儲存圖片
"""
upload_dir = 'uploads'
thumb_dir = 'thumbs'
size = (200, 200)
def __init__(self, static_path, name):
self.static_path = static_path # static
self.oldname = name # 701728.jpg
self.newname = self.gen_new_name()
def gen_new_name(self):
"""
生成隨機唯一的字串(檔名)
:return:
"""
_, ext = os.path.splitext(self.oldname)
return uuid.uuid4().hex + ext
# 圖片的url: uploads / 1202983.jpg
@property
def image_url (self):
return os.path.join(self.upload_dir, self.newname)
# 圖片上傳後的儲存路徑 static / uploads / 1202983.jpg
@property
def upload_path(self):
return os.path.join(self.static_path, self.image_url)
# 縮圖的url:uploads / thumbs / 1202983_200x200.jpg
@property
def thumb_url(self):
filename, ext = os.path.splitext(self.newname)
thumb_name = '{}_{}x{}{}'.format(filename, *self.size, ext)
return os.path.join(self.upload_dir, self.thumb_dir, thumb_name)
# 儲存圖片
def save_image(self, content):
with open(self.upload_path, 'wb') as f:
f.write(content)
# 生成縮圖
def make_thumbs(self):
im = Image.open(self.upload_path)
im.thumbnail(self.size)
# static / uploads / thumbs / 1202983.jpg
save_thumb_to_ = os.path.join(self.static_path, self.thumb_url)
im.save(save_thumb_to_, 'JPEG')
main.py
class UploadHandler(AuthBaseHandler):
"""
接受圖片上傳
"""
@tornado.web.authenticated
def get(self, *args, **kwargs):
self.render('upload.html')
def post(self, *args, **kwargs):
# 提取表單中‘name’為‘newimg’的檔案元資料 獲取上傳檔案資訊
img_files = self.request.files.get('newimg')
if img_files:
post_id = 0
for img in img_files:
# 儲存的圖片的目錄 名字
image_saver = ImageSave(self.settings['static_path'], img['filename'])
# 儲存圖片
image_saver.save_image(img['body'])
# 生成縮圖 ./ static / uploads /thumbs/ 701728_200x200.jpg
image_saver.make_thumbs()
# 儲存圖片的使用者 大圖地址 縮圖地址 把url存到資料庫
post = Posts.add_post_for(self.current_user, image_saver.image_url, image_saver.thumb_url)
post_id = post.id
self.redirect('post/{}'.format(post_id))
else:
self.write({'msg': 'empty form data'})
上傳圖片名字唯一
用 uuid 庫生成
uuid.uuid4().hex
In [2]: uuid.uuid4()
Out[2]: UUID('c27cbc55-c544-4375-a0d8-ed7f50cfc2aa')
In [3]: uuid.uuid4().hex
Out[3]: '17d9d7327d624edf99117f7f2c43d596'
改進首頁 /
顯示使用者自己上傳的圖片,可以點選檢視具體圖片頁
main.py
class IndexHandler(AuthBaseHandler):
"""
首頁
"""
@tornado.web.authenticated
def get(self, *args, **kwargs):
post_list = get_post_for(self.current_user)
self.render('index.html', post_list=post_list)
utils/account.py
def get_post_for(username):
"""
獲取使用者上傳的圖片資訊
:param username:
:return:
"""
user = session.query(Users).filter_by(name=username).first()
if user:
return user.posts
else:
return []
index.html
{% extends 'base.html' %}
{% block title %}
index page
{% end %}
{% block content %}
<p><a href="/logout">登出</a></p>
{% for post in post_list %}
<a href="post/{{ post.id }}">
<img src="{{ static_url(post.image_url) }}" width="666">
</a>
{% end %}
{% end %}
改進發現頁 /explore
顯示所有圖片縮圖檢視,可以點選檢視具體圖片頁
main.py
class ExploreHandler(AuthBaseHandler):
"""
發現頁
"""
@tornado.web.authenticated
def get(self, *args, **kwargs):
post_list = get_post_all()
self.render('explore.html', post_list=post_list)
utils/account.py
def get_post_all():
"""
獲取所有圖片資訊(降序)
:return:
"""
post_list = session.query(Posts).order_by(Posts.id.desc()).all()
return post_list
explore.html
{% extends 'base.html' %}
{% block title %}
explore page
{% end %}
{% block content %}
<p><a href="/logout">登出</a></p>
{% for post in post_list %}
<a href="post/{{ post.id }}">
<img src="{{ static_url(post.thumb_url) }}">
</a>
{% end %}
{% end %}
改進單獨頁 /post/2
顯示具體圖片頁面
main.py
class PostHandler(AuthBaseHandler):
"""
詳情頁
"""
@tornado.web.authenticated
def get(self, post_id):
post = get_post(post_id)
if not post:
self.write('post id is not exists')
else:
self.render('post.html', post=post)
utils/account.py
def get_post(post_id):
"""
獲取使用者的特定圖片
:param post_id:
:return:
"""
post = session.query(Posts).filter_by(id=post_id).first()
return post
post.html
{% extends 'base.html' %}
{% block title %}
post page
{% end %}
{% block content %}
<img src="{{ static_url(post.image_url)}}" width="560">
upload by {{ post.user.name }}
{% end %}
作業
進行圖片上傳的改進和完善3個頁面
完整程式碼
main.py
import tornado.web
from utils import photo
from models.account import Posts
from pycket.session import SessionMixin
from utils.account import get_post_for, get_post, get_post_all
from utils.photo import ImageSave
import os
class AuthBaseHandler(tornado.web.RequestHandler, SessionMixin):
def get_current_user(self):
return self.session.get('tudo_user_info')
class IndexHandler(AuthBaseHandler):
"""
首頁
"""
@tornado.web.authenticated
def get(self, *args, **kwargs):
post_list = get_post_for(self.current_user)
self.render('index.html', post_list=post_list)
class ExploreHandler(AuthBaseHandler):
"""
發現頁
"""
@tornado.web.authenticated
def get(self, *args, **kwargs):
post_list = get_post_all()
self.render('explore.html', post_list=post_list, current_user=self.current_user)
class PostHandler(AuthBaseHandler):
"""
詳情頁
"""
@tornado.web.authenticated
def get(self, post_id):
post = get_post(post_id)
if not post:
self.write('post id is not exists')
else:
self.render('post.html', post=post)
class UploadHandler(AuthBaseHandler):
"""
接受圖片上傳
"""
@tornado.web.authenticated
def get(self, *args, **kwargs):
self.render('upload.html')
def post(self, *args, **kwargs):
# 提取表單中‘name’為‘newimg’的檔案元資料 獲取上傳檔案資訊
img_files = self.request.files.get('newimg')
if img_files:
post_id = 0
for img in img_files:
# 儲存的圖片的目錄 名字
image_saver = ImageSave(self.settings['static_path'], img['filename'])
# 儲存圖片
image_saver.save_image(img['body'])
# 生成縮圖 ./ static / uploads /thumbs/ 701728_200x200.jpg
image_saver.make_thumbs()
# 儲存圖片的使用者 大圖地址 縮圖地址 把url存到資料庫
post = Posts.add_post_for(self.current_user, image_saver.image_url, image_saver.thumb_url)
post_id = post.id
self.redirect('post/{}'.format(post_id))
else:
self.write({'msg': 'empty form data'})
utils/account.py
import hashlib
from models.account import Users, session, Posts
from datetime import datetime
def hashed(passwd):
return hashlib.md5(passwd.encode('utf8')).hexdigest()
def authenticate(username, password):
"""
登入認證
:param username:
:param password:
:return:
"""
if username and password:
# 獲取資料庫中username對應的密碼
user_passwd = Users.get_passwd(username)
# 如果使用者存在 密碼匹配
if user_passwd and user_passwd == hashed(password):
return True
return False
def register(username, password, email):
"""
註冊
:param username:
:param password:
:param email:
:return:
"""
# 檢視使用者是否存在於資料庫中
if Users.is_exists(username):
return {'msg': '使用者已存在'}
hash_passwd = hashed(password)
# 新增使用者到資料庫
Users.add_user(username, hash_passwd, email)
return {'msg': 'ok'}
def save_last_login(username):
"""
# 儲存使用者username最後登入時間
:param username:
:return:
"""
t = datetime.now()
print("user {} login at {}".format(username, t))
session.query(Users).filter_by(name=username).update({Users.last_login: t})
session.commit()
def get_post_for(username):
"""
獲取使用者上傳的圖片資訊
:param username:
:return:
"""
user = session.query(Users).filter_by(name=username).first()
if user:
return user.posts
else:
return []
def get_post_all():
"""
獲取所有圖片資訊(降序)
:return:
"""
post_list = session.query(Posts).order_by(Posts.id.desc()).all()
return post_list
def get_post(post_id):
"""
獲取使用者的特定圖片
:param post_id:
:return:
"""
post = session.query(Posts).filter_by(id=post_id).first()
return post
photo.py
import os
import glob
from PIL import Image
import uuid
class ImageSave(object):
"""
儲存圖片
"""
upload_dir = 'uploads'
thumb_dir = 'thumbs'
size = (200, 200)
def __init__(self, static_path, name):
self.static_path = static_path # static
self.oldname = name # 701728.jpg
self.newname = self.gen_new_name()
def gen_new_name(self):
"""
生成隨機唯一的字串(檔名)
:return:
"""
_, ext = os.path.splitext(self.oldname)
return uuid.uuid4().hex + ext
# 圖片的url: uploads / 1202983.jpg
@property
def image_url(self):
return os.path.join(self.upload_dir, self.newname)
# 圖片上傳後的儲存路徑 static / uploads / 1202983.jpg
@property
def upload_path(self):
return os.path.join(self.static_path, self.image_url)
# 縮圖的url:uploads / thumbs / 1202983_200x200.jpg
@property
def thumb_url(self):
filename, ext = os.path.splitext(self.newname)
thumb_name = '{}_{}x{}{}'.format(filename, *self.size, ext)
return os.path.join(self.upload_dir, self.thumb_dir, thumb_name)
# 儲存圖片
def save_image(self, content):
with open(self.upload_path, 'wb') as f:
f.write(content)
# 生成縮圖
def make_thumbs(self):
im = Image.open(self.upload_path)
im.thumbnail(self.size)
# static / uploads / thumbs / 1202983.jpg
save_thumb_to_ = os.path.join(self.static_path, self.thumb_url)
im.save(save_thumb_to_, 'JPEG')
index.html
{% extends 'base.html' %}
{% block title %}
index page
{% end %}
{% block content %}
<p><a href="/logout">登出</a></p>
{% for post in post_list %}
<a href="post/{{ post.id }}">
<img src="{{ static_url(post.image_url) }}" width="666">
</a>
{% end %}
{% end %}
explore.html
{% extends 'base.html' %}
{% block title %}
explore page
{% end %}
{% block content %}
<p><a href="/logout">登出</a></p>
{% for post in post_list %}
<a href="post/{{ post.id }}">
<img src="{{ static_url(post.thumb_url) }}">
</a>
{% end %}
{% end %}
post.html
{% extends 'base.html' %}
{% block title %}
post page
{% end %}
{% block content %}
<img src="{{ static_url(post.image_url)}}" width="560">
upload by {{ post.user.name }}
{% end %}
base.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{% block title %}base{% end %}</title>
</head>
<body>
{% block content %}
base
{% end %}
</body>
</html>
login.html
{% extends 'base.html' %}
{% block title %}
login page
{% end %}
{% block content %}
<div class="">
{% if error %}
{{ error }}
{% end %}
<form action="/login?next={{ nextname }}" method="post" enctype="multipart/form-data">
<div class="form-group">
Username
<input autofocus="" class="form-control" id="id_username" maxlength="254" name="username" type=