1. 安裝虛擬環境工具
pip install virtualenvwrapper-win
2.建立虛擬環境
mkvirtualenv django_env
執行後畫面
環境都存在哪裡?
預設位置:
C:\Users\你的帳號\Envs
3.熟悉虛擬環境的指令
python --version → 確認是乾淨環境
deactivate → 離開
lsvirtualenv 或 workon → 看到 testenv 了嗎?
workon testenv → 再切回去
4.安裝Django
pip install django
5.製作安裝套件的文件requirements.txt
pip freeze > requirements.txt
6.初始化mysite Django 專案
django-admin startproject mysite
7.更換工作目錄
cd mysite
8.執行本地端網站
python manage.py runserver
9.打開瀏覽器
http://127.0.0.1:8000/
10.建立一個新應用程式
python manage.py startapp myapp
11.添加應用程式,mysite/mysite/settings.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 | """ Django settings for mysite project. Generated by 'django-admin startproject' using Django 6.0.2. For more information on this file, see https://docs.djangoproject.com/en/6.0/topics/settings/ For the full list of settings and their values, see https://docs.djangoproject.com/en/6.0/ref/settings/ """ from pathlib import Path # Build paths inside the project like this: BASE_DIR / 'subdir'. BASE_DIR = Path(__file__).resolve().parent.parent # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/6.0/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = 'django-insecure-!mi(werx6fq32e)h4we%q(d5k=(=coxpx^ux9z!#pqv=*-il13' # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True ALLOWED_HOSTS = [] # Application definition INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'myapp', ] MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ] ROOT_URLCONF = 'mysite.urls' TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': ['templates'], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ] WSGI_APPLICATION = 'mysite.wsgi.application' # Database # https://docs.djangoproject.com/en/6.0/ref/settings/#databases DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': BASE_DIR / 'db.sqlite3', } } # Password validation # https://docs.djangoproject.com/en/6.0/ref/settings/#auth-password-validators AUTH_PASSWORD_VALIDATORS = [ { 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', }, { 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', }, { 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', }, { 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', }, ] # Internationalization # https://docs.djangoproject.com/en/6.0/topics/i18n/ LANGUAGE_CODE = 'en-us' TIME_ZONE = 'UTC' USE_I18N = True USE_TZ = True # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/6.0/howto/static-files/ STATIC_URL = 'static/' |
12.建立網頁 mysite/templates/index.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | <!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Hello Django on Render!</title> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous"> </head> <body> <main class="container"> <div class="row text-center justify-content-center"> <div class="col"> <h1 class="display-4">Hello World!</h1> </div> </div> </main> </body> </html> |
13.建立一個簡單的視圖,mysite/myapp/views.py
14.設定路徑,mysite/mysite/uels.py
15.重新啟動網站
1 2 3 4 5 | from django.shortcuts import render
def index(request):
return render(request, 'index.html', {})
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | """ URL configuration for mysite project. The `urlpatterns` list routes URLs to views. For more information please see: https://docs.djangoproject.com/en/6.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 from myapp import views urlpatterns = [ path('admin/', admin.site.urls), path('', views.index, name='index'), ] |
python manage.py runserver
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | databases: - name: mysitedb # 資料庫服務名稱(可自訂) plan: free # free / starter 等,免費版夠用 databaseName: mysite # 資料庫名稱 user: mysite # 使用者名稱(Render 會自動產生密碼) services: - type: web name: mysite # Web Service 名稱 env: python # Python 環境 plan: free # 免費方案 region: singapore # 建議選離台灣近的(如 singapore 或 oregon),跟資料庫同區域避免延遲 buildCommand: pip install -r requirements.txt && python manage.py collectstatic --noinput startCommand: gunicorn mysite.wsgi:application --bind 0.0.0.0:$PORT # 如果你的專案資料夾是 mysite/mysite(內層),startCommand 改成:gunicorn mysite.wsgi:application ... envVars: - key: PYTHON_VERSION value: 3.14.1 # 或你的 Python 版本 - key: SECRET_KEY generateValue: true # Render 自動產生安全的 SECRET_KEY - key: DEBUG value: "False" - key: DATABASE_URL fromDatabase: name: mysitedb # 對應上面的資料庫 name property: connectionString # 自動注入 postgresql://... 格式 - key: ALLOWED_HOSTS value: "*" # 測試用,之後改成你的域名 |
17.建立新的藍圖
20.部署過程,顯示:ModuleNotFoundError: No module named 'app'
在 Render Dashboard 修正 Start Command
登入 https://dashboard.render.com → 選你的 Web Service(mysite)
點 Settings(或 Edit)
找到 Start Command 欄位
改成:gunicorn mysite.wsgi:application
21.再度部署,部署成功後,瀏覽器訪問時,收到 400 Bad Request:
127.0.0.1 - - [18/Feb/2026:08:20:57 +0000] "HEAD / HTTP/1.1" 400 143 ...
127.0.0.1 - - [18/Feb/2026:08:21:01 +0000] "GET / HTTP/1.1" 400 143 ...
這不是 Gunicorn 或 port 綁定問題,而是 Django 的安全檢查 觸發:你的 ALLOWED_HOSTS 設定沒包含 Render 給的域名(這裡是 mysite-1-p20l.onrender.com)。
Django 在 production 模式(DEBUG=False)下,會嚴格驗證 Host header。如果 Host 不匹配 ALLOWED_HOSTS,就直接回 400 Bad Request(不會給詳細錯誤頁面)。
22.修改mysite/mysite/setting.py
ALLOWED_HOSTS = [
'mysite-1-p20l.onrender.com', # 你的實際 Render URL(從 log 抄)
'.onrender.com', # 萬用(wildcard),涵蓋所有子域名,測試超方便
'localhost', # 本地開發用,可選
'127.0.0.1',
]
23.重新把修改後的程式,上傳到Github
git add mysite/settings.py
git commit -m "Fix ALLOWED_HOSTS for Render deployment"
git push origin main
24.自動重新部署
Render 會自動偵測 push → 自動 redeploy(如果開了 auto-deploy)
也可以用手動 redeploy(如果等不及)
去 Render Dashboard → 你的服務(mysite-1-p20l)→ Manual Deploy → Deploy latest commit