iT邦幫忙

2024 iThome 鐵人賽

DAY 3
1
Software Development

Django 2024: 從入門到SaaS實戰系列 第 4

Django in 2024: 總是得從這裡開始,Hello world!第一個Django專案

  • 分享至 

  • xImage
  •  

在我們建構第一個Django專案之前,必須要先聲明虛擬環境的重要性

以前還沒什麼觀念的時候,看到一些影片的安裝教學都直接安裝軟體,安裝的方式可能也有百百種

等到之後想移除時,可能在多個路徑下都有不同版本的相同軟體

在使用IDE引用來源時可能也是胡亂使用,這時候就很想要重頭開始一個乾淨的環境

也體現出使用虛擬環境的重要性

python有以下幾種套件可以幫忙建立虛擬環境

  1. venv
    • Python 3.x內建的模組,無需額外安裝。使用**python -m venv <環境名稱>**命令可以輕鬆建立虛擬環境
    • 只能使用創建時的python版本,且無法指定系統中不存在的python版本
    • 不能查看虛擬環境的環境列表
  2. virtualenv
    • 可以使用**pip install virtualenv安裝,然後使用virtualenv <環境名稱>**來創建虛擬環境。它支持Python 2和Python 3,並且能夠創建不同Python版本的虛擬環境
    • 跟venv功能雷同,區別在存放虛擬環境的位置
  3. pipenv
    • 結合了**pipvirtualenv的功能,提供了更高層次的包管理和虛擬環境管理。使用pipenv install**可以創建虛擬環境並安裝依賴。適合需要管理多個依賴的項目
    • 專案的前景較為堪憂
  4. Poetry
    • 一個較新的包管理和虛擬環境管理工具,專注於簡化Python專案的依賴管理。使用**poetry new <專案名稱>**創建新專案時會自動建立虛擬環境,並且提供了清晰的配置文件管理
    • 學習曲線較陡峭

這些工具各有特點,看各位自己的習慣進行使用,在這個系列文章中,我會使用poetry來建構我的虛擬環境。如果想更了解一些poetry的指令,我之前有寫過一篇文章就不詳細展開了

https://ithelp.ithome.com.tw/articles/10340858

建構環境

# 初始化虛擬環境
poetry new django_project

# 安裝Django 這邊使用4.2LTS版本,也可以直接選擇最新的安裝
poetry add Django==4.2
# 用於連接與操作postreSQL
poetry add psycopg2-binary 

確認是否成功,除了可以看poetry.lock檔案之外,輸入指令poetry show --tree也可以看安裝套件的相關依賴

django 4.2 A high-level Python web framework that encourages rapid development and clean, pragmatic design.
├── asgiref >=3.6.0,<4
├── sqlparse >=0.3.1
└── tzdata *

第一個Django專案

那我們現在就來進到我們第一個專案~

專案程式碼放在:https://github.com/class83108/django_project/tree/hello_world

# 先刪除不必要的包
rm -rf django_project

# 啟動虛擬環境
poetry shell

# 建立專案
django-admin startproject django_project

# 查看專案結構
tree
.
├── django_project
│   ├── __init__.py
│   ├── asgi.py # 如果專案需要用到非同步功能,使用asgi啟動django專案
│   ├── settings.py # 重要的設定都包含在裡面
│   ├── urls.py # 路由,說明哪些url指到哪些view中
│   └── wsgi.py # 如果不使用非同步,會使用wsgi啟動Django專案
└── manage.py # 命令工具,可以執行多種功能

我們可以透過python3 manage.py 指令來看有哪些命令可以執行

# 這邊只列出幾個我比較常使用的
[auth]
    createsuperuser # 用來建立超級用戶 管理後台與相關權限

