[Django + GitHub Actions] 使用pdoc将文档上传到GitHub Pages!
总结
使用pdoc可以将用Python编写的源代码进行文档化。
此外,还可以使用GitHub Actions和GitHub Pages将文档作为网站发布到存储库中。
这次将从使用pdoc将Django项目内的测试代码输出为单元测试规范书,到使用GitHub Actions发布规范书的方法进行解释。
虽然量比较大且内容稍微有难度,但让我们一起努力吧。
首先
-
- 今回のプロジェクトではPoetryとPostgresを使用
-
- Pythonのバージョンは3.11を使用
-
- テストフレームワークはPytestを使用
-
- テストコードを作成済みおよびdocstringを記載済み
- Djangoのプロジェクトを作成済み
文件架构
文件结构如下所示:
本次将在application文件夹中存储Django项目。
Django项目的名称为project,应用程序名称为application。
tree
・
├── .github
│ └── workflows
│ └── docs.yml
├── .gitignore
└── application
├── application
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ ├── models.py
│ ├── tests
│ ├── urls.py
│ └── views.py
├── manage.py
├── poetry.lock
├── project
│ ├── __init__.py
│ ├── asgi.py
│ ├── settings.py
│ ├── urls
│ └── wsgi.py
└── pyproject.toml
这个文件我们将制作
本次要制作的文件如下所示。
-
- application/pyproject.toml
-
- application/application/__init__.py
-
- .gitignore
- .github/workflow/docs.yml
应用程序/ pyproject.toml
创建 pyproject.toml 文件
这次
-
- Python
-
- Django
-
- Postgres
-
- Pytest
- Pdoc
安装包。
[tool.poetry]
name = "api"
version = "0.1.0"
description = "api"
authors = ["shun198"]
readme = "README.md"
[tool.poetry.dependencies]
python = "^3.11"
Django = "^4.1.2"
psycopg2 = "^2.9.6"
[tool.poetry.group.dev.dependencies]
pytest = "^7.1.3"
pytest-django = "^4.5.2"
pdoc = "^13.0.0"
如果您想详细了解Poetry的使用方法,请参考以下文章。
为什么无法在Django上运行pdoc?
当您需要生成Pdoc文档时,请执行以下命令。
poetry run pdoc -o docs application/tests
我认为,当你运行此命令时,原本应该将位于application/tests文件夹内的所有源代码以HTML格式输出到docs文件夹,但是估计会遇到以下错误输出。
File "/root/.cache/pypoetry/virtualenvs/api-MATOk_fk-py3.11/lib/python3.11/site-packages/django/apps/registry.py", line 260, in get_containing_app_config
self.check_apps_ready()
File "/root/.cache/pypoetry/virtualenvs/api-MATOk_fk-py3.11/lib/python3.11/site-packages/django/apps/registry.py", line 138, in check_apps_ready
raise AppRegistryNotReady("Apps aren't loaded yet.")
django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet.
只需一个方式,原文是這樣的:当执行pdoc时,在内部启动Django并输出结果。但是,这次在输出tests文件夹内的源代码时并没有启动Django。
Apps aren't loaded yet
可能是表示在屏幕上
对于想更了解尚未加载的应用的人士
运行Django时,会执行asgi.py(或wsgi.py)中的内容。
"""
ASGI config for project project.
It exposes the ASGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/4.1/howto/deployment/asgi/
"""
import os
from django.core.asgi import get_asgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.settings")
application = get_asgi_application()
之后将调用get_asgi_application()
import django
from django.core.handlers.asgi import ASGIHandler
def get_asgi_application():
"""
The public interface to Django's ASGI support. Return an ASGI 3 callable.
Avoids making django.core.handlers.ASGIHandler a public API, in case the
internal implementation changes or moves in the future.
"""
django.setup(set_prefix=False)
return ASGIHandler()
setup() function is called in Django.
-
- apps
- settings
只有当导入了Django所需的包时,才会导入setup()方法。如果没有setup()方法,将无法导入apps或settings。
Apps aren't loaded yet
出现这个错误是因为这个原因。
from django.utils.version import get_version
VERSION = (4, 0, 6, "final", 0)
__version__ = get_version(VERSION)
def setup(set_prefix=True):
"""
Configure the settings (this happens as a side effect of accessing the
first setting), configure logging and populate the app registry.
Set the thread-local urlresolvers script prefix if `set_prefix` is True.
"""
from django.apps import apps
from django.conf import settings
from django.urls import set_script_prefix
from django.utils.log import configure_logging
configure_logging(settings.LOGGING_CONFIG, settings.LOGGING)
if set_prefix:
set_script_prefix(
"/" if settings.FORCE_SCRIPT_NAME is None else settings.FORCE_SCRIPT_NAME
)
apps.populate(settings.INSTALLED_APPS)
换句话说,当执行pdoc时,必须先执行setup方法。
处理方法
在执行django.setup()之前,可以在想要输出的文件夹(例如application/tests)的__init__.py文件中添加django.setup()。由于django.setup()也会在项目内执行,因此如果尝试启动Django,可能会发生与django.setup()冲突无法启动的情况。因此,我们可以通过判断是否存在名为CI_MAKING_DOCS的环境变量来避免冲突。
import os
if os.environ.get("CI_MAKING_DOCS") is not None:
"""テスト仕様書をpdocで出力するためにdjango.setupを実施する"""
import django
django.setup()
执行pdoc的命令
通过将值传递给名为CI_MAKING_DOCS的环境变量,在Poetry运行时,将执行django.setup()。
CI_MAKING_DOCS=1 poetry run pdoc -o docs application/tests/
如果您使用docker-compose,请执行以下命令。
docker-compose exec app env CI_MAKING_DOCS=1 poetry run pdoc -o docs application/tests/
如果创建了一个名为“docs”的文件夹,那就是成功了。

