時間:2023-05-29 01:36:01 | 來源:網(wǎng)站運營
時間:2023-05-29 01:36:01 來源:網(wǎng)站運營
Django 3網(wǎng)頁開發(fā)指南第4版 第1章 Django 3.0入門:本文完整目錄請見 Django 3網(wǎng)頁開發(fā)指南 - 第4版$ sudo pip3 install --upgrade pip setuptools wheel
虛擬環(huán)境從Python 3.3開始就已進行內(nèi)置了。$ cd ~/projects $ mkdir myproject_website 、 $ cd myproject_website $ python3 -m venv env
$ source env/bin/activate
$ . env/bin/activate
(env)$
(env)$ deactivate
(env)$ pip install "Django~=3.0.0"
(env)$ django-admin.py startproject myproject所執(zhí)行命令會創(chuàng)建一個名為myproject的目錄,其中存放項目文件。目錄中包含一個名稱同樣為myproject的Python模塊。為避免混淆、保持方便,我們將頂級目錄重命名為django-myproject。這個目錄會進行版本控制,其中應(yīng)包含.git或相應(yīng)的子目錄。
myproject_website├── commands/├── db_backups/├── mockups/├── src/│ └── django-myproject/│ ├── externals/│ │ ├── apps/│ │ │ └── README.md│ │ └── libs/│ │ └── README.md│ ├── locale/│ ├── media/│ ├── myproject/│ │ ├── apps/│ │ │ ├── core/│ │ │ │ ├── __init__.py│ │ │ │ └── versioning.py│ │ │ └── __init__.py│ │ ├── settings/│ │ │ ├── __init__.py│ │ │ ├── _base.py│ │ │ ├── dev.py│ │ │ ├── production.py│ │ │ ├── sample_secrets.json│ │ │ ├── secrets.json│ │ │ ├── staging.py│ │ │ └── test.py│ │ ├── site_static/│ │ │ └── site/│ │ │ ├── css/│ │ │ │ └── style.css│ │ │ ├── img/│ │ │ │ ├── favicon-16x16.png│ │ │ │ ├── favicon-32x32.png│ │ │ │ └── favicon.ico│ │ │ ├── js/│ │ │ │ └── main.js│ │ │ └── scss/│ │ │ └── style.scss│ │ ├── templates/│ │ │ ├── base.html│ │ │ └── index.html│ │ ├── __init__.py│ │ ├── urls.py│ │ └── wsgi.py│ ├── requirements/│ │ ├── _base.txt│ │ ├── dev.txt│ │ ├── production.txt│ │ ├── staging.txt│ │ └── test.txt│ ├── static/│ ├── LICENSE│ └── manage.py*└── venv/
# requirements/_base.txt Django~=3.0.4 djangorestframework -e git://github.com/omab/python-social-auth.git@6b1e301c79#egg=python-social-auth
# requirements/production.txt -r _base.txt
# requirements/dev.txt -r _base.txt coverage django-debug-toolbar selenium
(env)$ pip install -r requirements/dev.txt
(env)$ pip freeze > requirements/_base.txt
(env)$ pip freeze > requirements.txt
要在新的虛擬環(huán)境中安裝這些模塊,僅需使用如下命令:(env)$ pip install -r requirements.txt
如果需要通過其它版本控制系統(tǒng)或本地路徑安裝Python庫,可以通過官方文檔學(xué)習(xí)pip的更多用法。BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))修改后長下面這樣:BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
# myproject/settings/production.py from ._base import *
# myproject/settings/dev.py from ._base import * EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings.production')
??對于每種環(huán)境,推薦在PyCharm的設(shè)置、env/bin/activate腳本或.bash_profile中單獨設(shè)置DJANGO_SETTINGS_MODULE環(huán)境變量
# settings/_base.pyimport osBASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))# ... TEMPLATES = [{# ... DIRS: [ os.path.join(BASE_DIR, 'myproject', 'templates'), ],# ... }]# ... LOCALE_PATHS = [ os.path.join(BASE_DIR, 'locale'), ]# ... STATICFILES_DIRS = [ os.path.join(BASE_DIR, 'myproject', 'site_static'), ]STATIC_ROOT = os.path.join(BASE_DIR, 'static') MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
# settings/_base.py import os from django.core.exceptions import ImproperlyConfigured def get_secret(setting): """Get the secret variable or return explicit exception.""" try: return os.environ[setting] except KeyError: error_msg = f'Set the {setting} environment variable' # 譯者注:f-string 用法在3.6版本開始引入 raise ImproperlyConfigured(error_msg)
SECRET_KEY = get_secret('DJANGO_SECRET_KEY') DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql_psycopg2', 'NAME': get_secret('DATABASE_NAME'), 'USER': get_secret('DATABASE_USER'), 'PASSWORD': get_secret('DATABASE_PASSWORD'), 'HOST': 'db', 'PORT': '5432', } }
$ export DJANGO_SECRET_KEY="此處修改為50個字符的隨機長字符串"$ export DATABASE_NAME="myproject"$ export DATABASE_USER="myproject"$ export DATABASE_PASSWORD="修改為數(shù)據(jù)庫密碼"
注意對于所有密碼、API密鑰及其它需要在Django配置中使用的敏感信息都應(yīng)使用get_secret() 函數(shù)。# settings/_base.pyimport osimport jsonwith open(os.path.join(os.path.dirname(__file__), 'secrets.json'), 'r') as f: secrets = json.loads(f.read())def get_secret(setting): """Get the secret variable or return explicit exception.""" try: return secrets[setting] except KeyError: error_msg = f'Set the {setting} secret variable' raise ImproperlyConfigured(error_msg)
它會讀取配置目錄中的secrets.json 文件,該文件至少應(yīng)當(dāng)有如下結(jié)構(gòu):{ "DATABASE_NAME": "myproject", "DATABASE_USER": "myproject", "DATABASE_PASSWORD": "修改為數(shù)據(jù)庫密碼", "DJANGO_SECRET_KEY": "此處修改為50個字符的隨機長字符串" }
確保在版本控制中忽略secrets.json文件,但為方便起見,可以創(chuàng)建一個帶有空值的sample_secrets.json 文件并對其進行版本控制:{ "DATABASE_NAME": "", "DATABASE_USER": "", "DATABASE_PASSWORD": "", "DJANGO_SECRET_KEY": "此處修改為50個字符的隨機長字符串" }
externals/ ├── apps │ ├── README.md │ ├── cms │ ├── haystack │ └── storages └── libs ├── README.md ├── boto ├── requests └── twython
# settings/_base.py import os import sys BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) EXTERNAL_BASE = os.path.join(BASE_DIR, "externals") EXTERNAL_LIBS_PATH = os.path.join(EXTERNAL_BASE, "libs") EXTERNAL_APPS_PATH = os.path.join(EXTERNAL_BASE, "apps") sys.path = ["", EXTERNAL_LIBS_PATH, EXTERNAL_APPS_PATH] + sys.path
(env)$ python manage.py shell >>> import sys>>> sys.path
在嘗試導(dǎo)入模塊時,Python在列表中搜索模塊并在查找到時返回每一個結(jié)果。# versioning.py import subprocess from datetime import datetime def get_git_changeset_timestamp(absolute_path): repo_dir = absolute_path git_log = subprocess.Popen( "git log --pretty=format:%ct --quiet -1 HEAD", stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, cwd=repo_dir, universal_newlines=True, ) timestamp = git_log.communicate()[0] try: timestamp = datetime.utcfromtimestamp(int(timestamp)) except ValueError: # Fallback to current timestamp return datetime.now().strftime('%Y%m%d%H%M%S') changeset_timestamp = timestamp.strftime('%Y%m%d%H%M%S') return changeset_timestamp
# settings/_base.py from myproject.apps.core.versioning import get_git_changeset_timestamp # ... timestamp = get_git_changeset_timestamp(BASE_DIR) STATIC_URL = f'/static/{timestamp}/'
# settings/_base.pywith open(os.path.join(BASE_DIR, 'myproject', 'settings', 'last-modified.txt'), 'r') as f: timestamp = f.readline().strip() STATIC_URL = f'/static/{timestamp}/'
可以通過預(yù)提交鉤子(hook)來讓Git倉庫更新last-modified.txt。這一可執(zhí)行bash腳本名稱就為pre-commit并放在django-myproject/.git/hooks/目錄下:# django-myproject/.git/hooks/pre-commit#!/usr/bin/env pythonfrom subprocess import check_output, CalledProcessErrorimport osfrom datetime import datetimedef root(): ''' returns the absolute path of the repository root ''' try: base = check_output(['git', 'rev-parse', '--show-toplevel']) except CalledProcessError: raise IOError('Current working directory is not a git repository') return base.decode('utf-8').strip()def abspath(relpath): '''returns the absolute path for a path given relative to the root of the git repository''' return os.path.join(root(), relpath)def add_to_git(file_path): ''' adds a file to git ''' try: base = check_output(['git', 'add', file_path]) except CalledProcessError: raise IOError('Current working directory is not a git repository') return base.decode('utf-8').strip()def main(): file_path = abspath("myproject/settings/last-modified.txt") with open(file_path, 'w') as f: f.write(datetime.now().strftime("%Y%m%d%H%M%S")) add_to_git(file_path)if __name__ == '__main__': main()
這個腳本會提交到Git倉庫時更新last-modified.txt并將該文件添加到Git索引中。# /etc/mysql/my.cnf[client] default-character-set = utf8[mysql] default-character-set = utf8[mysqld]collation-server = utf8_unicode_ci init-connect = 'SET NAMES utf8' character-set-server = utf8
如果以上有任何版塊不存在,請自行在文件中添加。如果各版塊已經(jīng)存在,將設(shè)置添加到已有的配置中,并使用命令行工具重啟MySQL,如下:$ /etc/init.d/mysql restart
$ createdb --encoding=UTF8 --locale=en_US.UTF-8 --template=template0 myproject
# .gitignore### Python template# Byte-compiled / optimized / DLL files __pycache__/*.py[cod]*$py.class# Installer logspip-log.txt pip-delete-this-directory.txt# Unit test / coverage reports htmlcov/.tox/.nox/.coverage .coverage.* .cache nosetests.xml coverage.xml *.cover .hypothesis/ .pytest_cache/# Translations *.mo*.pot# Django stuff: *.log db.sqlite3# Sphinx documentationdocs/_build/# IPython profile_default/ ipython_config.py# Environmentsenv/# Media and Static directories /media/!/media/.gitkeep/static/ !/static/.gitkeep# Secrets secrets.json
/media/ !/media/.gitkeep
這告訴Git要忽略 /media/目錄但保持使用版本控制追蹤 /media/.gitkeep文件。因為Git版本控制僅追蹤文件而不是目錄,所以我們使用.gitkeep 來確保在每個環(huán)境中都會創(chuàng)建media目錄,但不進行追蹤。alias delpyc='find . -name "*.py[co]" -deletefind . -type d -name "__pycache__" -delete'2. 此時要清理Python編譯后文件,進入項目目錄并在命令行中輸入如下命令: ```(env)$ delpyc
# 系統(tǒng)庫 import os import re from datetime import datetime# 第三方庫import botofrom PIL import Image# Django模塊from django.db import models from django.conf import settingsfrom cms.models import Page# 當(dāng)前應(yīng)用模塊from .models import NewsArticle from . import app_settings
(env)$ cd myproject/apps/(env)$ django-admin.py startapp magazine
創(chuàng)建好magazine應(yīng)用之后,在models.py中添加一個NewsArticle模型、在admin.py中為該模型配置管理界面并在設(shè)置的INSTALLED_APPS中添加myproject.apps.magazine。如何對于這些操作你還不熟悉,請參照Django官方課程進行學(xué)習(xí)。# myproject/apps/magazine/apps.py from django.apps import AppConfig from django.utils.translation import gettext_lazy as _ class MagazineAppConfig(AppConfig): name = "myproject.apps.magazine" verbose_name = _("Magazine") def ready(self): from . import signals
# myproject/apps/magazine/__init__.py default_app_config = "myproject.apps.magazine.apps.MagazineAppConfig"
# myproject/apps/magazine/signals.py from django.db.models.signals import post_save, post_delete from django.dispatch import receiver from django.conf import settings from .models import NewsArticle @receiver(post_save, sender=NewsArticle) def news_save_handler(sender, **kwargs): if settings.DEBUG: print(f"{kwargs['instance']} saved.") @receiver(post_delete, sender=NewsArticle) def news_delete_handler(sender, **kwargs): if settings.DEBUG: print(f"{kwargs['instance']} deleted.")
>>> from django.apps import apps as django_apps>>> magazine_app_config = django_apps.get_app_config("magazine") >>> magazine_app_config<MagazineAppConfig: magazine>>>> magazine_app_config.models_module<module 'magazine.models' from '/path/to/myproject/apps/magazine/models.py'>>>> NewsArticle = django_apps.get_model("magazine", "NewsArticle") >>> NewsArticle<class 'magazine.models.NewsArticle'>
譯者注:以上請在django-myproject目錄下操作并設(shè)置環(huán)境變量export DJANGO_SETTINGS_MODULE='myproject.settings.xxx'# myproject/apps/magazine/app_settings.py from django.conf import settings from django.utils.translation import gettext_lazy as _ # Example: SETTING_1 = getattr(settings, "MAGAZINE_SETTING_1", "default value") MEANING_OF_LIFE = getattr(settings, "MAGAZINE_MEANING_OF_LIFE", 42) ARTICLE_THEME_CHOICES = getattr( settings, "MAGAZINE_ARTICLE_THEME_CHOICES", [ ('futurism', _("Futurism")), ('nostalgia', _("Nostalgia")), ('sustainability', _("Sustainability")), ('wonder', _("Wonder")), ] )
from django.db import modelsfrom django.utils.translation import gettext_lazy as _class NewsArticle(models.Model): created_at = models.DateTimeField(_("Created at"), auto_now_add=True) title = models.CharField(_("Title"), max_length=255) body = models.TextField(_("Body")) theme = models.CharField(_("Theme"), max_length=20) class Meta: verbose_name = _("News Article") verbose_name_plural = _("News Articles") def __str__(self): return self.title3. 然后在admin.py中我們將導(dǎo)入并使用app_settings.py中的設(shè)置,如下:
from django import formsfrom django.contrib import adminfrom .models import NewsArticlefrom .app_settings import ARTICLE_THEME_CHOICESclass NewsArticleModelForm(forms.ModelForm): theme = forms.ChoiceField( label=NewsArticle._meta.get_field("theme").verbose_name, choices=ARTICLE_THEME_CHOICES, required=not NewsArticle._meta.get_field("theme").blank, ) class Meta: fields = "__all__"@admin.register(NewsArticle)class NewsArticleAdmin(admin.ModelAdmin): form = NewsArticleModelForm4. 如果希望重寫給定項目中的ARTICLE_THEME_CHOICES設(shè)置,應(yīng)在項目設(shè)置中添加MAGAZINE_ARTICLE_THEME_CHOICES:
from django.utils.translation import gettext_lazy as _ # ...MAGAZINE_ARTICLE_THEME_CHOICES = [ ('futurism', _("Futurism")), ('nostalgia', _("Nostalgia")), ('sustainability', _("Sustainability")), ('wonder', _("Wonder")), ('positivity', _("Positivity")), ('solutions', _("Solutions")), ('science', _("Science")),]### 實現(xiàn)原理...getattr(object, attribute_name[, default_value]) Python函數(shù)嘗試通過object獲取attribute_name屬性并在未查找到時返回default_value。我們會從Django設(shè)置塊中讀取不同的設(shè)置,在不存在時使用默認值。注意我們也可以在models.py中定義theme字段的選項,但這里在后臺管理代碼中創(chuàng)建了一個自定義的ModelForm并其中設(shè)置了選項。這樣做是避免在每次修改ARTICLE_THEME_CHOICES的時候產(chǎn)生一次新的數(shù)據(jù)庫遷移。### 其它內(nèi)容* *創(chuàng)建應(yīng)用配置*一節(jié)* **第6章 模型管理**## 使用Docker容器處理Django, Gunicorn, Nginx和PostgreSQLDjango項目不僅有Python包的依賴,還對系統(tǒng)有很多要求,如web服務(wù)器、數(shù)據(jù)庫、服務(wù)端緩存和郵件服務(wù)。在開發(fā)Django項目時,需要確保所有環(huán)境和所有開發(fā)者安裝了相同的依賴。一種保持這些依賴同步的方式是使用Docker。通過Docker,可以對每個項目單獨擁有不同版本的數(shù)據(jù)庫、web 或其它服務(wù)。Docker是一種用于創(chuàng)建稱之為容器的帶配置、自定義虛擬機的系統(tǒng)。它允許我們精確地復(fù)制生產(chǎn)環(huán)境的設(shè)置。Docker通過稱為Docker鏡像的東西進行創(chuàng)建。鏡像由如何構(gòu)建容器的層(或指令)組成??梢杂蠵ostgreSQL鏡像、Redis鏡像、Memcached鏡像,以及針對Django項目的自定義鏡像,所有這些鏡像可通過Docker Compose 整合成關(guān)聯(lián)的容器。在本小節(jié)中,我們將使用項目樣板來設(shè)置帶有數(shù)據(jù)庫的Django項目,由Nginx和Gunicorn提供服務(wù)、并通過Docker Compose對它們進行管理。### 準(zhǔn)備工作首先,我們需要安裝Docker引擎,可按照https://www.docker.com/get-started上的教程進行安裝。這通常包含Compose工具,讓我們可以管理需要多個容器的系統(tǒng),對于隔離環(huán)境的Django也非常理想。如果要單獨安裝,可參見https://docs.docker.com/compose/install/中有關(guān)Compose的內(nèi)容。**譯者注:** 考慮到國內(nèi)的網(wǎng)絡(luò)環(huán)境可配置 Docker 倉庫的加速:Preferences>Docker Engine,如添加
"registry-mirrors": [ "http://hub-mirror.c.163.com", ]### 如何實現(xiàn)...我們來共同探討下Django和Docker樣板:1. 將https://github.com/archatas/django_docker中的代碼下載到本地,如~/projects/django_docker 目錄中。 > ??如果你選擇的是其它目錄,如myproject_docker,那么需要進行全局搜索并將django_docker替換為myproject_docker。2. 打開docker-compose.yml文件。需要創(chuàng)建3個容器:nginx, gunicorn和db。不必擔(dān)心它看上去很復(fù)雜,我們將在后面詳細講解:
version: "3.7"services: nginx: image: nginx:latest ports: - "80:80" volumes: - ./config/nginx/conf.d:/etc/nginx/conf.d - static_volume:/home/myproject/static - media_volume:/home/myproject/media depends_on: - gunicorn gunicorn: build: context: . args: PIP_REQUIREMENTS: "${PIP_REQUIREMENTS}" command: bash -c "/home/myproject/env/bin/gunicorn --workers 3 --bind 0.0.0.0:8000 myproject.wsgi:application" depends_on: - db volumes: - static_volume:/home/myproject/static - media_volume:/home/myproject/media expose: - "8000" environment: DJANGO_SETTINGS_MODULE: "${DJANGO_SETTINGS_MODULE}" DJANGO_SECRET_KEY: "${DJANGO_SECRET_KEY}" DATABASE_NAME: "${DATABASE_NAME}" DATABASE_USER: "${DATABASE_USER}" DATABASE_PASSWORD: "${DATABASE_PASSWORD}" EMAIL_HOST: "${EMAIL_HOST}" EMAIL_PORT: "${EMAIL_PORT}" EMAIL_HOST_USER: "${EMAIL_HOST_USER}" EMAIL_HOST_PASSWORD: "${EMAIL_HOST_PASSWORD}" db: image: postgres:latest restart: always environment: POSTGRES_DB: "${DATABASE_NAME}" POSTGRES_USER: "${DATABASE_USER}" POSTGRES_PASSWORD: "${DATABASE_PASSWORD}" ports: - 5432 volumes: - postgres_data:/var/lib/postgresql/data/volumes: postgres_data: static_volume: media_volume:3. 打開并通讀Dockerfile文件。有創(chuàng)建gunicorn容器所需要的一些層(或指令):
# pull official base image FROM python:3.8# accept argumentsARG PIP_REQUIREMENTS=production.txt# set environment variablesENV PYTHONDONTWRITEBYTECODE 1ENV PYTHONUNBUFFERED 1# install dependenciesRUN pip install --upgrade pip setuptools# create user for the Django project RUN useradd -ms /bin/bash myproject# set current userUSER myproject# set work directoryWORKDIR /home/myproject# 添加以下內(nèi)容避免因 Volume 所帶來的 root 權(quán)限問題RUN mkdir static && mkdir media# create and activate virtual environment RUN python3 -m venv env# copy and install pip requirementsCOPY --chown=myproject ./src/myproject/requirements /home/myproject/requirements/# 添加豆瓣源在國內(nèi)加速RUN ./env/bin/pip3 install -i https://pypi.doubanio.com/simple/ -r /home/myproject/requirements/${PIP_REQUIREMENTS}# copy Django project filesCOPY --chown=myproject ./src/myproject /home/myproject/4. 復(fù)制build_dev_example.sh 腳本到build_dev.sh中并編輯其內(nèi)容。有一些要傳遞給docker-compose腳本的環(huán)境變量:
#!/usr/bin/env bash DJANGO_SETTINGS_MODULE=myproject.settings.dev /DJANGO_SECRET_KEY="change-this-to-50-characters-long-random-string" /DATABASE_NAME=myproject /DATABASE_USER=myproject /DATABASE_PASSWORD="change-this-too" /PIP_REQUIREMENTS=dev.txt /docker-compose up --detach --build5. 在命令行工具中,為build_dev.sh添加執(zhí)行權(quán)限并運行它來構(gòu)建容器:
$ chmod +x build_dev.sh $ ./build_dev.sh6. 如果此時訪問http://0.0.0.0/en/,應(yīng)當(dāng)會看到Hello, World!頁面。 在訪問http://0.0.0.0/en/admin/時,會看到如下內(nèi)容:
OperationalError at /en/admin/ FATAL: role "myproject" does not exist這表示你需要在Docker容器中創(chuàng)建數(shù)據(jù)庫用戶及數(shù)據(jù)庫。7. 我們通過SSH連接db容器并在Docker容器中創(chuàng)建數(shù)據(jù)庫用戶、密碼及數(shù)據(jù)庫本身:
$ docker exec -it django_docker_db_1 bash /# su - postgres /$ createuser --createdb --password myproject /$ createdb --username myproject myproject在被詢問時,輸入與build_dev.sh腳本中相同的數(shù)據(jù)庫密碼。(如未出現(xiàn)6中的報錯則無需手動執(zhí)行以上用戶創(chuàng)建) 連續(xù)按兩次Ctrl + D來登出PostgreSQL用戶和Docker容器?,F(xiàn)在訪問http://0.0.0.0/en/admin/的話,會看到如下內(nèi)容: ```ProgrammingError at /en/admin/ relation "django_session" does not exist LINE 1: ...ession_data", "django_session"."expire_date" FROM "django_se...這表示我們需要運行遷移來創(chuàng)建數(shù)據(jù)庫模式。
$ docker exec -it django_docker_gunicorn_1 bash $ source env/bin/activate (env)$ python manage.py migrate (env)$ python manage.py collectstatic (env)$ python manage.py createsuperuser回復(fù)管理命令所詢問的所有問題。按兩次Ctrl + D登出Docker容器。如果現(xiàn)在導(dǎo)航至http:/?/?0.?0.?0.?0/?en/?admin/?,應(yīng)當(dāng)會看到Django后臺管理頁面,在這里可以通過所創(chuàng)建的超級用戶來進行登錄。
django_docker/├── Dockerfile├── LICENSE├── README.md├── build_dev_example.sh├── config│ └── nginx│ └── conf.d│ └── myproject.conf├── docker-compose.yml├── git-hooks│ ├── install_hooks.sh│ └── pre-commit└── src └── myproject ├── locale │ └── de │ └── LC_MESSAGES │ └── django.po ├── manage.py ├── myproject │ ├── __init__.py │ ├── apps │ │ └── __init__.py │ ├── settings │ │ ├── __init__.py │ │ ├── _base.py │ │ ├── dev.py │ │ ├── last-update.txt │ │ ├── production.py │ │ ├── staging.py │ │ └── test.py │ ├── site_static │ │ └── site │ │ ├── css │ │ │ └── style.css │ │ ├── img │ │ │ ├── favicon-16x16.png │ │ │ ├── favicon-32x32.png │ │ │ └── favicon.ico │ │ ├── js │ │ │ └── main.js │ │ └── scss │ │ └── style.scss │ ├── templates │ │ ├── base.html │ │ └── index.html │ ├── urls.py │ └── wsgi.py └── requirements ├── _base.txt ├── dev.txt ├── production.txt ├── staging.txt └── test.txt
Docker相關(guān)的主要配置在docker-compose.yml和Dockerfile中。Docker Compose是對Docker的命令行API進行的封裝。build_dev.sh腳本運行Django項目,Gunicorn WSGI HTTP服務(wù)器的端口號為8000,Nginx的端口號為80(對靜態(tài)和媒體文件提供服務(wù)并將請求代理到Gunicorn),PostgreSQL數(shù)據(jù)庫的端口為5432。#/etc/nginx/conf.d/myproject.confupstream myproject { server django_docker_gunicorn_1:8000;}server { listen 80; location / { proxy_pass http://myproject; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $host; proxy_redirect off; } rewrite "/static//d+/(.*)" /static/$1 last; location /static/ { alias /home/myproject/static/; } location /media/ { alias /home/myproject/media/; } }
在第12章 部署中的在預(yù)發(fā)布環(huán)境中基于Nginx和Gunicorn部署和在生產(chǎn)環(huán)境中基于Nginx和Gunicorn部署小節(jié)中會學(xué)習(xí)更多有關(guān)Nginx和Gunicorn配置的知識。$ docker-compose down $ ./build_dev.sh
如果和所預(yù)期的效果不一致,可以通過docker-compose logs命令來檢查日志:$ docker-compose logs nginx$ docker-compose logs gunicorn $ docker-compose logs db
通過SSH來連接其中的任一容器,可以使用下面的命令:$ docker exec -it django_docker_gunicorn_1 bash $ docker exec -it django_docker_nginx_1 bash$ docker exec -it django_docker_db_1 bash
可以使用docker cp命令將Docker容器的數(shù)據(jù)卷進行拷入和拷出文件、目錄的處理:$ docker cp ~/avatar.png django_docker_gunicorn_1:/home/myproject/media/ $ docker cp django_docker_gunicorn_1:/home/myproject/media ~/Desktop/
如果希望更好地掌握Docker和Docker Compose,可以學(xué)習(xí)官方文檔的內(nèi)容,尤其是https://docs.docker.com/compose/部分。關(guān)鍵詞:入門,發(fā)指
微信公眾號
版權(quán)所有? 億企邦 1997-2025 保留一切法律許可權(quán)利。