[django]
		dumpdata # 匯出資料庫的資料
    inspectdb # 匯出目前DB中所有table的配置
    loaddata # 將外部資料載入資料庫
    makemigrations # 整理出model有變動的部分
    migrate # 將makemigrations紀錄的資料實施到DB中
    shell # 進入shell模式,可以做一些基本的CRUD操作
    startapp # 建立新的app
    test # 對每個app下的test*.py檔中的內容進行測試

[staticfiles]
    collectstatic # 將每個app下以及安裝套件下的所有靜態資源根據參數匯入到特定資料夾
    runserver # 啟動本機專案

現在對這些命令如果還沒有什麼概念的話也沒有關係,之後操作到的時候就會有想法了

並且除了Django預設的命令,也可以建立management/commands來客製化自己的指令

那就來啟動我們的專案吧

python3 manage.py runserver
# 可以在最後面加上port ex: python3 manage.py runserver 8888
# 默認啟動在8000 port上

接著在瀏覽器輸入http://127.0.0.1:8000/

能看到以下畫面就代表我們成功啟動Django專案了!
https://ithelp.ithome.com.tw/upload/images/20240915/20161866R9uKJlnUpf.png

基礎設置

我們先在manage.py同目錄建立其他幾個資料夾static, staticfiles與templates以及建立.env檔

專案目錄如下:

.
├── django_project
│   ├── __init__.py
│   ├── __pycache__
│   │   ├── __init__.cpython-312.pyc
│   │   └── settings.cpython-312.pyc
│   ├── asgi.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── manage.py # .env跟他同級
├── static # 放置靜態資源
│   ├── css
│   ├── images
│   └── js
├── staticfiles # 之後方便整合nginx等找到所有的靜態資源 之後會再展開說明
└── templates # 放網頁模板

.env中除了配置資料庫的設定值之外,還可以把許多敏感的資訊放進來

# .env
DB_HOST=127.0.0.1
DB_USER=your_db_user
DB_PWD=your_db_password
DB_NAME=your_db_name

SECRET_KEY=xxxxx

DEBUG=true

還需要安裝相關套件,才能順利導入環境變數

poetry add load-dotenv

接著到settings.py中導入相關的環境變數,並且簡單介紹基本的配置

# settings.py

from dotenv import load_dotenv
import os

# 環境變數檔案的路徑
ENV_FILE_PATH = BASE_DIR / ".env"

# 載入.env檔案
load_dotenv(ENV_FILE_PATH)

# 配置變數
# 設置debug 生產環境要改False
DEBUG = os.getenv("DEBUG").lower() == "true"

# 開發環境可以先不設置,生產環境要限制網域
ALLOWED_HOSTS = []

# postgreSQL 相關設定
DB_HOST = os.getenv("DB_HOST")
DB_USER = os.getenv("DB_USER")
DB_PWD = os.getenv("DB_PWD")
DB_NAME = os.getenv("DB_NAME")

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = os.getenv("SECRET_KEY")

# 註冊專案下的所有APP
INSTALLED_APPS = [
    'django.contrib.admin',
		....
    'django.contrib.staticfiles',
]

# 配置中間件 在request與response中扮演重要角色
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
		....
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

# 配置template的位置
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates/')], # 根據你template的資料夾決定
        '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',
            ],
        },
    },
]

# 連接DB 可以配置多個DB,但是一定要有一個default
DATABASES = {
    'default': { 
        'ENGINE': 'django.db.backends.postgresql', # 這邊我們設置postreSQL的資料庫
        'NAME': DB_NAME,
        'USER': DB_USER,
        'PASSWORD': DB_PWD,
        'HOST': DB_HOST,
        'PORT': '5432',
    },
}

# 配置靜態資源
STATIC_URL = 'static/' # 靜態資源的url
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')] # 在dev環境中靜態資源的位置
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') # 用在production環境中,靜態資源的位置

# 配置時區
TIME_ZONE = 'Asia/Taipei'

# 配置上傳檔案的路徑
MEDIA_URL = '/media/' # 上傳檔案的url配置
MEDIA_ROOT = os.path.join(BASE_DIR, 'uploads') # 讓django去這裡找檔案

