Flask Web開發一書中,使用了與我的郵箱綁定的Gravatar圖形做爲用戶頭像。Gravatar提供的頭像比較簡陋,並且可能因爲網絡問題沒法生成頭像。多數社交網站和博客提供用戶自定義頭像功能,所以本身加上了自定義頭像的功能。html
思路:用戶選擇我的頭像後,將頭像文件上傳到服務器端特定的文件夾中;在用戶模型中添加字段,保存頭像存儲的路徑,這樣就實現了頭像與用戶的關聯。前端
一、模型中添加頭像路徑字段bootstrap
保留原有的avatar_hash字段,定義real_avatar字段用來存儲頭像地址。服務器
# models.py class User(UserMixin, db.Model): # ... real_avatar = db.Column(db.String(128), default = None)
二、上傳文件表單網絡
使用FileField類建立了上傳文件的表單字段。網上也有人把頭像修改和編輯我的資料集成到一個表單裏,但一般來講用戶資料修改和頭像修改是獨立的功能,並且資料修改有用戶和管理員兩個級別,集成到一塊對程序修改較多。session
# main/forms.py class ChangeAvatarForm(FlaskForm): avatar = FileField('') submit = SubmitField('Submit')
三、修改頭像的視圖函數app
提交上傳文件的表單後,可經過request.files字典中得到上傳的文件對象,該對象的filename屬性爲文件名,從文件名中可提取後綴名,判斷上傳的文件是不是容許的格式。確認格式無誤後,將文件保存到upload_folder文件夾中,文件名爲「用戶名+後綴名」,因爲每一個用戶的用戶名不一樣,所以可使用便於識別的用戶名來命名頭像,也可使用用戶id命名頭像文件。函數
# main/views.py @main.route('/change-avatar', methods=['GET', 'POST']) @login_required def change_avatar(): '''修改頭像''' form = ChangeAvatarForm() if form.validate_on_submit(): # 文件對象 avatar = request.files['avatar'] fname = avatar.filename # 存儲路徑 upload_folder = current_app.config['UPLOAD_FOLDER'] # 容許格式 allowed_extensions = ['png', 'jpg', 'jpeg', 'gif'] # 後綴名 fext = fname.rsplit('.',1)[-1] if '.' in fname else '' # 判斷是否符合要求 if fext not in allowed_extensions: flash('File error.') return redirect(url_for('.user', username=current_user.username)) # 路徑+用戶名+後綴名 target = '{}{}.{}'.format(upload_folder, current_user.username, fext) avatar.save(target) current_user.real_avatar = '/static/avatars/{}.{}'.format(current_user.username, fext) db.session.add(current_user) flash('Your avatar has been updated.') return redirect(url_for('.user', username = current_user.username)) return render_template('change_avatar.html', form=form)
配置文件中配置頭像文件保存路徑:測試
# config.py class Config: UPLOAD_FOLDER = os.getcwd() + '/app/static/avatars/'
四、前端的修改網站
在change_avatar.html頁面渲染ChangeAvatarForm表單:
<!-- templates/change_avatar.html --> {% extends "base.html" %} {% import "bootstrap/wtf.html" as wtf %} {% block title %}Flasky - Change Avatar{% endblock %} {% block page_content %} <div class="page-header"> <h1>Change Your Avatar</h1> </div> <div class="col-md-4"> {{ wtf.quick_form(form) }} </div> {% endblock %}
在我的用戶頁面,可直接使用頭像圖片做爲連接,地址是頭像上傳頁面。因爲用戶資料頁面是開放的,只有用戶本人或管理員訪問時才加上此連接。同時爲了和原有的Gravatar頭像功能兼容,這裏進行了判斷:當用戶上傳了本身的頭像時,顯示自定義頭像,不然顯示默認的Gravatar頭像。同時,還將自定義頭像的尺寸與Gravatar頭像的尺寸保持一致,顯得更協調些。也能夠不用Gravatar頭像,像多數網站同樣設置一個默認的頭像。
除了用戶頁面外,帳戶、博客文章、評論這幾處也會用到小頭像,要予以修改,保持一致。
<!-- templates/user.html --> <a {% if user == current_user or current_user.is_administrator() %}href="{{ url_for('.change_avatar') }}"{% endif %}> {% if user.real_avatar %} <img class="img-rounded profile-thumbnail" src="{{ user.real_avatar }}" height="256" width="256" > {% else %} <img class="img-rounded profile-thumbnail" src="{{ user.gravatar(size=256) }}"> {% endif %} </a>
五、測試
完成以上代碼後,修改頭像後的我的頁面顯示效果以下:
點擊大頭像便可進入上傳頭像頁面。目前用戶提供的頭像須要自行截切成正方形,不然頭像會壓扁或拉長,很難看。通常的社交網站的頭像修改界面每每提供圖像的預覽和截切功能,主要和前端相關,後續也可將該部分功能集成到程序裏。
能夠多測試幾個用戶: