---
# System prepended metadata

title: Django

---

# **Django install**
> django 官網 : https://www.djangoproject.com/start/
> 別人的 hackmd : https://hackmd.io/@peterju/B12HQdsFO

* 安裝 python 並加入 path : https://www.python.org/downloads/windows/
* 安裝 vscode : https://code.visualstudio.com/
* python 3.6.6 加入 path
* cmd : `python --version` 檢查有沒有成功
* 安裝 pip : `python get-pip.py`
* cmd : `pip --version` 檢查有沒有成功
* 安裝虛擬機
```
//下載虛擬機
python -m pip install virtualenv

//打開權限
Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned

//創建虛擬機 myenv 是虛擬機的名字, 可以自己改
python -m venv myenv

//開啟虛擬機
myenv\Scripts\Activate

//關閉虛擬機
deactivate
```
* 開啟虛擬機就會像這樣

![螢幕擷取畫面 2024-03-15 201610](https://hackmd.io/_uploads/rJnZ6nW0T.png)
* 安裝 django (一樣要在虛擬機模式下)
```
//下載 django
pip install django

//確認版本
django-admin --version

//建立 project, Orange 是專案名稱可以自己改
django-admin startproject Orange
```
* 每個檔案的用途去看這邊 : https://ithelp.ithome.com.tw/articles/10199733
* 到 Orange\settings.py 改語言和時區
```
LANGUAGE_CODE = 'en-TW'

TIME_ZONE = 'Asia/Taipei'
```
* 啟動 web server
```
py manage.py runserver 
```
# **Project Setting**
* 創建 app : myapp
```
//創建 app : myapp
python manage.py startapp myapp
```
* 更改 Orange/setting.py
```
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'myapp',        # 加入 myapp
]
```
* 建立靜態檔案, 模板
```
md templates
md static
md static\images
md static\css
md static\js
md static\plugins
```
* 更改 Orange/setting.py 公開 templates 路徑讓所有 apps 都可以調用
```
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [BASE_DIR / "templates"],        #加入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',
            ],
        },
    },
]
```
* 將下面這行加入 Orange/settings.py, 公開 static 路徑
```
import os
STATICFILES_DIRS=[
    os.path.join(BASE_DIR,"static")
]
```
---
下面隨個人喜好設定, 可做可不做
* 到官網下載 bootstrp : https://getbootstrap.com/docs/5.3/getting-started/download/
* 將檔案複製到 Orange/static/plugins
* 加入 <link> 到 html 檔案, 連結到 bootstrp 檔案
<!DOCTYPE html>
```
<link rel="stylesheet" href="/static/plugins/bootstrap-5.3.3-dist/css/bootstrap.css">
```
* 也可以使用網頁連結, 這樣就不需要下載 bootstrp 檔案, 但沒網路會跑不出來
```
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
```

# **Simple Creation**
## Example 1 : Views html 溝通, URL 映射
* Orange/urls.py
```
from django.contrib import admin
from django.urls import path
from myapp import views as myapp_views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('index/', myapp_views.index),
    path('index2/', myapp_views.index2),
    path('hello/<name>', myapp_views.hello),
]
```
* Orange/templates/index.html
```
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{{name}}</title>
</head>
<body>
    <p>{{name}}</p>
    <p>{{age}}</p>
</body>
</html>
```
* Orange/myapp/views.py
```
from django.shortcuts import render
from django.http import HttpResponse

# Create your views here.   
def index(request):
    return render(request, "index.html",{
        "name":"Orangebaby",
        "age":"20"
    })

def hello(request, name):
    return HttpResponse("Hello " + name)

def index2(request):
    context={}
    context["age"]="20"
    context["name"]="Orangebaby"
    return render(request, "index.html", context)
    
#index and index2 兩種方法相同
```
* 嘗試打開 http://127.0.0.1:8000/index/, http://127.0.0.1:8000/index2/ views 兩種不同的傳值方法, 效果相同
* hello/ 後面的字, 會直接接入網頁內, http://127.0.0.1:8000/hello/Orange
## Example 2 : 引入 static 資料
* 下載圖片 : https://www.pinterest.com/pin/281543723295792/, 放入 Orange/static/images
* 將 staic 檔案資料載入 index.html 
```
<body>
    {%load static%}
    <img src="{%static 'images/ppp.jpg'%}" height="500">
</body>
```
## Example 3 : 模板繼承
* 將 base.html 整個繼承到 index.html, 其中只需定義 block 的資料即可
* index.html
```
{% extends "base.html" %}
{% block mainbody %}
<p> Orange </p>
{% endblock mainbody %}

{% block food %} apple {% endblock food %}
```
* base.html
```
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Orange</title>
</head>
<body>
    <p>Hi</p>
    {% block mainbody %}
    {% endblock mainbody %}
    <p>我想吃 {% block food %}{% endblock food %}</p>
</body>
</html>
```
## Example 3 : dict, list, if/else, for loop
* myapp/views.py
```
from django.shortcuts import render
from django.http import HttpResponse

# Create your views here.   
def index(request):
    context={}
    context["name"] = "Orange"
    views_list = ["Apple", "Banana", "Cheese"]
    context["list"] = views_list
    views_dic = {"food":"Apple","color":"red","number":10}
    context["dict"] = views_dic
    lucky_number = 80
    context["lucky_number"] = lucky_number
    return render(request, "index.html",context)
```
* index.html
```
<body>
    {# list #}
    <h1><b>list section</b></h1>
    <p>{{ list }}</p>                            
    <p>{{ list.0 }}</p>
    <p>{{ list.1 }}</p><p>{{ list.2 }}</p>
    {# dict #}
    <h1><b>dict section</b></h1>
    <p>{{ dict }}</p>
    <p>{{ dict.food }}</p>
    <p>{{ dict.color }}</p>
    <p>{{ dict.number }}</p>
    {# if/else #}
    <h1><b>if/else section</b></h1>
    <p>
        {% if lucky_number >= 100 %}
            You are lucky.
        {% elif lucky_number >= 50 %}
            You are normal.
        {% else %}
            You are poor
        {% endif %}
    </p>
    {# for loop #}
    <h1><b>for loop section</b></h1>
    <p>
        {% for food in list %}
            {{food}}
        {% endfor %}
        <br>
        {% for key, value in dict.items %}
            {{key}} : {{value}}&ensp;
        {% endfor %}
        <br>
        {% for i in emptylist %}
            i
        {% empty %}
            This list is empty
        {% endfor %}
    </p>
</body>
```
## Example 4 : 自定義標籤
* Orange/setting.py 新增 libraries
```
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [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',
            ],
            'libraries':{        #新增 libraries
                'my_def':'templates.my_def', #自定義函數的位置
            }
        },
    },
]
```
* Orange/templates/my_def.py
```
from django import template
from django.utils.safestring import mark_safe

register = template.Library()

@register.simple_tag
def add(a, b, c):
    return a+b+c

@register.simple_tag
def input():
    temp = f'''
    <ul class="dropdown-menu position-static d-grid gap-1 p-2 rounded-3 mx-0 shadow w-220px" data-bs-theme="light">
        <li><a class="dropdown-item rounded-2 active" href="#">Action</a></li>
        <li><a class="dropdown-item rounded-2" href="#">Another action</a></li>
        <li><a class="dropdown-item rounded-2" href="#">Something else here</a></li>
        <li><hr class="dropdown-divider"></li>
        <li><a class="dropdown-item rounded-2" href="#">Separated link</a></li>
    </ul>
    '''
    return mark_safe(temp)
```
* Orange/templates/index.html
```
<!DOCTYPE html>
<html lang="en">
    {% include "header.html" %}
<body>
    {% load my_def %}
    <h1> {% add 10 20 30 %} </h1><br><br>
    {% input %}
</body>
</html>
```
* Orange/templates/header.html
```
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{{name}}</title>
    <link rel="stylesheet" href="/static/plugins/bootstrap-5.3.3-dist/css/bootstrap.css">
</head>
```
# **DataBase**
* 下載 Mysql
```
pip install mysqlclient
```

* 變更 Django 使用的資料庫
```
DATABASES = {        #記得下面都要填仔細, 不然 web 會跑不起來
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'your_database_name',
        'USER': 'your_mysql_username',
        'PASSWORD': 'your_mysql_password',
        'HOST': 'localhost',
        'PORT': '3306',
    }
}
```
* 內建 APP 所需之資料表
```
py manage.py migrate
```
* 更新 myapp/model.py, 變更資料模型 (直接決定資料庫的模型)
```
from django.db import models        #This is example
from django.utils import timezone

# Create your models here.
class student(models.Model):
    SEX_CHOICES = [
        ('M', '男'),
        ('F', '女'),
    ]
    cName = models.CharField('姓名',max_length=20, null=False)
    cSex = models.CharField('性別',max_length=1, choices=SEX_CHOICES, default='', null=False)
    cBirthday = models.DateField('生日',null=False)
    cEmail = models.EmailField('Email',max_length=100, blank=True, default='')
    cPhone = models.CharField('手機',max_length=50, blank=True, default='')
    cAddr = models.CharField('地址',max_length=255, blank=True, default='')
    last_modified = models.DateTimeField('最后修改日期', auto_now = True)
    created = models.DateTimeField('保存日期',default = timezone.now)

    def __str__(self):
        return self.cName
```
* 將模型的異動產生 migrations 遷移檔
```
py manage.py makemigrations myapp
```