Django
Lecturer:Yan
2020 / 4 / 5
Models
-
Introduction of model.
-
Basic OOP
-
Create an application.
-
Create a blog post model.
-
Create tables.
-
Django admin
Outline
Introduction of Model
Models
- 為了使用資料庫來管理資料,透過 Models 來完成與資料庫的互動。
- 使用 Models 時,資料庫轉換相當方便。
# mysite/settings.py
...
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
settings.py 中設定了資料庫連線的預設值
這裡為了方便直接使用預設的 SQLite 3
Basic OOP
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/
或是現在叫我再講一次
Lab 1 - Class
建立一個叫 cat 的 class
- attribute:姓名、年齡
- method:會叫
Lab 1 - Class
little_white = Cat('你幫那隻貓取的名字',3)
little_white.purr()
print(little_white.name)
你設定的叫聲
你幫那隻貓取的名字
建立一個叫小白的 Object
希望出現的結果:
class Cat:
# attribute
def __init__(self,name,age):
self.name = name
self.age = age
# method
def purr(self):
print('meow')
little_white = Cat('little_white',3) # 實例化 class
little_white.purr() # 呼叫 class 的 method
print(little_white.name) # 呼叫 class 的 attribute
Lab - 1 完整程式碼
- 繼承是指,從原先有的 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')
繼承的完整程式碼
Lab 2 - Inheritance
建立一個叫 kitten 的 class 並繼承剛剛寫的 Cat
- attribute:名字、年齡、顏色
- method:會叫、會抓
class kitten(Cat):
def __init__(self,name,age,color):
super().__init__(name,age)
# 新增 attribute - 花色
self.color = color
def scarch(self):
# 新增 method - 抓
print('sofa gg')
little_black = kitten('little_black',6,black) # 建立 object
little_black.purr() # 呼叫父類別的 method
print(little_black.name) # 呼叫父類別的 attribute
little_black.scarch() # 呼叫子類別的 method
print(little_black.color) # 呼叫子類別的 attribute
Lab - 2 子類別寫法
# 父類別
class Cat:
# attribute
def __init__(self,name,age):
self.name = name
self.age = age
# method
def purr(self):
print('meow')
# 建立一個叫 kitten 的 class 並繼承剛剛寫的 Cat
class kitten(Cat):
def __init__(self,name,age,color):
super().__init__(name,age)
# 新增 attribute - 花色
self.color = color
def scarch(self):
# 新增 method - 抓
print('sofa gg')
little_black = kitten('little_black',6,black) # 建立 object
little_black.purr() # 呼叫父類別的 method
print(little_black.name) # 呼叫父類別的 attribute
little_black.scarch() # 呼叫子類別的 method
print(little_black.color) # 呼叫子類別的 attribute
Lab - 2 完整程式碼
Creat an application
$ 不用打,只要打後面的指令
進到上次建立的虛擬環境中
$ cd 到上次建立的資料夾
$ venv\Scripts\activate
$ cd 到上次建立的資料夾
$ source venv/bin/activate
for Windows
for Mac
如果你不小心刪掉上次的 venv 了
不用翻之前的 slide,你要的都在這~
$ cd 到你要建虛擬環境的資料夾
$ python -m venv 你想取的名字
$ source venv/bin/activate #用 windows 的請去掉 source
$ pip install django
$ django-admin startproject mysite
如果你不小心刪掉上次的 project
$ django-admin startproject mysite
新建 app
$ python manage.py startapp blog
blog 是可以換成你想取的 app 名稱的
告訴 Django 需要管理的 app
修改 mysite/settings.py
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'trips',
# 新增
'blog',
)
記得是要加入你剛剛建立的 app 名稱
Create a blog post model
定義 Models 的 object
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
$ 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
Django Admin ?
- Django 內建的一個 App
- 經設定可用來管理後台
$ python manage.py createsuperuser
要使用 Django 的管理後台,
我們需要一個管理員帳號。
接著就照著指示建立好帳號
# blog/admin.py
from django.contrib import admin
from .models import Post
admin.site.register(Post)
還要讓 Django 知道,
有哪些 Model 需要管理後台。
$ python manage.py runserver
完成後連至 http://127.0.0.1:8000/admin,
即可看到管理後台的登入頁面:
登入後畫面
按下 add posts,就能看到我們剛剛寫的那些欄位
Thanks for listening.
References
- Google. (2019). Python Classes and Objects. Retrieved from https://www.learnbyexample.org/python-classes-and-objects/
- Google. (2019). Python Inheritance. Retrieved from https://www.learnbyexample.org/python-inheritance/
- Django girls - taipei. (2016). Models. Retrieved from https://djangogirlstaipei.gitbooks.io/django-girls-taipei-tutorial/django/models.html
- Django girls. (2016). Django 模型. Retrieved from https://tutorial.djangogirls.org/zh/django_models/
- BY. (2018). Day6 : 資料庫的創建 - Models. Retrieved from https://ithelp.ithome.com.tw/articles/10200181
- Kyle Bai. (2014). 基本物件導向概念. Retrieved from https://k2r2bai.com/2014/06/03/msic/oop/
References
Django - Models
By oneone
Django - Models
SIRLA 2020 Django Tutorial
- 191