.gitignore 文件
将docs文件夹添加到.gitignore中,因为不需要对其进行版本控制。
docs/
GitHub Pages的设置
在创建工作流之前,我们需要进行GitHub Pages的设置。在打开”设置”页面后,将”源”设为”GitHub Actions”。

创建工作流程 (Create a workflow)
接下来,我将解释如何创建一个工作流,将通过pdoc导出的文档上传到GitHub Pages。这里的工作流是根据pdoc官方提供的工作流进行创建的,但由于使用了Poetry等稍有不同之处,我将进行解释说明。
name: GitHub Pages
on:
push:
branches:
- develop
# security: restrict permissions for CI jobs.
permissions:
contents: read
env:
SECRET_KEY: test
DJANGO_SETTINGS_MODULE: project.settings
ALLOWED_HOSTS: 127.0.0.1
POSTGRES_NAME: test
POSTGRES_USER: test
POSTGRES_PASSWORD: test
POSTGRES_HOST: 127.0.0.1
POSTGRES_PORT: 5432
CI_MAKING_DOCS: 1
jobs:
# Build the documentation and upload the static HTML files as an artifact.
build:
runs-on: ubuntu-latest
defaults:
run:
working-directory: application
steps:
- name: Chekcout code
uses: actions/checkout@v3
- name: Install poetry
run: pipx install poetry
- name: Use cache dependencies
uses: actions/setup-python@v4
with:
python-version: '3.11'
cache: 'poetry'
- name: Install Packages
run: poetry install
- name: Create documentation
run: poetry run pdoc -o docs application/tests/
- name: Upload Documents
uses: actions/upload-pages-artifact@v1
with:
# 絶対パスを指定
path: application/docs/
# Deploy the artifact to GitHub pages.
# This is a separate job so that only actions/deploy-pages has the necessary permissions.
deploy:
needs: build
runs-on: ubuntu-latest
permissions:
pages: write
id-token: write
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- id: deployment
uses: actions/deploy-pages@v2
在执行时指定分支
我們將確保在本次開發分支和功能分支合併或推送到develop分支時,工作流程將被執行。
name: GitHub Pages
on:
push:
branches:
- develop
环境变量
由于这次我正在使用Postgres,所以在使用数据库时,请指定数据库的环境变量。
还请指定启动Django所需的环境变量,包括SECRET_KEY。
在使用pdoc时,也需要提供CI_MAKING_DOCS环境变量。
env:
SECRET_KEY: test
DJANGO_SETTINGS_MODULE: project.settings
ALLOWED_HOSTS: 127.0.0.1
POSTGRES_NAME: test
POSTGRES_USER: test
POSTGRES_PASSWORD: test
POSTGRES_HOST: 127.0.0.1
POSTGRES_PORT: 5432
CI_MAKING_DOCS: 1
使用诗歌实施的PDOC执行
如果你想要了解有关Poetry缓存的使用方法以及其他详细信息,请参考以下文章,因为这次我们使用了Poetry来实现安装的加速,并利用Poetry的设置和缓存来加快第二次及以后的安装速度。
此外,在使用actions/upload-pages-artifact@v1时,请将docs文件夹的路径设置为绝对路径。通过使用官方提供的这个action,docs文件夹中的文件将被保存为artifact在GitHub Actions内,并且可以上传到GitHub Pages。
jobs:
# Build the documentation and upload the static HTML files as an artifact.
build:
runs-on: ubuntu-latest
defaults:
run:
working-directory: application
steps:
- name: Chekcout code
uses: actions/checkout@v3
- name: Install poetry
run: pipx install poetry
- name: Use cache dependencies
uses: actions/setup-python@v4
with:
python-version: '3.11'
cache: 'poetry'
- name: Install Packages
run: poetry install
- name: Create documentation
run: poetry run pdoc -o docs application/tests/
- name: Upload Documents
uses: actions/upload-pages-artifact@v1
with:
# 絶対パスを指定
path: application/docs/
让我们来执行工作流程吧!
如果直接将更改提交到develop分支,或者将PR合并到develop分支,工作流程将被执行。
如果能够创建名为GitHub Pages的构件并成功地在链接上进行转移并查看,则表示成功。


总结
由于找不到使用Django和pdoc将文档上传到GitHub Pages的文章,而且还遇到了从未见过的错误消息,起初不知道该怎么办,所以我写了这篇文章。如果你理解了原理,就能轻松地创建,希望你能尝试一下。
请提供更多上下文。