這邊不詳細介紹static跟staticfile應用上的區別,之後如果需要用到的時候再來說明

此外因為在後面的專案會需要跟據schema來區分用戶的資料,所以DB推薦使用postgreSQL來進行配置,我是直接使用Docker啟動,相關配置如下

image: postgres:13-alpine
volumes:
    - ../postgres_data:/var/lib/postgresql/data
ports:
    - "5432:5432"
environment:
    - POSTGRES_DB=${DB_NAME}
    - POSTGRES_USER=${DB_USER}
    - POSTGRES_PASSWORD=${DB_PWD}

初入Django MTV

那我們現在再來複習一下Django的基本架構

使用者根據特定url發請請求→url找到相對應的ViewView依據特定邏輯處理Model中的資料→View拿到最終數據後渲染到Templates
https://ithelp.ithome.com.tw/upload/images/20240915/20161866l2R0LRNZwK.png

這邊我就先不提及Middleware的部分,之後如果有需求的時候再來做介紹

那我們就來透過實作來完成這樣的流程吧

  1. 首先建立article app

app的作用其實主要是方便管理,如果是真的很小很單純的專案的確可以所有配置在根目錄下完成

python3 manage.py startapp article

# app下的結構
├── __init__.py
├── __pycache__
├── admin.py
├── apps.py
├── migrations # 會紀錄每一次model的建立或是修改等資料
├── models.py # 配置model
├── tests.py
├── urls.py # 需手動添加 設置路由
└── views.py # 配置視圖
  1. 在settings.py中註冊app
INSTALLED_APPS = [
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
    # my apps
    "article",
]
  1. 進入app下的models.py

在models.py中,我們配置需要在資料庫中建立的表格,一個類別相當於一個表格

每一個類別都需要繼承models.Model,而類別的屬性則為表格中的欄位

我們需要新增的表格如下:

# article.models.py
from django.db import models

class Article(models.Model):
    article_id = models.AutoField(primary_key=True)
    title = models.CharField(max_length=120)
    content = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    category = models.ForeignKey("Category", on_delete=models.CASCADE)
    author = models.ForeignKey("Author", on_delete=models.CASCADE)
    tags = models.ManyToManyField("Tag")

class Category(models.Model):
    category_id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=120)

class Author(models.Model):
    author_id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=120)
    age = models.IntegerField()

class Tag(models.Model):
    tag_id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=120)

我們可以看到屬性也是使用models模塊下不同的類別,設定欄位的類型之外,也進行其他的配置

例如:

  • AutoField(primary_key=True):表示唯一標識符。AutoField 會自動增加,primary_key=True 表示這是主鍵,通常會被映射為資料庫中的 INTEGER 類型,
  • CharField(max_length=120):CharField 用於存儲較短的字符串,max_length=120 限制最大長度為120個字符,被映射為 VARCHAR類型
  • TextField():TextField 用於存儲長文本,沒有長度限制,被映射為TEXT 類型
  • DateTimeField():創建時間,auto_now_add=True 使其在創建時自動設置為當前時間,而auto_now=True 使其在每次保存時自動更新為當前時間。被映射為 DATETIME 類型
  • ForeignKey("Category", on_delete=models.CASCADE):與 Category 模型的外鍵關係,CASCADE 表示當關聯的 Category 被刪除時,文章也會被刪除
  • ManyToManyField("Tag"):與 Tag 模型的多對多關係,會建立一個額外的關聯表,包含兩個外鍵欄位,分別指向相關的兩個表

其他更詳細的配置可以看官方文檔:

https://docs.djangoproject.com/en/4.2/ref/models/fields/#field-types

  1. 接下來就要將這個設定遷移到資料庫中
python3 manage.py makemigrations

# output
Migrations for 'article':
  article/migrations/0001_initial.py
    - Create model Author
    - Create model Category
    - Create model Tag
    - Create model Article

