在我們建構第一個Django專案之前,必須要先聲明虛擬環境的重要性
以前還沒什麼觀念的時候,看到一些影片的安裝教學都直接安裝軟體,安裝的方式可能也有百百種
等到之後想移除時,可能在多個路徑下都有不同版本的相同軟體
在使用IDE引用來源時可能也是胡亂使用,這時候就很想要重頭開始一個乾淨的環境
也體現出使用虛擬環境的重要性
python有以下幾種套件可以幫忙建立虛擬環境
python -m venv <環境名稱>
**命令可以輕鬆建立虛擬環境pip install virtualenv
安裝,然後使用virtualenv <環境名稱>
**來創建虛擬環境。它支持Python 2和Python 3,並且能夠創建不同Python版本的虛擬環境pip
和virtualenv
的功能,提供了更高層次的包管理和虛擬環境管理。使用pipenv install
**可以創建虛擬環境並安裝依賴。適合需要管理多個依賴的項目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 *
那我們現在就來進到我們第一個專案~
專案程式碼放在: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專案了!
我們先在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的基本架構
使用者根據特定url
發請請求→url
找到相對應的View
→View
依據特定邏輯處理Model
中的資料→View
拿到最終數據後渲染到Templates
上
這邊我就先不提及Middleware的部分,之後如果有需求的時候再來做介紹
那我們就來透過實作來完成這樣的流程吧
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 # 配置視圖
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
# my apps
"article",
]
在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
模塊下不同的類別,設定欄位的類型之外,也進行其他的配置
例如:
primary_key=True
表示這是主鍵,通常會被映射為資料庫中的 INTEGER 類型,max_length=120
限制最大長度為120個字符,被映射為 VARCHAR類型auto_now_add=True
使其在創建時自動設置為當前時間,而auto_now=True
使其在每次保存時自動更新為當前時間。被映射為 DATETIME 類型其他更詳細的配置可以看官方文檔:
https://docs.djangoproject.com/en/4.2/ref/models/fields/#field-types
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
可以看到表格們確實都出現了
python3 manage.py shell
# 進入shell模式,可以輸入簡單指令來操作
>>> from article.models import Tag
>>> tag = Tag(name="Django")
>>> tag.save()
# 先建立第一筆資料
>>> exit() # 退出shell模式
# 根目錄下的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),
]
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
<!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>
可以看到我們的資料成功顯示在頁面上啦~
明天會更深入的了解Django的MTV中應該要做什麼配置
這些都在明天揭曉~
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/