到目前為止我們的博客處理的都是文字〈鸦現(xiàn)代互聯(lián)網(wǎng)早就進入了“讀圖”時代郊尝,圖片的維護、展示也就相當重要战惊。
上一章中預(yù)留了avatar字段流昏,用來保存用戶上傳的頭像,現(xiàn)在我們來實現(xiàn)這個功能。
必要的設(shè)置
圖片屬于一種媒體文件况凉,它與靜態(tài)文件類似谚鄙,需要設(shè)置一個統(tǒng)一的目錄,便于集中存儲和訪問刁绒。
這類需要框架統(tǒng)一設(shè)置的參數(shù)闷营,當然應(yīng)該在/my_blog/settings.py
中。在底部加上:
/my_blog/settings.py
...
# 媒體文件地址
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')
MEDIA_ROOT和MEDIA_URL是用戶上傳文件保存知市、訪問的位置:
在前面的
Profile
中我們設(shè)置了upload_to參數(shù)傻盟。有了這個參數(shù),文件上傳后將自動保存到項目根目錄的media
文件夾中嫂丙。os.path.join(MEDIA_ROOT, 'media/')
指定了media文件夾的位置娘赴。MEDIA_URL代表用戶通過URL來訪問這個本地地址的URL。設(shè)置好這個參數(shù)后跟啤,用戶就可以通過解析url诽表,很方便的獲取文件的地址。這樣做的好處是避免的硬編碼隅肥,讓代碼更容易維護竿奏。
Django框架擅長的是對邏輯的處理,而對圖片這類文件的處理則非常的耗時腥放。因此在實際的生產(chǎn)環(huán)境中(即產(chǎn)品上線之后)议双,通常是有專門的Web服務(wù)器來處理文件的訪問。
而在開發(fā)階段我們不會在意效率問題捉片,所以Django也提供了方法平痰,讓開發(fā)服務(wù)器能夠處理圖片。
在/my_blog/urls.py
添加下面的語句:
/my_blog/urls.py
...
# 新引入的模塊
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
...
]
#添加這行
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
這樣就為以后上傳的圖片配置好了URL路徑伍纫。
編寫MTV
回顧一下宗雇,avatar
的字段已經(jīng)在上一章寫好了:
/userprofile/models.py
...
class Profile(models.Model):
...
avatar = models.ImageField(upload_to='avatar/%Y%m%d/', blank=True)
...
upload_to
指定了圖片上傳的位置,即/media/avatar/%Y%m%d/
莹规。%Y%m%d
是日期格式化的寫法赔蒲,會最終格式化為系統(tǒng)時間。比如說圖片上傳是2018年12月5日良漱,則圖片會保存在/media/avatar/2018205/
中舞虱。
注意
ImageField
字段不會存儲圖片本身,而僅僅保存圖片的地址母市。記得用pip指令安裝Pillow矾兜。
表單類在前面也寫好了,不用修改:
/userprofile/forms.py
...
class ProfileForm(forms.ModelForm):
class Meta:
model = Profile
fields = ('phone', 'avatar', 'bio')
接著需要修改視圖患久,使之能夠?qū)D片進行處理:
/userprofile/views.py
...
@login_required(login_url='/userprofile/login/')
def profile_edit(request, id):
...
# 修改本行
# 上傳的文件保存在 request.FILES 中椅寺,通過參數(shù)傳遞給表單類
profile_form = ProfileForm(request.POST, request.FILES)
if profile_form.is_valid():
...
# 添加在 profile.bio = profile_cd['bio'] 后面
# 如果 request.FILES 存在文件浑槽,則保存
if 'avatar' in request.FILES:
profile.avatar = profile_cd["avatar"]
...
- 表單上傳的文件對象存儲在類字典對象
request.FILES
中,因此需要修改表單類的參數(shù)返帕,將它一并傳遞進去桐玻。 - 如果
request.FILES
中存在鍵為avatar
的元素,則將其賦值給profile.avatar
(注意保存的是圖片地址)荆萤;否則不進行處理镊靴。
修改模板文件,添加代碼顯示链韭、處理用戶的頭像:
/templates/userprofile/edit.html
...
{% if profile.avatar %}
<div class="col-md-4">頭像</div>
<img src="{{ profile.avatar.url }}" style="max-width: 20%; border-radius: 15%;" class="col-md-4">
{% else %}
<h5 class="col-md-4">暫無頭像</h3>
{% endif %}
<br>
<br>
<form ... enctype="multipart/form-data">{% csrf_token %}
<!-- avatar -->
<div class="form-group">
<label for="avatar">上傳頭像</label>
<input type="file" class="form-control-file" name="avatar" id="avatar">
</div>
...
- 模板語法
{% if ... %}
判斷用戶是否上傳頭像偏竟。 -
<img>
標簽用于顯示圖片內(nèi)容;在style
屬性中規(guī)定了圖片的最大寬度并帶有一點的圓角梧油。 -
注意,表單必須設(shè)置
enctype="multipart/form-data"
屬性州邢,才能夠正確上傳圖片等文件儡陨。 - 添加
<input type="file" ...>
標簽用于上傳圖片。
啟動服務(wù)器量淌,刷新用戶信息頁面:
點擊選擇圖片骗村,上傳一張圖片后點擊提交:
查看一下項目目錄,生成了新的文件夾media/avatar/20181205/
呀枢,其中存儲了該頭像文件胚股;在SQLiteStudio中查看avatar
字段,其保存的是文件的url地址裙秋。
除了上傳琅拌,圖片的處理還包括驗證格式、改變尺寸摘刑、更名进宝、裁剪、美化等多種多樣的需求枷恕。
如果上傳的圖片重名党晋,會導致報錯嗎?請試試看徐块。
更改圖片僅僅會改變字段中存儲的url未玻,并不會真正刪除圖片本身。因此在處理大容量文件時要小心胡控,需要額外的方法進行清理扳剿。
總結(jié)
本章學習了通過表單上傳文件的基礎(chǔ)知識。更加高級的文件處理手段還需在探索中不斷發(fā)掘昼激。你還可以利用BootStrap知識舞终,美化個人信息外觀轻庆,使它像一個完善的產(chǎn)品級頁面。
- 有疑問請在杜賽的個人網(wǎng)站留言敛劝,我會盡快回復余爆。
- 或Email私信我:dusaiphoto@foxmail.com
- 項目完整代碼:Django_blog_tutorial
轉(zhuǎn)載請告知作者并注明出處。