Python Flask 10 用户上传头像

来源:互联网 发布:请简述阿里云产品优势 编辑:程序博客网 时间:2024/06/13 23:39

欢迎访问地平线上的一匹狼-Python Flask 10 用户上传头像

借助上节的基础==>
点我啊! Python Flask 上传文件">点我啊! Python Flask 上传文件
这节我们实现一下修改用户头像以及默认头像的功能.

截止目前的项目进度:
点我啊! Github:flask-大型网站架构5-新增上传头像">点我啊! Github:flask-大型网站架构5-新增上传头像

最终效果如图:
1.

2.

3.

4.

开始!

1:

因为我们需要对每个用户存下他的头像信息.
这里我们选择直接存储图片url的形式进行存储.
所以我们需要对model层User添加一个gravatar列,存储头像url.
主要代码如下:

class User(UserMixin,db.Model):    __tablename__ = 'users'    gravatar = db.Column(db.String(200),default='/_uploads/photos/default.jpg')

其中gravatar的默认值是默认头像相对url.

2:

首先我们依然需要先码出上传头像界面的表单(form).

先配置所要上传的目标地址变量/config.py:

import osUPLOADED_PHOTOS_DEST = os.path.abspath(os.path.join(os.getcwd(),"app/static/Gravatar"))

我们需要对上传文件进行约束为图片格式,这里我们用一个UploadSet模块,编辑代码/app/__init__.py:

from flask_uploads import UploadSet, configure_uploads, IMAGES, patch_request_classphotos = UploadSet('photos',IMAGES)

然后将创建好的photo对象加入已经创建好的app中:

configure_uploads(app,photos)patch_request_class(app)  

然后编写form表单:

from flask_wtf.file import FileField, FileRequired, FileAllowedfrom flask_uploads import UploadSet, configure_uploads, IMAGES, patch_request_classfrom .. import photosfrom flask_wtf import FlaskFormclass UploadForm(FlaskForm):    photo = FileField(validators=[        FileAllowed(photos, u'只能上传图片!'),         FileRequired(u'请选择一个头像吧!')])    submit = SubmitField(u'确认上传',render_kw={"class":"btn btn-primary"})

其中render_kw是一个dict类型,作用是渲染对应表单的css.
FileAllowed用来检测上传文件类型,不对的的话返回第二个参数.
FileRequiredRequired作用近似,即非空判断.

3:

接下来我们就要开始编写view层了.
这里我们将编辑头像页面的url设为/edit-gravatar
所以我们需要码一个有GETPOST的视图函数.

from flask_login import  current_userfrom flask_login import login_user,login_required,logout_userfrom .forms import UploadFormfrom flask import render_template, session, redirect, url_for, current_app,abort,flashfrom .. import db,photos@main.route('/edit-gravatar',methods=['GET','POST'])@login_requireddef edit_gravatar():    form = UploadForm()    if form.validate_on_submit():        filename = photos.save(form.photo.data)        file_url = photos.url(filename)        current_user.gravatar = file_url        db.session.add(current_user)        flash('修改成功!')        return redirect(url_for('.user',username=current_user.username,file_url=file_url))    return render_template('edit_gravatar.html',form=form,file_url=current_user.gravatar)

注意我们所上传的头像文件即使名字相同也不会覆盖掉之前的头像文件的..(所以还是以二进制存到数据库中更好一点么).

4:

接下来我们需要编写前台界面了:
首先,由于如果我们直接用quick_form创建表单的话,表单的css就不好改了.所以我们把每个表单分开放入form type=file中,并且通过传参或者重叠覆盖修改表单控件的样式.

其中,修改input type=file样式的通用方法是将opacity设为0,然后用一个a标签将input和a组合到一起,这样修改a的样式便相当于修改input的样式.
对应的几部分代码如下:

/*CSS*/.upload{    padding: 5px 10px;    height: 40px;    line-height: 30px;    position: relative;    border: 1px solid #999;    text-decoration: none;    text-align:center;    color: #fff;}.change{    position: absolute;    overflow: hidden;    right: 0;    top: 0;    opacity: 0;}
<a class="btn btn-success upload" placeholder="上传头像" >    <p id="show_gt">选择您要上传的头像~</p>    {{ form.photo(class="change",placeholder="上传头像",onchange="c()") }}</a>

然后在css中修改upload样式即可.
其中btn btn-xxxbootstrap样式.

但是到这里还需要考虑一个问题,就是当选中图片以后,并不会显示到页面上,必选点击提交以后才会修改,下次访问这个页面才会变成新图片.
所以我们需要一种方法使选中图片的同时将图片显示在页面上,并和之前的头像对比.
这里我们使用直接通过JavaScript在本地显示:
对应JS代码如下:

<script type="text/javascript">    function c () {        var gt=document.getElementById('show_gt');        gt.innerText = '已选中图片~'        var r= new FileReader();        f=document.getElementById('photo').files[0];        r.readAsDataURL(f);        r.onload=function  (e) {            document.getElementById('show').src=this.result;        };    }</script>

因为FlaskForm生成的表单的id和类中对应表单实例的名字是一样的,所以这里的id是photo.
获取图片对象(object) f.
把这个File对象传给FileReader对象的读取方法,就能读取文件了。

连接: [JS进阶] HTML5 之文件操作(file)" target="_blank">点我啦! [JS进阶] HTML5 之文件操作(file)

最后的r.result即为对应图片的二进制数据.

然后就是修改一下排版即可:

<!-- edit_gravatar.html -->{% extends "base.html" %}{% import "bootstrap/wtf.html" as wtf %}{% block title %}编辑个人头像{% endblock %}{% block page_content %}<form method="POST" enctype="multipart/form-data">     {{ form.hidden_tag() }}     <div class="page-header"><h2>展览板~</h2></div>     <a class="btn btn-success upload" placeholder="上传头像" ><p id="show_gt">选择您要上传的头像~</p>        {{ form.photo(class="change",placeholder="上传头像",onchange="c()") }}     </a><br/>     {% for error in form.photo.errors %}         <span style="color: red;">{{ error }}</span>     {% endfor %}     {% if file_url %}     <br><img src="{{ file_url }}" width="256" height="256">     {% endif %}     <a class="btn btn-success"><-之前 之后-></a>     <img src="{{ file_url }}" id='show' width="256" height="256"><br/><br/>     {{ form.submit }}</form><script type="text/javascript">    function c () {        var gt=document.getElementById('show_gt');        gt.innerText = '已选中图片~'        var r= new FileReader();        f=document.getElementById('photo').files[0];        r.readAsDataURL(f);        r.onload=function  (e) {            document.getElementById('show').src=this.result;        };    }</script>{% endblock %}

Done

原创粉丝点击