Lecturer:Yan
Django
Basic
大綱
- 課程目標
- Web framework 介紹
- Django 介紹
- MTV 架構介紹
- 虛擬環境介紹
- Django 安裝
- 建立 Django projects
- Hello Worlds!
- Models
- OOP
Outline
GOAL
這兩堂課中你將會學到
- 基本的物件導向
- 用 Django 建立一個屬於自己的日誌網站
!! 本課程只是入門,並不會深入解釋所有概念 !!
有興趣的話可以加入 SIRLA 或是繼續自學 ouo
Web framework 介紹
Web framework ?
網頁框架就是別人已經設定好的一個網站模板,你可以學習它的規則,然後修改成自己需要的樣子。簡單來說就是當你開發 Web 應用程式時所用的框架。
通常會提供:
- 一個既定的程式骨架
- 強大且豐富的函式庫 ( Libraries )
常見的網頁框架
常用 Python 框架比較
- 大而全
- 內建全套解決方案
- 注重組件的重用性、可插拔性
- 微框架
- 自由、靈活,可擴展性強
- 入門簡單
框架本身無法自行運作,開發者要將框架搭配上自己的程式,才是一個完整的應用程式。
Django 介紹
Introduction
Django ?
- 免費開放原始碼
- 著重快速開發、高效能
- 遵從 DRY 守則,致力於淺顯易懂和優雅的程式碼
- 使用 MTV 架構
- 是 Python 最著名的 Web Framework,可以快速開發安全和可維護的網站。
它有以下幾個特色:
DRY
Don't Repeat Yourself
- 原則是「系統中的每一部分,都必須有一個單一的、明確的、權威的代表」。
- 指的是代碼必須能夠表達所應表達的內容,但是不能含有任何重複代碼。
- 當 DRY 原則被成功應用時,一個系統中任何單個元素的修改都不需要與其邏輯無關的其他元素發生改變。
實例
Text
實例
MTV 架構介紹
Introduction
MVC
- Model : 資料的管理(例如與資料庫的溝通) 、演算法邏輯(商業邏輯) 、物件結構定義
- View : 呈現給使用者看、操作的介面
- Controller : 依據傳入的資料該怎麼運作、程式流程的控制、該回傳給使用者什麼資料等
MVC
負責資料庫
要呈現哪一個資料,
並交由 Template 呈現
最後的 HTML 呈現
Why MTV ?
使用 MTV 架構的好處:
- 避免 Spaghetti Code
- 分離前後端
- 前後端可獨立作業
- 擁有更多彈性
- 較容易維護
- 降低程式複雜度
虛擬環境介紹
Introduction
- 你的專案會擁有一個專屬的獨立 Python 環境。
- 不需要 root 權限,就可以安裝新套件。
- 方便控管不同版本的套件,不用擔心升級套件會影響到其他專案。
建立好後,會出現剛剛取名的資料夾,切換進去
$ cd mysite
// 如果你剛剛取不一樣的名字
$ cd 名字
$ 不用打,只要打後面的指令
$ cd 到你想放資料夾的地方
$ mkdir 隨便你取
建好你要當作虛擬環境的資料夾
$ cd 到資料夾
前往該資料夾
$ python -m venv 你想取的名字
// 舉例來說
$ python -m venv venv
創建虛擬環境
$ pip install virtualenv
如果你是用 mac 記得先安裝
$ 你剛剛取的虛擬環境名稱\Scripts\activate
for Windows
for Mac
$ source 你剛剛取的虛擬環境名稱/bin/activate
進入虛擬環境
$ pip install django
安裝 Django
$ pip list
可以先 exit 到虛擬環境外後,再輸入:
這時候你就會發現剛剛在虛擬環境裡安裝的套件,真的沒有在外面。
建立 Django project
Introduction
建立專案資料夾 - startproject
首先,使用 django-admin.py 來建立第一個 Django project mysite :
$ django-admin.py startproject mysite
// 這裡是以取名為 mysite 為例
$ django-admin.py startproject 這裡可以放你要的名字
啟動開發伺服器 - runserver
runserver 會啟動一個簡單的 web server,方便於在開發階段使用
$ cd mysite // 先進到剛剛建好的 project 資料夾
$ python manage.py runserver
建立 Django app
Introduction
建立 Django app
利用 startapp 建立一個 Django app - blog
$ python manage.py startapp blog
// 這裡是以取名為 blog 為例
$ python manage.py startapp 這裡可以放你要的名字
新增 app
打開 mysite/settings.py,找到 INSTALLED_APPS
# 檔案位置:mysite/settings.py
...
# Application definition
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'blog', <--- !! 加在這裡 !!
)
Hello World!
Introduction
Django Views
Django view 其實是一個 function,處理 HttpRequest 物件,並回傳 HttpResponse 物件。
一個網頁程式當中的邏輯通常是這個樣子的:
在 Django 當中,處理這部分的邏輯稱之為 Django Views,通常我們都會放在 Django APP 當中的 views.py 檔案裡面。
request
進來
從資料庫
撈資料
處理
資料
把網頁
呈現出來
建立第一個 View
建立一個名為 hello_world 的 view
在 blog/views.py 輸入下列程式碼:
# 檔案位置:mysite/blog/views.py
from django.http import HttpResponse
def hello_world(request):
return HttpResponse("Hello World!")
Django URL 設定
Django 需要知道 URL 與 view 的對應關係
例如有人瀏覽 http://127.0.0.1:8000/hello/ 時 ,hello_world() 這個 view function 需要被執行。
而這個對應關係就是 URL conf (URL configuration)。
URL Conf
現在來設定 Hello World 的 URL conf。
打開 mysite/urls.py,import 剛剛寫的 view function:
from blog.views import hello_world
在 urlpatterns 中加入下面這行:
url(r'^hello/$', hello_world),
urls.py 目前的長相
# 檔案位置:mysite/mysite/urls.py
from django.conf.urls import include, url
from django.contrib import admin
from blog.views import hello_world
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^hello/$', hello_world),
]
剛剛寫了什麼鬼 ?
url(regex, view)
像剛剛寫得 url(r'^hello/$', hello_world),
- regex
- 定義的 URL 規則
- 規則以 regular expression 來表達
- r'^hello/$' 代表的是 hello/ 這種 URL
- view
- 對應的 view function
- 指的是 hello_world 這個 view
嗚呼,現在可以來說 Hello World 拉
現在啟動你的 web server,就像剛剛那樣:
$ cd ../ // 回到 mysite 資料夾
$ python manage.py runserver
在瀏覽器輸入 http://127.0.0.1:8000/hello/,你會看到網頁顯示我們在 HttpResponse 傳入的文字Hello World!
Templates
Introduction
建立資料夾
確認目前所在位置是在 mysite 裡
新增一個名為 templates 的資料夾
$ mkdir templates
設定 Templates 資料夾的位置
修改 mysite/settings.py 中的 TEMPLATES 設定
將 'DIRS' 原本的 [] 修改成:
[os.path.join(BASE_DIR, 'templates').replace('\\', '/')]
並在前面引入 os
import os
修改完的 TEMPLATES 設定應該要長這樣
# 檔案位置:mysite/mysite/settings.py
import os #前面要加入這句
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates').replace('\\', '/')],
'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',
],
},
},
]
在 templates 資料夾中新增一個 hello_world.html
<!-- 檔案位置:mysite/templates/hello_world.html -->
<!DOCTYPE html>
<html>
<head>
<title>I come from template!!</title>
<style>
body {
background-color: 你想要的顏色;
}
em {
color: 你想要的顏色;
}
</style>
</head>
<body>
<h1>Hello World!</h1>
<em>{{ current_time }}</em>
</body>
</html>
建立 Template
hello_world.html 的完整長相
<!-- 檔案位置:mysite/templates/hello_world.html -->
<!DOCTYPE html>
<html>
<head>
<title>I come from template!!</title>
<style>
body {
background-color: black;
}
h1 {
color: white;
}
em {
color: white;
}
</style>
</head>
<body>
<h1>Hello World!</h1>
<em>{{ current_time }}</em>
</body>
</html>
讓 Hello World 變厲害一點
掏出(?) 剛剛改過的 blog/views.py
把 hello_world 修改一下
# 檔案位置:mysite/blog/views.py
from datetime import datetime
from django.shortcuts import render
def hello_world(request):
return render(request, 'hello_world.html', {
'current_time': str(datetime.now()),
})
接著再打開來看看
$ python manage.py runserver
在瀏覽器輸入 http://127.0.0.1:8000/hello/
此時可以看到剛剛的模板被套用了,
而字跟背景會是你設定的顏色
將 view function hello_world 修改如下:
# 檔案位置:mysite/blog/views.py
from datetime import datetime
from django.shortcuts import render
def hello_world(request):
return render(request, 'hello_world.html', {
'current_time': str(datetime.now()),
})
使用 render function
Models
Installation
Models
- 為了使用資料庫來管理資料,透過 Models 來完成與資料庫的互動。
- 使用 Models 時,資料庫轉換相當方便。
# 檔案位置:mysite/mysite/settings.py
...
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
settings.py 中設定了資料庫連線的預設值
這裡為了方便直接使用預設的 SQLite 3
Basic OOP
Installation
OOP
Object Oriented Programming (物件導向程式設計)
將功能抽象化後,用程式表達出來的一種程式設計方式
Objects
Class
設計圖
實例化
實際的東西
都可以當成 Object
class ClassName:
你設定的 arrtibute 跟 method
Create a Class
class 的組成包含了
- 事物的屬性(attribute)
- 可做到的行為(method)
屬性分為兩種:
- 類別屬性(class attribute)
- 實例屬性(instance attribute)
Attributes
class motorcycle:
# class attribute
wheels = 2
# instance attributes
def __init__(self, color):
self.color = color
# method 1
def showDescription(self):
print("This motorcycle is ", self.color)
# method 2
def changeColor(self, color):
self.color = color
簡單來說就是在 class 中加入函式
Methods
第一個參數一定要是 self,即使 method 沒用到它
Create a function
def 函式名稱(參數):
程式碼
return 某個值
一個函式的基本架構如下 :
def hello():
print('Hello, World!')
建立一個最基本的函式
def hello():
print('Hello, World!')
hello() # 這樣就是呼叫
呼叫這個函式
def hello(name):
print('Hello,', name)
建立一個 帶參數 的函式
def hello(name):
print('Hello,', name)
hello('yan') # 呼叫時要給參數值
呼叫這個函式
def sum(a, b):
return a + b
建立一個帶有 return 的函式
def sum(a, b):
return a + b
x = sum(3, 4) # 呼叫時要給參數值
print(x)
呼叫這個函式
class Human:
type_name = 'human'
def __init__(self, name, age):
self.name = name
self.age = age
def eat(self):
print("I'm eating.")
Class Human
Attribute |
---|
type name |
name |
age |
Method |
---|
eat |
來寫個叫 Human 的 class 吧
class Human:
type_name = 'human'
def __init__(self, name, age):
self.name = name
self.age = age
class Human:
延續剛剛的程式碼,建立一個叫 yan 的 object :
# 變數名稱 = 函式名稱(參數)
yan = Human('yan', 20)
Create a Object
現在測試一下這個 object
print(yan.name, yan.age)
yan.eat()
class Human 完整程式碼
class Human:
type_name = 'human'
def __init__(self, name, age):
self.name = name
self.age = age
def eat(self):
print("I'm eating.")
yan = Human('yan', 20)
print(yan.name, yan.age)
yan.eat()
如果你還是搞不懂 class,可以參考一下這篇https://www.learnbyexample.org/python-classes-and-objects/
或是現在叫我再講一次
- 繼承是指,從原先有的 class 定義出新的 class 。
- 子類別會擁有父類別的 attribute 跟 method。
- 可以將相同事情歸在同一大類中。
Inheritance
舉個例子
Class
Class
繼承
Attributes
- Name
- Language
Attributes
- Name
- Language: Chinese
Methods
- Walk
- Eat
- Sleep
- Drink
Methods
- Walk
- Eat
- Sleep
Human
🇹🇼 Taiwanese
Objects
實例化
Attributes
- Name: 小明
- Language: Chinese
Methods
- Walk
- Eat
- Sleep
- Drink: bubble tea
小明
class Human:
type_name = 'human'
def __init__(self, name, age):
self.name = name
self.age = age
def eat(self):
print("I'm eating.")
class Taiwanese(Human):
def __init__(self, name, age):
super().__init__(name,age)
self.language = 'Chinese'
def drink(self, typeofdrink):
print("I drink %s"%typeofdrink)
先建立父類別(Human)
class Human:
type_name = 'human'
def __init__(self, name, age):
self.name = name
self.age = age
def eat(self):
print("I'm eating.")
class Human:
type_name = 'human'
def __init__(self, name, age):
self.name = name
self.age = age
def eat(self):
print("I'm eating.")
class Taiwanese(Human):
再建立子類別(Taiwanese)
繼承
可以另外增加屬於子類別的 attribute 或 method
class Human:
type_name = 'human'
def __init__(self, name, age):
self.name = name
self.age = age
def eat(self):
print("I'm eating.")
class Taiwanese(Human):
def __init__(self, name, age):
super().__init__(name,age)
yan = Taiwanese('yan',20)
print(yan.name(), yan.language())
yan.eat()
yan.drink('bubble tea')
建立 object ,測試一下剛剛寫的繼承
class Human:
type_name = 'human'
def __init__(self, name, age):
self.name = name
self.age = age
def eat(self):
print("I'm eating.")
class Taiwanese(Human):
def __init__(self, name, age):
super().__init__(name,age)
self.language = 'Chinese'
def drink(self, typeofdrink):
print("I drink %s"%typeofdrink)
yan = Taiwanese('yan',20)
print(yan.name, yan.language)
yan.eat()
yan.drink('bubble tea')
繼承的完整程式碼
Create a blog post model
Installation
定義 Models 的 object
# 檔案位置:mysite/blog/models.py
from django.conf import settings
from django.db import models
from django.utils import timezone
class Post(models.Model):
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
title = models.CharField(max_length=200)
text = models.TextField()
created_date = models.DateTimeField(default=timezone.now)
published_date = models.DateTimeField(blank=True, null=True)
def publish(self):
self.published_date = timezone.now()
self.save()
def __str__(self):
return self.title
打開 blog/models.py,刪掉所有東西然後改成:
開始一行一行解釋到底打了什麼囉 ouo
from django.conf import settings
from django.db import models
from django.utils import timezone
首先 import 一些會用到的套件
目標:建立一個 blog 文章資料庫
- title
- text
- author
- created_date
- published_date
而一篇文章中,應該會有以下這些元素
class Post(models.Model):
因為這個 class 是繼承 django.db.models.Model
所以後面小括號要塞進 models.Model
def publish(self):
在 class 中建立一個叫 publish 的 method
將 publish date 指派為當前的時間、儲存
self.published_date = timezone.now()
self.save()
def __str__(self):
return self.title
定義這個 object 的字串描述
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
外來鍵
代表對應到哪個 class
當對應的類別被刪除之後
這些對應到別人的資料要怎麼被處理
Primary key
- 每個資料表都必須要有一個主鍵的欄位。
- 主鍵不能為空值。
id | name |
---|
093 | Erica |
237 | Julie |
521 | Erica |
Foreign Key
- 用來建立不同資料表之間的關係。
- 一定是其他資料表的主鍵。
id | name | class |
---|
093 | Erica | 1 |
237 | Julie | 2 |
521 | Erica | 3 |
1 | A班 |
2 | B班 |
3 | C班 |
class_id | name |
---|
CharField:字串欄位
title = models.CharField(max_length=200)
設定可包含之字元個數
text = models.TextField()
TextField:沒有長度限制的長文本
非必填欄位
created_date = models.DateTimeField(default=timezone.now)
published_date = models.DateTimeField(blank=True, null=True)
DateTimeField:日期與時間欄位
可為空
Create tables
Installation
$ cd 到 mysite
$ python manage.py makemigrations blog
因為我們在 models.py 做了更動,
所以要告訴 Django 我們修改了一些內容
blog 是你的 app 名稱
$ Migrations for 'blog':
blog/migrations/0001_initial.py
- Create model Post
完成後會出現以下的文字敘述
$ python manage.py migrate blog
接著將 Post 這個 model 放進資料庫
blog 是你的 app 名稱
$ Operations to perform:
Apply all migrations: admin, auth, blog...
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
...
完成後會出現類似的文字敘述
Django admin
Installation
Django Admin ?
- Django 內建的一個 App
- 經設定可用來管理後台
首先我們要來同步 Django 專案下 models.py 中
預設的類別(Class) 及資料庫
$ python manage.py migrate
$ python manage.py createsuperuser
而要使用 Django 的管理後台,
我們需要一個管理員帳號。
接著就照著指示建立好帳號,創建密碼時是不會顯示的,要自己記得打到哪裡
# 檔案位置:mysite/blog/admin.py
from django.contrib import admin
from .models import Post
admin.site.register(Post)
還要讓 Django 知道,有哪些 Model 需要管理後台。
修改 blog/admin.py
$ python manage.py runserver
完成後連至 http://127.0.0.1:8000/admin,
即可看到管理後台的登入頁面:
登入後畫面
如果剛剛有註冊好你需要 Django 管理後台的 Model,這邊就會出現它
按下 add posts,就能看到我們剛剛寫的那些欄位
新增一篇文章試試看
建立首頁
Installation
# ...
from blog.models import Post
def home(request):
post_list = Post.objects.all()
return render(request, 'home.html', {
'post_list': post_list,
})
在 blog/views.py 內新增
建立首頁的 view
# 檔案位置:mysite/blog/views.py
from datetime import datetime
from django.shortcuts import render
from blog.models import Post
def home(request):
post_list = Post.objects.all()
return render(request, 'home.html', {
'post_list': post_list,
})
def hello_world(request):
return render(request, 'hello_world.html', {
'current_time': str(datetime.now()),
})
目前完整的 blog/views.py
# 檔案位置:mysite/mysite/urls.py
from django.conf.urls import include, url
from django.contrib import admin
from diary.views import hello_world, home # 這邊要新增
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^hello/$', hello_world),
# 還有這裡也要新增
url(r'^$', home),
]
將 mysite/mysite/urls.py 修改
設定首頁的 URL
<!-- 檔案位置:mysite/templates/home.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>My blog</title>
</head>
<body>
<h1>Hello! This is my blog</h1>
<div class="container">
{% for post in post_list %}
<div class="post">
<h2><a href="{% url 'post_detail' pk=post.pk %}">{{ post.title }}</a></h2>
<p>{{ post.created_date }}</p>
<p>{{ post.text }}</p>
</div>
{% endfor %}
</div>
</body>
</html>
在 templates 資料夾中新增一個 home.html
建立首頁的 Template
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',
],
},
},
確定一下 mysite/mysite/settings.py 是否長這樣
更改 settings.py
接著再打開來看看
$ python manage.py runserver
現在一打開你就能看到剛剛新增好的首頁啦
建立 Post
Installation
from django.shortcuts import render
from django.http import HttpResponse
from blog.models import Post
def hello_world(request):
return HttpResponse("Hello World!")
def home(request):
post_list = Post.objects.all()
return render(request, 'home.html', {
'post_list': post_list,
})
# 新增這邊
def post_detail(request, pk):
post = Post.objects.get(pk=pk)
return render(request, 'post.html', {'post':post})
在 mysite/blog/views.py 內新增
建立 Post 的 view
from django.conf.urls import include, url
from django.contrib import admin
from blog.views import hello_world, home, post_detail #新增這裡
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^hello/$', hello_world),
url(r'^$', home),
# 還有這裡也要新增
url(r'^post/(?P<pk>\d+)/$', post_detail, name='post_detail'),
]
修改 mysite/mysite/urls.py
設定文章的 URL
建立文章介面
Installation
在 blog 資料夾內建立一個 static 資料夾
裡面再建立一個 css 資料夾
先來開個資料夾
venv
mysite/
├── manage.py
├── mysite
├── templates
└── blog
├── static
└── css
h1 a {
color: orange;
}
h1{
text-align: center;
color: #8CB2D0;
}
h2{
text-align: center;
color: #8CB2D0;
font-style:italic;
}
body p {
text-align: center;
font-style:italic;
}
.post {
color: #A89797;
font-family: 'Dancing Script', cursive;
}
.page-header {
background-color: #B6533E;
margin-top: 0;
padding: 20px 20px 20px 40px;
}
.container{
display: flex;
justify-content: space-around;
}
建立 mysite/blog/static/css/blog.css
{% load static %}
<html>
<head>
<meta charset="utf-8">
{% block title %}
{% endblock %}
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">
<link rel="stylesheet" href="{% static 'css/blog.css' %}">
<link href="https://fonts.googleapis.com/css2?family=Dancing+Script:wght@500&display=swap" rel="stylesheet">
</head>
<body>
<div class="page-header">
<h1><a href="/">My Blog</a></h1>
</div>
{% block content %}
{% endblock %}
</body>
</html>
mysite/templates/base.html
建立 base.html
{% extends "base.html" %}
{% block title %}
<title>test blog</title>
{% endblock %}
{% block content %}
<h2>Hello! this is my blog</h2>
<div class="container">
{% for post in post_list %}
<div class="post">
<h2><a href="{% url 'post_detail' pk=post.pk %}">{{ post.title }}</a></h2>
<p>{{ post.created_date }}</p>
<p>{{ post.text|linebreaksbr|slice:":30" }}</p>
</div>
{% empty %}
<p>敬請期待</p>
{% endfor %}
</div>
{% endblock %}
mysite/templates/home.html
修改 home.html
{% extends "base.html" %}
{% block title %}
<title>{{ post.title }} | test blog</title>
{% endblock %}
{% block content %}
<div class="post">
<h2><a href="#">{{ post.title }}</a></h2>
<p>{{ post.created_date }}</p>
<p>{{ post.text }}</p>
</div>
{% endblock %}
mysite/templates/post.html
新增 post.html
新增一篇文章
連至 http://127.0.0.1:8000/admin,從管理後台新增一篇測試用文章
$ python manage.py runserver
接著打開首頁 http://127.0.0.1:8000/ 測試看看
應該會看到剛剛新增好的文章,也能點擊進去
加上 navbar
Installation
{% load static %}
<html>
<head>
<meta charset="utf-8">
{% block title %}
{% endblock %}
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">
<link rel="stylesheet" href="{% static 'css/blog.css' %}">
<link href="https://fonts.googleapis.com/css2?family=Dancing+Script:wght@500&display=swap" rel="stylesheet">
</head>
<body>
<nav class="navbar">
<a class="navbar-brand" href="/">My blog</a>
<a class="navbar-brand" href="https://github.com/">My github</a>
<a class="navbar-brand" href="/admin">Sign in</a>
</nav>
<div class="page-header">
<h1><a href="/">My Blog</a></h1>
</div>
{% block content %}
{% endblock %}
</body>
</html>
mysite/templates/base.html
修改 base.html
/*新增這邊*/
.navbar {
list-style-type: none;
margin: 0;
padding: 0;
background-color: #FCA205;
}
.navbar a{
color: #FFFFFF;
}
/*到這邊*/
h1 a {
color: #FCA205;
}
h1{
text-align: center;
color: #8CB2D0;
}
h2{
text-align: center;
color: #8CB2D0;
font-style:italic;
}
body p {
text-align: center;
font-style:italic;
}
.post {
color: #A89797;
font-family: 'Dancing Script', cursive;
}
.page-header {
background-color: #B6533E;
margin-top: 0;
padding: 20px 20px 20px 40px;
}
.container{
display: flex;
justify-content: space-around;
}
修改 mysite/blog/static/css/blog.css
你的首頁 http://127.0.0.1:8000/ 就會有 navbar 啦
而上面的連結能點擊進去
部署
Installation
$ pip install dj-database-url gunicorn dj-static
$ pip install heroku psycopg2-binary
套件安裝
接著將套件全部條列出來
$ pip freeze > requirements.txt
並在 requirements.txt 中加入 psycopg2==2.8.5
大概會長得像下面這樣
asgiref==3.3.1
certifi==2020.12.5
chardet==4.0.0
dj-database-url==0.5.0
dj-static==0.0.6
Django==3.1.7
gunicorn==20.0.4
heroku==0.1.4
idna==2.10
psycopg2-binary==2.8.6
python-dateutil==1.5
pytz==2021.1
requests==2.25.1
sqlparse==0.4.1
static3==0.7.0
urllib3==1.26.4
psycopg2==2.8.5
在 mysite 中(第一層)新增叫做 Procfile 的檔案
web: gunicorn --pythonpath mysite mysite.wsgi
mysite
├── Procfile
├── blog
├── db.sqlite3
├── manage.py
├── mysite
├── requirements.txt
└── templates
在 mysite/mysite 中(第二層)新增叫做 production_settings.py 的檔案
# 檔案位置:mysite/mysite/production_settings.py
# Import all default settings.
from .settings import *
import dj_database_url
DATABASES = {
'default': dj_database_url.config(),
}
# Static asset configuration.
STATIC_ROOT = 'staticfiles'
# Honor the 'X-Forwarded-Proto' header for request.is_secure().
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
# Allow all host headers.
ALLOWED_HOSTS = ['*']
# Turn off DEBUG mode.
DEBUG = False
修改 wsgi.py
# 檔案位置:mysite/mysite/wsgi.py
import os
from django.core.wsgi import get_wsgi_application
from dj_static import Cling
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")
application = Cling(get_wsgi_application())
新增 .gitignore
# 檔案位置:mysite/.gitignore
venv #這裡是你的虛擬環境名稱
*.pyc
__pycache__
staticfiles
db.sqlite3
目前的檔案結構
mysite
├──mysite
│ ├── blog
│ │ ├── __init__.py
│ │ ├── production_settings.py
│ │ ├── settings.py
│ │ ├── urls.py
│ │ └── wsgi.py
│ ├── templates
│ └── manage.py
├── venv
├── .gitignore
├── Procfile
└── requirements.txt
Heroku
首先到官網註冊一下
建立 Git Repository
$ git init
$ git add .
$ git commit -m "add all"
-m 後面的訊息可自訂
加到環境變數中
$ set PATH=%PATH%;C:\Program Files\Heroku\bin #Heroku安裝的路徑
登入並新增新的 Heroku App
$ heroku login
$ heroku create
如果你想要自己取 app 的名稱,指令如下:
$ heroku create 這裡放app名稱
設定環境變數
$ heroku config:set DJANGO_SETTINGS_MODULE=mysite.production_settings
將專案上傳到 Heroku
$ heroku config:set DJANGO_SETTINGS_MODULE=mysite.production_settings
將專案上傳到 Heroku
$ git push heroku master
網站初始化
$ heroku ps:scale web=1
$ heroku run python mysite/manage.py migrate
$ heroku run python mysite/manage.py createsuperuser
試試看成功了沒
$ heroku open
Thanks for listening.
References
- Andy Lu. (2018). 玩 Django — Part 3 (MTV 架構). Retrieved from https://reurl.cc/D99R9Q
- zhaoolee. (2018). Pipenv一键搭建python虚拟环境. Retrieved from https://www.jianshu.com/p/1441169b3dbe
- Toyo. (2018). [C#][.Net MVC] 02. 什麼是MVC架構. Retrieved from https://progressbar.tw/posts/95
- bessyhuang. (2019). Django 網站開發. Retrieved from https://hackmd.io/kwk4rdTjQli6qHObtpn68g?view#%E8%AA%B2%E7%A8%8B%E7%B0%A1%E4%BB%8B%E8%88%87%E7%9B%AE%E6%A8%99
兩堂課帶你入門 Django
By oneone
兩堂課帶你入門 Django
【SIRLA 2021 對外課程】雖然寫著兩堂課,但其實是(目標)兩堂課帶你入門
- 172