該指令會建立migrations檔,讓之後的migrate指令知道要怎麼修改資料庫內的表格結構

接著輸入

python3 manage.py migrate

# output
Operations to perform:
  Apply all migrations: admin, article, auth, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying admin.0003_logentry_add_action_flag_choices... OK
  Applying article.0001_initial... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying auth.0010_alter_group_name_max_length... OK
  Applying auth.0011_update_proxy_permissions... OK
  Applying auth.0012_alter_user_first_name_max_length... OK
  Applying sessions.0001_initial... OK

可以看到除了我們建立的表格外,也有其他像是user, permission之類的表,這就是Django預設的表格,如果不想要用到這些表格可以從INSTALLED_APPS刪除

這也是我們一開始跑runserver指令時,你會看到下面的警告

You have 18 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.

我們去資料庫中看一下,我這邊是使用DBeaver來作為視覺化軟體,因為Mac要改成英文比較麻煩,我比較懶就暫時沒調整XD

可以看到表格們確實都出現了
https://ithelp.ithome.com.tw/upload/images/20240915/2016186653X33spPXZ.png
https://ithelp.ithome.com.tw/upload/images/20240915/201618666iJcmcAMRe.png

  1. 去建立tags的資料
python3 manage.py shell
# 進入shell模式,可以輸入簡單指令來操作

>>> from article.models import Tag
>>> tag = Tag(name="Django")
>>> tag.save()
# 先建立第一筆資料
>>> exit() # 退出shell模式
  1. Model的部分好了,我們來配置路由吧(url)
# 根目錄下的urls.py
from django.urls import path, include

urlpatterns = [
    path("admin/", admin.site.urls), # 連到admin後台
    path("article/", include("article.urls")), # 連去article app中
]

# 在article app下建立urls.py
from django.urls import path
from .views import tag_view # 這邊等我們等一下去view建立視圖函式

urlpatterns = [
    path("tag/", tag_view),
]

  1. 去view.py中配置我們的視圖
from django.shortcuts import render
from .models import Tag

def tag_view(request):
    tags = Tag.objects.all() # 取出所有的tag
    return render(request, "tag.html", {"tags": tags}) # 用字典的形式傳送資料到template
  1. templates下建立tag.html
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
</head>
<body>
	<section class="tag">
		<h1>I am tag list</h1>
		<ul>
			{% for tag in tags %} # 將tags遍歷出來
				<li>{{ tag.name }}</li> # {{}}內可以放變數
			{% endfor %} # 記得一定要補上endfor,if的話就是endif
		</ul>
	</section>
</body>
</html>
  1. 最後去瀏覽器看看~
    https://ithelp.ithome.com.tw/upload/images/20240915/20161866vSgOvhjn97.png

可以看到我們的資料成功顯示在頁面上啦~

今日總結

  1. 我們先透過poetry架設虛擬環境,並且安裝需要的套件
  2. 建立第一個Django專案,並且簡單介紹基本配置
  3. 連結資料庫,並且透過指令將django model上的配置遷移過去
  4. 配置路由、視圖與模板,最終呈現資料庫中的資料

明天會更深入的了解Django的MTV中應該要做什麼配置

  • Model除了建立欄位之外,我們還能做什麼配置嗎?
  • Url中還有什麼細節要注意呢?
  • View中的ORM語法有哪些?
  • Template的DTL還有其他語法嗎?

這些都在明天揭曉~

參考資料

https://vocus.cc/article/64fec089fd897800018b21c1
https://www.cnblogs.com/doublexi/p/15783355.html
https://www.djangoproject.com/download/
https://www.geeksforgeeks.org/custom-django-management-commands/


上一篇
Django in 2024: Django架構深度解析
下一篇
Django in 2024: 淺嚐Model, Url與Template
系列文
Django 2024: 從入門到SaaS實戰31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言