內容目錄
Django範例 上傳個人圖片
前言
又準備開始說廢話了(誤
好吧事情是這樣的,這幾天有一個朋友要我寫個例子給他,大致上涵蓋一些比較基礎的東西,雖然很想教他直接去看官網的教學,不過我還是寫了一個範例給他,這邊預設好你已經裝好django的套件和Pycharm專業版。
以下是預計會做出來的功能
1.一個上傳資料的頁面(姓名、頭像、自我介紹)
2.一個展示所有資料的頁面
一、建立一個django project
我平常都使用Pycharm做為我的開發工具,所以直接以Pycharm做為我的起手式
- 點選左上角選單File->New Project
(必須使用專業版的pycharm才有django的選項哦)
2.我們把untitled5改成user_profile吧然後按下create
由於我們要上傳圖片檔案,所以先安裝Pillow這個套件,到pycharm的terminal介面輸入以下指令
pip install pillow
3.之後你看Project的目錄結構大概會長這樣(templates是pycharm幫你建立的,如果你是用命令創建django專案的要手動新建這個目錄)
user_profile/
manage.py
templates/
user_profile/
__init__.py
settings.py
urls.py
wsgi.py
二、新建一個App
- 為了不混淆我把下面要新建app的名稱設定為upload_profile
然後到終端機內輸入以下命令
python manage.py startapp upload_profile
2.目錄結構就會變成這樣,你可以看到多出一個upload_profile的資料夾
.
├── manage.py
├── templates
├── upload_profile
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── tests.py
│ └── views.py
└── user_profile
├── __init__.py
├── settings.py
├── urls.py
└── wsgi.py
三、設定路由
- 路由的目的是讓網址能夠導向正確的目錄和程式,又有首先我們先進入一級路由 在user_profile下面的urls.py中你會看到以下程式碼,有備註的是我後來新增上去的
from django.contrib import admin
from django.urls import path
from django.urls import include # 要導入這個include
urlpatterns = [
path('admin/', admin.site.urls),
path('user_profile/',include('upload_profile.urls')) # 新增的,把路由做導向
]
2.接下請進入app(upload_profile)下的urls.py,請自己新建一個urls.py,並輸入以下程式碼,這邊解說一下,從上面的路由進來後,會根據app下面的路由進行路由分發的動作
from django.urls import path
from . import views
urlpatterns = [
path('add/', views.add),
path('detail/', views.detail),
]
3.我們去設定views.py,一樣是在app下面的哦,不是根目錄views.py切記!
locals()會把def 內所有的變數組成一個dict,然後傳入templates中算是懶人寫法的一種
render是渲染用第一個直接傳request,第二個參數是你的html檔案位置,django會自己去尋找,稍後步驟我會把這些檔案建立,到目前為止還沒有這些檔案
from django.shortcuts import render
# Create your views here.
def add(request):
return render(request, 'upload_profile/add.html', locals())
def detail(request):
return render(request, 'upload_profile/detail.html', locals())
4. 建立templates目錄
這邊注意一下,我所說的是在app下面的templates目錄,而非根目錄下的templates
在app 目錄下建立一個templates目錄,下面再建立一個upload_profile目錄,下面在新建兩個html檔案分別是add.html、detail.html
.
├── __init__.py
├── admin.py
├── apps.py
├── migrations
│ └── __init__.py
├── models.py
├── templates
│ └── upload_profile
│ ├── add.html
│ └── detail.html
├── tests.py
├── urls.py
└── views.py
四、建立Model
還記得我們前面所說,有姓名、頭像、自我介紹這三個屬性嗎?
- 進入app下的model.py文件中,裡面已經有以下的程式碼
from django.db import models
2. 撰寫User Model
from django.db import models
# Create your models here.
class User(models.Model):
user_name = models.CharField(max_length=30)
user_image = models.ImageField(upload_to='image/')
introduce = models.FileField(upload_to='introduce/')
def __str__(self):
return self.user_name
CharField 代表字符串的model的一個屬性
ImageField 代表圖片的的一個屬性
introduce 是一個檔案,在資料庫中會記錄他的路徑
五、註冊app
前面我們忘記做一個步驟就是把app名稱寫入setting.py中,這個檔案在project的根目錄下,而不是在app setting.py 哦
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'upload_profile',
]
六、 以model建立資料庫
這邊如果是sqlite的話可以直接做,否則你要先建立好資料庫
然後進入終端機中輸入命令
python manage.py makemigrations upload_profile
在輸入以下命令,正式的把資料庫建立起來
python manage.py migrate upload_profile
七、開始撰寫template
- 我們先處理add.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>添加使用者資料<</title>
</head>
<body>
<h1>添加使用者</h1>
<form action="/upload_profile/add/" enctype="multipart/form-data" method="post">
{% csrf_token %} # 防止跨站請求偽造
<label for="user_name">名字:</label>
<input type="text" name="user_name"><br><br>
<label for="user_image">大頭貼:</label><br>
<input type="file" name="user_image"><br><br>
<label for="introduce">自我介紹:</label><br>
<input type="file" name="introduce"><br><br>
<input type="submit" value="提交">
</form>
</body>
</html>
創建一個form表單來上傳資料,並啟動server
python manage.py runserver
進入瀏覽器http://127.0.0.1:8000/upload_profile/add/,就會出現以下畫面
八、處理view的動作
這時候如果你操作該網頁你會發現沒有任何的作用,所以我們必須去處理後端的邏輯,請進入app目錄下面的去處理view.py
from django.shortcuts import render
from .models import User # 新增的程式碼
# Create your views here.
def add(request):
# =====新增的程式碼=====#
if request.method == "POST":
user_name = request.POST.get('user_name') # 對應剛剛add.html 中的input name
user_img = request.FILES.get('user_image')
introduce = request.FILES.get('introduce')
user = User(user_name=user_name, user_image=user_img, introduce=introduce)
user.save()
return render(request, 'upload_profile/add.html', locals())
# =====新增的程式碼=====#
return render(request, 'upload_profile/add.html', locals())
不過到這邊還沒結束,我們還沒設定上傳的資料要放在哪裡
九、設定上傳檔案存放的目錄
進入根目錄的setting.py中輸入
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
你如果把UPLOAD_ROOT 給print出來會是你的project根目錄下的upload資料夾,我們還要去project下建立一個upload資料夾
/Users/usr/PycharmProjects/user_profile/media/
再進入project根目錄下的urls.py中加入下面命令
from django.conf.urls.static import static
from django.conf import settings
# 修改一下urlpatterns
urlpatterns = [
path('admin/', admin.site.urls),
path('upload_profile/', include('upload_profile.urls')),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
把上傳的目錄和url做綁定的動作,進入http://127.0.0.1:8000/upload_profile/add/
填寫名稱和上傳圖片一個自我介紹的文字檔,會發現project下的meida文件裡面多了introduce和image 資料夾裡面各新增了檔案,進去db.sqlite3裡面也發現了一筆記錄
十、處理detail.html
我們要先回到app目錄下的views.py去把資料全部先撈出來
def detail(request):
list_user = User.objects.all() # 把資料庫中所有的user資料全部撈出來
return render(request, 'upload_profile/detail.html', locals())
接下來要把所有已經存在的user 撈出來顯示在頁面上,我們開啟app目錄下的templates/upload_profile/detail.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>所有使用者</title>
</head>
<body>
<h1>使用者列表</h1>
{% for user in list_user %}
<h2>{{ user.user_name }}</h2>
<img src="{{ user.user_image.url }}" alt="">
<div>
{% for line in user.introduce.readlines %}
<p>{{ line.decode }}</p>
{% endfor %}
</div>
{% endfor %}
</body>
</html>
{% for %} 有點像python的for in loop 把裡面每個物件提取出來,然後把裡面的屬性拿出來,通常{ % %} 裡面都包有語法{{}}裡面則是單個屬性值,裡面的for循環則是因為他是一個文件所以我想要把他每行讀取出來,另外decode則是把\r\n這些給拿掉,還有還有!ser.user_image.url 一定要加url才能網址才能顯示正確哦!
後記
沒想到一個簡單的例子寫起來篇幅竟然這麼長,官方文件中有備註這樣的寫法其實不應該用在production裡面,不過我想說就是用最簡單的寫法讓朋友可以瞭解
本篇大概就是講解以下的重點
路由、ORM的保存、Model的建立、上傳文件、views!
原始碼我放在這
https://github.com/webeasyplay/django-upload_example
如果看到這你真的很有耐心XDD 掰掰!