# Django
## 安裝Django
確認Python版本
```
...\> py -m django --version
```
利用pip套件來安裝Django
```
pip install django
```
## 建立新專案
```
...\> django-admin startproject mysite
```
mysite 為專案名稱可以自行設定
### 檔案結構
```
mysite/
manage.py
mysite/
__init__.py
settings.py
urls.py
asgi.py
wsgi.py
```
結構說明:
* mysite/
最外層的專案容器的名稱,可自行更改。
* manage.py
一個命令列工具程式,幫忙 Django 專案中各種互動。
* mysite/
此目錄下是實際的 Python 項目,可以在此導入各種內容。
* mysite/\_\_init\_\_.py
一個空文件,告訴Python該目錄應視為 Python 軟件包。
* mysite/settings.py
Django項目的設定/配置。 Django設定將告訴您所有設定的工作方式。
* mysite/urls.py
Django項目的URL聲明。為此專案網站的“目錄”。
* mysite/asgi.py
一個為專案提供服務(與ASGI兼容的Web服務器)的入口點。
* mysite/wsgi.py
一個為專案提供服務(與WSGI兼容的Web服務器)的入口點。
[WSGI規範](https://wsgi.readthedocs.io/en/latest/)
## 開啟伺服器
```
...\> py manage.py runserver
```
成功會出現
```
Performing system checks...
System check identified no issues (0 silenced).
You have unapplied migrations; your app may not work properly until they are applied.
Run 'python manage.py migrate' to apply them.
March 24, 2020 - 15:50:53
Django version 3.0, using settings 'mysite.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
```
:::success
更換不同端口
```
...\> py manage.py runserver 8080
```
:::
## 新增功能
:::info
app 在 Django 代表的是一個網站的應用(一項功能)。
根據功能的差異來分類 app。 e.g. 登入功能、點餐功能 ...等等
:::spoiler *Projects vs. apps*
What’s the difference between a project and an app? An app is a Web application that does something – e.g., a Weblog system, a database of public records or a small poll app. A project is a collection of configuration and apps for a particular website. A project can contain multiple apps. An app can be in multiple projects.
:::
```
#加入點餐功能
...\> django-admin startapp orders
```
### APP 資料結構
```
mysite/
manage.py
mysite/...
orders/
__init__.py
admin.py
apps.py
migrations/
__init__.py
models.py
tests.py
views.py
```
結構說明:
* admin.py : 設定資料庫呈現的模式,之後會跟 models 溝通。
* models.py : 建構你的資料庫型態。
* tests.py : 用來測試你的邏輯是否有遺漏。
* views.py : 寫商業邏輯的地方,跟 urls.py 做呼應並將所需傳達給前端
* urls.py : 讓 views.py 與相對的網站做對應,要自行建立。
* apps.py : 用來區別 app 的一個檔案。
* \_\_init\_\_.py : 告訴 Python 這資料夾是個套件。
* migrations : 記錄 models 裡面所創建的資料庫型態。
#### 編輯 orders/views.py 內容
建立點餐方法及邏輯
#### 建立並在 orders/urls.py 中添加路徑
* orders/urls.py
設定 app 中 urls 對應。(類似區域性概念)
```
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index'),
]
```
* mysite/urls.py
修改主要網站站點中 urls 對應。(類似廣域概念)
```
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path('orders/', include('orders.urls')),
path('admin/', admin.site.urls),
]
```
* Path [用法說明](https://docs.djangoproject.com/en/3.0/ref/urls/)
## 修改設定 settings
* 修改時區為 'Asia/Taipei' [pytz](https://docs.djangoproject.com/en/2.2/_modules/pytz/)
* 設定及管理 [static files](https://docs.djangoproject.com/en/dev/howto/static-files/)
在 mysite/settings.py 修改設定後
```
...\> py manage.py migrate
```
## 更改模型 models
在 mysite/models.py 建立/修改模型後
```
...\> py manage.py makemigrations mysite
```
所建立的 Migration (資料遷移)檔案,存放在 app 下的 migrations 資料夾中,產生的0001_initial.py檔案(依序編號)。
Ref:
* [manage.py](https://docs.djangoproject.com/en/3.0/ref/django-admin/)
* [Models 說明文件](https://docs.djangoproject.com/en/3.0/ref/models/)
* 使用 ImageField 需安裝 Pillow library 幫助判斷是否為影像格式。[*Pillow library.*](https://pillow.readthedocs.io/en/latest/handbook/overview.html)
### Models 筆記
::::success
```
# carts.Model 中 cart 修改後 失敗:
python manage.py migrate --fake carts zero
python manage.py migrate carts
#報錯 carts 資料表已存在
sqlite3.OperationalError: table "carts_cart" already exists
#進入 sqlite 操作:
python manage.py dbshell
# 搜尋所有表格
.table
#確認資料表中的屬性
.schema carts_cart
#發現屬性不合,刪除資料表重建
DROP TABLE carts_cart
#檢查是否刪除
.table
#發現多了 carts_cart_product
DROP TABLE carts_cart_product
#檢查是否刪除
.table
#完成,離開
.exit
#重新遷移資料庫
python manage.py makemigrations
python manage.py migrate
```
::::
## 視圖(控制) Views
在 /views.py 中定義一些方法,處理響應、計算或控制資訊。
[Base views](https://docs.djangoproject.com/en/3.0/ref/class-based-views/base/)
[Date API reference](https://docs.djangoproject.com/en/3.0/ref/class-based-views/generic-date-based/)
[QuerySet API reference](https://docs.djangoproject.com/en/3.0/ref/models/querysets/)
### Views 筆記
::::success
```
# get_or_create() method; 如果查詢不到 Bob 或 Robert 就創建一個
from django.db.models import Q
obj, created = Person.objects.filter(
Q(first_name='Bob') | Q(first_name='Robert'),
).get_or_create(last_name='Marley', defaults={'first_name': 'Bob'})
```
::::
## 模板 Templates
* [Django Templates Doc](https://docs.djangoproject.com/en/3.0/topics/templates/)
* [利用 Tag 及 Filter 建立模板。](https://docs.djangoproject.com/en/3.0/ref/templates/builtins/)
能更快速、靈活地建立起網頁,互相調用減少重複製作。
### 簡介
::::info
- variables
變數,以 {{ 變數名 }} 表示
- Tag
標籤,{% 標籤名 %}
- Filters
過濾器,{ 標籤 \| 變數 } 將變參數傳入標籤
```
{{ my_date|date:"Y-m-d" }}
```
- include :
網頁模板後,插入當前網頁
```
#插入 navbar.html
{% include 'navbar.html' %}
```
- extend :
繼承一個網頁
```
#在網頁的一開始聲明繼承 base.html
{% extends 'base.html' %}
```
- block :
設定一個區塊,名為 content
```
#設定一個區塊
{% block content %}
write something ...
{% endblock %}
```
- comment :
```
#注釋
{# 注釋內容 #}
#多段注釋
{% comment %}
```
::::
### Templates 筆記
::::success
```
#內容太多,想使用 ... 表示時:
{{ content |truncatewords:30 }} 取 content 變數中前30字符,不可用於中文
{{ content |truncatechars:30 }} 取 content 變數中前30字符,可用於中文
#直接切掉,沒有 ...
{{ content |slice:30 }} 取 content 變數中前30字符,可用於中文
```
::::
#### 其他
* [Django REST Framework_quickstart](https://www.django-rest-framework.org/tutorial/quickstart/)
* [To build high-performance Web APIs, focus on the right things. ](https://www.dabapps.com/blog/api-performance-profiling-django-rest-framework/)
###### tags: `Django`