Django簡介
Django簡介
MVC與MTV模型
MVC百度百科:全名Model View Controller,是模型(model)-視圖(view)-控制器(controller)的縮寫,一種軟件設計典范,用一種業務邏輯、數據、界面顯示分離的方法組織代碼,將業務邏輯聚集到一個部件里面,在改進和個性化定制界面及用戶交互的同時,不需要重新編寫業務邏輯。
通俗解釋:一種文件的組織和管理形式!不要被縮寫嚇到了,這其實就是把不同類型的文件放到不同的目錄下的一種方法,然后取了個高大上的名字。當然,它帶來的好處有很多,比如前后端分離,松耦合等等。
MTV: 有些WEB框架覺得MVC的字面意思很別扭,就給它改了一下。view不再是HTML相關,而是主業務邏輯了,相當于控制器。html被放在Templates中,稱作模板,于是MVC就變成了MTV。這其實就是一個文字游戲,和MVC本質上是一樣的,換了個名字和叫法而已,換湯不換藥。
MVC
- Web服務器開發領域里著名的MVC模式,將web應用分為以下三層:
- 模型(Model)
- 視圖(View)
- 控制器(Controller)
- 以上三層之間以一種插件式的、松耦合的方式連接在一起:
- 模型負責業務對象與數據庫的映射(ORM)
- 視圖負責與用戶的交互(頁面)
- 控制器接受用戶的輸入調用模型和視圖完成用戶的請求。
- 其示意圖如下所示:
MTV
Django的MTV模式本質上和MVC是一樣的,也是為了各組件間保持松耦合關系,只是定義上有些許不同,Django的MTV分別是指:
M 代表模型(Model): 負責業務對象和數據庫的關系映射(ORM)。
T 代表模板 (Template):負責如何把頁面展示給用戶(html)。
V 代表視圖(View): 負責業務邏輯,并在適當時候調用Model和Template。
除了以上三層之外,還需要一個URL分發器,它的作用是將一個個URL的頁面請求分發給不同的View處理,View再調用相應的Model和Template,MTV的響應模式如下所示:
用戶通過瀏覽器向我們的服務器發起一個請求(request),這個請求會去訪問視圖函數,(如果不涉及到數據調用,那么這個時候視圖函數返回一個模板也就是一個網頁給用戶),視圖函數調用模型,模型去數據庫查找數據,然后逐級返回,視圖函數把返回的數據填充到模板中,最后返回網頁給用戶。
- Django 的MTV模型組織
Django項目實例
安裝
python3.5、pip3及pycharm專業版可自行安裝。
例:windows cmd命令行自動安裝Pypi提供的最新版本。
pip3 install django
配置環境變量
成功安裝Djangio后,如有需要,可以將python的Scripts目錄加入到系統環境變量中,以便調用django-admin命令。
配置完成后,可直接在cmd任一路徑下運行django-admin help命令測試安裝和配置完成:
創建django項目和應用
- 在windows cmd命令行界面下,使用diango提供的命令創建diango項目如下:
django-admin startproject mysite
- 其中mysite是項目名稱,可自行替換成你想建立的項目名。
- 而在該項目下創建應用的命令是:
python manage.py startapp blog
- 其中blog為app,應用名稱,可自行替換成你想建立的應用名稱。
- 啟動django項目的命令為:
python manage.py runserver 8080
- runserver 默認為本機(127.0.0.1),后面跟的8080為端口號,可根據實際環境替換。
- 這樣一個簡單的原始的django就啟動起來了,我們到瀏覽器輸入127.0.0.1:8080實際上訪問的就是django的這個項目,如圖:
一般開發使用pycharm(IDE)操作是點擊file-new project,選擇Django欄目;
右側選擇項目所在路徑,選擇項目使用的python版本環境(可選虛擬環境),
注意Location中選擇項目路徑的同時所選的目錄也就是項目的名稱,
More Settings欄可設置模板文件夾名,web應用名稱,勾選自動創建相關web應用文件夾等。
點擊右下方的Create按鈕創建。
Django自動生成類似下面的目錄結構:
* 和項目同名的文件夾中存放的是
* settings.py 配置文件;
* urls.py url路由文件;
* wsgi.py 網絡通信接口模塊;
* templates模板目錄下為空,此目錄主要用于存放各個html模板文件。
* 項目根目錄下的manage.py文件為django項目的管理主程序,工具等。
* 各個應用目錄(如我這邊的創建的應用名為app01)下存放主要有:
* views.py 為處理業務邏輯;
* tests.py 為單元測試;
* modes.py 為處理數據庫;
* 推薦在項目根目錄下自行建立起一個static的靜態文件,用于存放css,js,img,html等靜態文件。
- 在每個Django項目中可以包含多個APP,相當于一個大型項目中的分系統、子模塊、功能部件等等,相互之間比較獨立,但也可以有聯系。
- 所有的APP共享項目資源。
編寫路由(url控制器)
路由由urls文件進行處理,功能是將瀏覽器輸入的url映射到相應的(views)業務處理邏輯。
由于和業務處理邏輯相關,也就是和views相關,所以在文件開頭就需要先導入對應app的views.py文件。
例:沒做增添之前的urls.py(包括了官方注釋)
"""tielemao URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/2.0/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path
urlpatterns = [
path('admin/', admin.site.urls),
]
增添路由條目后:
from django.contrib import admin
from django.urls import path
# 需先導入對應的app目錄中的views文件
from app01 import views
urlpatterns = [
# admin為后臺管理的路由,一般不會暴露出來,注釋掉居多
# path('admin/', admin.site.urls),
# 自己新增的路由條目,前半部分表示路徑的為正則表達式,后半部分為對應的業務邏輯函數
path('index/', views.index),
]
編寫業務處理邏輯(views視圖函數)
urls.py中增添的路由條目中對應了相應的自己命名的業務邏輯函數,
也就是接下來你就需要為此在相應的views.py文件增添上相應的視圖函數。
原始的views.py文件:
from django.shortcuts import render
# Create your views here.
增添相應函數后:
from django.shortcuts import render
# 導入HttpResponse模塊
from django.shortcuts import HttpResponse
# Create your views here.
# request參數按規范必須有,類似self的默認存在,名字可以改,但不建議。
# 它里面封裝了用戶請求的所有內容。
def index(request):
# 可以print打印request.POST或request.GET來查看到請求
# print(request.POST)
# print(request.GET)
# 正常是不能直接返回字符串,必須使用Django提供的HttpResponse
# 這個類封裝起來就可以返回字符串了,這是Django的規則,不是python的。
return HttpResponse("hello world!")
通過上面兩個簡單的步驟,將index這個url指向了views里的index()函數,它接收用戶請求,并返回一個“hello world”字符串。
我們就可以啟動web服務演示一下了。
運行web服務
- 命令行方式:
python manage.py runserver 127.0.0.1:8000
- pycharm中可以通過在工具欄中找到編輯配置文件的選項,快速進行設置host和port后再點擊綠色三角形進行運行:
運行效果:
在瀏覽器中訪問http://127.0.0.1:8000
此時會出現404的錯誤信息,因為此時我們訪問的地址并不是index/,在開發過程中,Django給出的這些錯誤信息很重要,仔細閱讀方便排錯,但一旦正式上線生產環境,就一定要關掉如此詳細的調錯信息功能,常見的錯誤就自己另寫html報錯頁面。
在地址欄中輸入http://127.0.0.1:8000/index/,訪問才會出現己設置好的正常顯示的hello world!
返回HTML
上面例子返回給用戶的是一個字符串,真正的web應用肯定是不會這樣做的,通常返回的都應該是一個HTML文件給用戶。那么,我們寫如下showtime函數和time.html的HTML文件,做為一個用戶訪問獲取
當前時間的功能例子:
- urls.py代碼如下:
from django.contrib import admin
from django.urls import path
# 需先導入對應的app目錄中的views文件
from app01 import views
urlpatterns = [
# admin為后臺管理的路由,一般不會暴露出來,注釋掉居多
path('admin/', admin.site.urls),
# 自己新增的路由條目,前半部分表示路徑的為正則表達式,后半部分為對應的業務邏輯函數
path('index/', views.index),
# 新增用戶訪問time/路由,獲取當前時間函數
path('time/', views.showtime),
]
- views.py代碼如下,增加一個showtime函數:
from django.shortcuts import render
# 導入HttpResponse模塊
from django.shortcuts import HttpResponse
# 導入時間模塊
import datetime
# Create your views here.
# request參數按規范必須有,類似self的默認存在,名字可以改,但不建議。
# 它里面封裝了用戶請求的所有內容。
def index(request):
# 正常是不能直接返回字符串,必須使用Django提供的HttpResponse
# 這個類封裝起來就可以返回字符串了,這是Django的規則,不是python的。
return HttpResponse("hello world!")
def showtime(request):
now=datetime.datetime.now()
ctime=now.strftime("%Y-%m-%d %X")
return render(request, "time.html", {"ctime":ctime})
request,它是一個對象。
當中存儲了請求信息,比如請求路徑,請求方式,GET數據,POST數據…等等。
必須要接收一個request參數。
當你想返回一個html文件時,不是使用HttpResponse方法,而是使用render方法來渲染(打包)。
不過本質上render最終還是使用了HttpResponse方法發送byte字節給瀏覽器的。
- 模板templates目錄下,新建一個time.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{# 由兩個大括號括起來里面加個變量名,相當于是字典的鍵名,是django用于占位輸出的語法 #}
<h3>當前時間:{{ ctime }}</h3>
</body>
</html>
訪問效果如下:
settings.py設置模板文件夾
settings.py文件中有TEMPLATES變量,它是一個列表,列表中又存放了一個字典,其中一個鍵值對
'DIRS':[os.path.join(BASE_DIR, 'templates')]
效果就是默認設置了模板目錄是使用默認的項目文件夾下的templates目錄。
如果有特殊需要修改的就是在此改動。
另外django有一個好處,代碼更改之后,一般無需重啟web服務,它會自動加載最新代碼。
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')]
,
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
使用靜態文件
將html文件返回給用戶還不夠,前端三大塊,HTML、CSS、JS還有各種插件等,完整齊全才是一個好看的頁面。在django中,一般將靜態文件放在static目錄中。接下來,在項目根目錄下新建一個static目錄。
同時,我還在此目錄下建立起js,css,img子目錄和相關文件,如圖:
static這個靜態目錄名和Django默認設置的靜態目錄名別名一致,
在settings.py中可找到相關設置項,就是在結尾處再添加上新的一行表示告訴Django靜態目錄的路徑:
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.0/howto/static-files/
STATIC_URL = '/static/'
# STATIC_URL表示的是引用別名(指針),不是具體的目錄
# 可以改成你想指定的名字,但是在相應的引用地方必須和它對應到
# 增加以下一段表示設置靜態目錄的路徑
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static'),
)
# 真實目錄名不要在html中寫死,而是寫成別名引用,
# 如此,目錄名就算有改動也只需改動此處即可。
# 另外,由于此行是一個元組,別忘了后面還需加個逗號。
同理,在html文件中引用靜態文件,例如jquery.js文件如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{# 由兩個大括號括起來里面加個變量名,相當于是字典的鍵名,是django用于占位輸出的語法 #}
<h3>當前時間:{{ ctime }}</h3>
<script src="/static/js/jquery.js"></script>
</body>
</html>
主要看<script src="/static/js/jquery.js"></script>
這一行,里面的路徑并沒有寫死,而是使用了static/
來代指了真實的靜態目錄。
接收用戶發送的數據(get和post請求)
至此,我們做到了將一個要素齊全的HTML文件返還給了用戶瀏覽器。
但這還不夠,因為web服務器和用戶之間還沒有動態交互。
下面我們來設計一個login頁面,上面建立一個表單,讓用戶輸入用戶名和密碼,提交給login
這個url,服務器將接收到這些數據。
login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登錄</title>
</head>
<body>
<form action="" method="post">
{# 注意Django中有一個跨站請求保護機制,所以需要加以下一行 #}
{% csrf_token %}
用戶名:<input type="text" name="user" />
密碼:<input type="password" name="pwd" />
<input type="submit" value="提交" />
</form>
</body>
</html>
這其中牽涉到一個csrf的防護機制
- CSRF百度百科:CSRF(Cross-site request forgery)跨站請求偽造,也被稱為“One Click Attack”或者Session Riding,通常縮寫為CSRF或者XSRF,是一種對網站的惡意利用。盡管聽起來像跨站腳本(XSS),但它與XSS非常不同,XSS利用站點內的信任用戶,而CSRF則通過偽裝來自受信任用戶的請求來利用受信任的網站。與XSS攻擊相比,CSRF攻擊往往不大流行(因此對其進行防范的資源也相當稀少)和難以防范,所以被認為比XSS更具危險性。
假如沒有加
{% csrf_token %}
這一行防護,運行時將會報如下圖的錯誤:
urls.py中
urlpatterns
添加路由條目:
path('login/', views.login),
views.py中添加login函數:
def login(request):
if request.method=="POST":
username = request.POST.get("user", None)
password = request.POST.get("pwd", None)
print("用戶名:", username,"密碼", password)
return render(request, "login.html")
此邏輯處理將會在pycharm中可以看到用戶輸入的用戶名密碼。
運行效果如下:
html頁面效果:
pycharm后端效果:
pycharm中可以看到提交后的post請求數據后端都獲取到了。
返回動態頁面
我們收到了用戶的數據,但返回給用戶的依然是個靜態頁面,通常頁面會根據用戶的數據,進行處理后在返回給用戶。
django采用自己的模板語言,類似jinja2,可根據提供的數據,替換掉HTML中的相應部分。
例:views.py文件修改如下:
# 創建一個用戶信息表,預設了兩個數據,將返回給瀏覽器展示給用戶
user_list = [
{"user":"tielemao", "pwd":"12345"},
{"user":"LiLei", "pwd":"abc123"},
]
def login(request):
if request.method=="POST":
username = request.POST.get("user", None)
password = request.POST.get("pwd", None)
temp = {"user":username, "pwd":password}
user_list.append(temp)
return render(request, "login.html", {"data":user_list})
# render接收的第三個參數是后臺返回給瀏覽器的數據,一個字典。
# data是字典的鍵,是你在login.html中自定義的指針名字,對應引用值。
而login.html相應修改:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登錄</title>
</head>
<body>
<form action="" method="post">
{# 注意Django中有一個跨站請求保護機制,所以需要加以下一行 #}
{% csrf_token %}
用戶名:<input type="text" name="user" />
密碼:<input type="password" name="pwd" />
<input type="submit" value="提交" />
</form>
<h2>用戶列表</h2>
<table border="1">
<thead>
<th>用戶名</th>
<th>密碼</th>
</thead>
<tbody>
{% for line in data %}
<tr>
<td>{{ line.user }}</td>
<td>{{ line.pwd }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>
login.html中利用for循環將data(引用)迭代填入數據到表格。
訪問頁面并輸入一些數據測試效果如下:
效果就是用戶列表會隨著提交的數據而發生變化,算是一個簡單的動態頁面, 和用戶的交戶過程。
使用數據庫
上面我們雖然和用戶交互得很好,但并沒有保存任何數據,頁面一旦關閉,或服務器重啟,一切都將回到原始狀態。
使用數據庫是正常最常見的,django通過自帶的ORM框架操作數據庫,并且自帶輕量級的sqlite3數據庫。這次我們先來使用sqlite數據庫來演示,后面再學習詳細使用mysql。
首先是注冊app,不進行這一步的話django不會知道該給哪個app創建表。
- 在settings.py中注冊你的app:
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app01.apps.App01Config',
]
例,因為我之前執行了創建應用的命令,django2.06版本自動在創建應用的同時就幫我注冊了app,就是上面代碼中的app01.apps.App01Config
。如果重復注冊一個app01,會在運行python manage.py makemigrationsw
命令的時候報錯django.core.exceptions.ImproperlyConfigured: Application labels aren't unique, duplicates: app01
然后在settings中,配置數據庫相關的參數,這次使用自帶的sqlite,不需要修改。
# Database
# https://docs.djangoproject.com/en/2.0/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
- 編輯models.py,也就是MTV中的M。
from django.db import models
# Create your models here.
# 固定繼承models.Model這個類
class UserInfo(models.Model):
id = models.AutoField(primary_key=True)
user = models.CharField(max_length=32)
pwd = models.CharField(max_length=32)
以上創建了三個字段,分別保存id,用戶名和密碼。
- 通過命令創建數據庫的表:
python manage.py makemigrations
- 注:migration譯作遷移
- 注意此時運行完此命令只是翻譯了了sql語句,還沒有真正將sql語句實行到數據庫中
E:\Django\tielemao>python manage.py makemigrations
Migrations for 'app01':
app01\migrations\0001_initial.py
- Create model UserInfo
* `python manage.py migrate`
* 此命令執行后才是真正在相應的數據庫中創建好了表。
* 同時還會將diango一些認為要創建的表創建上。
E:\Django\tielemao>python manage.py migrate
Operations to perform:
Apply all migrations: admin, app01, auth, contenttypes, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying app01.0001_initial... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying auth.0009_alter_user_last_name_max_length... OK
Applying sessions.0001_initial... OK
使用sqlite3作為數據庫的話,現在可以在項目根目錄下看到有
db.sqlite3
文件- 可以使用查看sqlite文件的軟件連接查看該數據庫驗證。
- 例如使用navicat連接sqlite:
修改views.py中的業務邏輯如下:
from django.shortcuts import render
# 導入models文件
from app01 import models
def login(request):
if request.method=="POST":
username = request.POST.get("user", None)
password = request.POST.get("pwd", None)
# 添加數據到數據庫
models.UserInfo.objects.create(user=username, pwd=password)
# 從數據庫中讀取所有數據
user_list = models.UserInfo.objects.all()
return render(request, "login.html", {"data":user_list})
# render接收的第三個參數是后臺返回給瀏覽器的數據,一個字典。
# data是字典的鍵,是你在login.html中自定義的指針名字,對應引用值。
重啟web服務,刷新瀏覽器頁面,之后和用戶交互的數據都能保存到數據庫中。
任何時候都可以從數據庫中讀取數據,展示到頁面上。
至此,一個要素齊全,主體框架展示清晰的簡單django項目完成了。
【end】
智能推薦
Django簡介和安裝
目錄 Django MVC模型 Django的MTV模型 Django的安裝 虛擬環境 Django Django是一個開放源代碼的Web應用框架,由Python寫成,其網站的特點是高質量,可維護,可擴展,Django的web項目可在短時間內完成。 MVC模型 Django是一個基于MVC構造的框架,即模型M,視圖V 和 控制器C。它是一種軟件設計典范,用一種業務邏輯、數據、界面顯示分離...
Django簡介和配置
Django的架構思想 Model 數據庫 Template 模板文件 View 業務處理 下載django: pip3 install django 創建一個Django工程 django-ad...
Django----簡介
Django ---- 簡介 Django發布于2005年,是當前Python世界里最負盛名且成熟的網絡框架。最初用來制作在線新聞的Web站點。 Django是一個用Python編寫的開放源代碼的Web應用框架(源代碼是開源的,遵守BSD版權)。采用了MVC的框架模式,也有很多人把它稱為MVT(MTV)模式。 MVC 設計模式 一種軟件設計典范,用一種業務邏輯,使數據,界面顯示分離的方法組織代碼,...
Django框架簡介
框架(framework),指為解決一個開放性的問題而設計的具有一 定約束性的支撐結構,使用框架可以幫助你快速開發特定的系統。 部署Django環境 下載安裝Django模塊 方法一:使用pip工具 更新pip的版本 首先要確保安裝了pip工具 方法二:使用git 方法三:下載Django的py包,然后使用python命令安裝 檢測是否安裝成功 安裝數據庫 django默認提供了Sqlite數據庫...
Django簡介(下)
Django簡單應用 模型的增刪改查(ORM模塊) 數據的查詢 查詢所有數據 按照指定條件查詢 計數語句 符合條件的多條數據查詢 模糊查詢 數據的增加 第一種方式: 第二種方式(重點) 關于數據庫表名的設計 關于模型與數據庫數據的關系 視圖與模型的結合使用 設計顯示用戶的操作頁面 HTML操作頁面 模型的增刪改查(ORM模塊) 數據的查詢 查詢所有數據 導包 格式:模型類名.objects.all...
猜你喜歡
django命令簡介
django命令目錄: 在cmd中輸入:dango-admin即可返回全部的django的命令 引入 Windows+R,輸入cmd,然后在命令行輸入即可返回django的全部命令: 命令代碼解釋 check:檢測所有項目是否存在問題 compilemessages:編譯語言文件,用于項目區域語言設置 dbshell:進度django配置的數據庫,可執行sql語句 diffsetti...
Django簡介及安裝
Djano簡介 基本介紹 Django是一個由python編寫的一個開放源代碼的web應用框架 Dajngo的模型是MVC模型:即 Model(模型)+ View(視圖)+ Controlle(控制器) MVC的優勢:低耦合,開發快捷,部署方便,可重用性高 ,維護成本低 特點 強大的數據庫功能 自帶強大的后臺功能 優雅的網址 MVC與MTV模型 MVC模式 是軟件工程的一種軟件架構模式,把軟件系統...
freemarker + ItextRender 根據模板生成PDF文件
1. 制作模板 2. 獲取模板,并將所獲取的數據加載生成html文件 2. 生成PDF文件 其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件; 還有一個問題至今沒有解決,就是關于生成PDF文件...
電腦空間不夠了?教你一個小秒招快速清理 Docker 占用的磁盤空間!
Docker 很占用空間,每當我們運行容器、拉取鏡像、部署應用、構建自己的鏡像時,我們的磁盤空間會被大量占用。 如果你也被這個問題所困擾,咱們就一起看一下 Docker 是如何使用磁盤空間的,以及如何回收。 docker 占用的空間可以通過下面的命令查看: TYPE 列出了docker 使用磁盤的 4 種類型: Images:所有鏡像占用的空間,包括拉取下來的鏡像,和本地構建的。 Con...