django-distill
は Web サイトが開設されました。詳細については、以下をご覧ください。
django-distill
、Django の最小構成の静的サイト ジェネレーターおよびパブリッシャーです。ほとんどの Django バージョンがサポートされていますが、Django 3.x リリースを含む最新バージョンをお勧めします。 1.7 リリースのdjango-distill
Python 3 のみをサポートします。Python 2 のサポートは廃止されました。 Python 2 のサポートが必要な場合は、requirements.txt または Pipfile でdjango-distill
バージョン 1.6 に固定してください。 Python 3.6 以降をお勧めします。
django-distill
完全に機能する静的サイトをエクスポートできるように既存の Django サイトを拡張します。これは、主に静的なフロントエンドを備えているものの、コンテンツの管理に CMS を使用したいブログなどのサイトに適しています。
django-distill
簡単に記述できる反復可能な関数を使用して Django プロジェクト内の URL を反復処理し、静的 HTML として保存したいページのパラメーターを生成します。これらの静的ファイルは、Amazon S3、Googe Cloud Files、Microsoft Azure Storage などのバケット スタイルのリモート コンテナに自動的にアップロードすることも、完全に動作するプロジェクトのローカル静的バージョンとしてローカル ディレクトリに書き込むこともできます。サイト生成または蒸留プロセスは、CI/CD ワークフローに簡単に統合して、コミット時に静的サイトを自動デプロイできます。 django-distill
Django プロジェクトを「Jamstack」スタイルのサイト アーキテクチャと互換性のあるものにするための Django の拡張機能として定義できます。
django-distill
カスタム レンダラーやその他のより冗長なコードを作成する必要がなく、既存の Django フレームワークに直接プラグインされます。また、 django-distill
既存の動的サイトと統合し、サイト全体ではなくページの小さなサブセクションに対してのみ静的ページを生成することもできます。
CDN 上の静的ファイルの場合、次の「キャッシュ バスター」ライブラリを使用して、変更をプッシュするときに静的メディアを高速に更新できます。
? meeb/django-キャッシュキラー
静的ブログを作成し、Netlify での継続的デプロイメントを介してdjango-distill
とdjango-cachekiller
を使用する完全なサンプル サイトがここにあります。
? meeb/django-distill-example
pip からインストールします。
$ pip install django-distill
django_distill
settings.py
のINSTALLED_APPS
に追加します。
INSTALLED_APPS = [
# ... other apps here ...
'django_distill' ,
]
それでおしまい。
django-distill
静的ページを生成するため、 HTTP 200
ステータス コードを返すGET
リクエストを許可するビューのみがサポートされます。
/blog?post_id=123&title=abc
などのクエリ文字列パラメータではなく、 /blog/123-abc
などの URI パラメータを使用していることを前提としています。クエリ文字列パラメータは、明らかな理由により、静的ページ生成には意味がありません。
画像やスタイル シートなどの静的メディア ファイルは、 STATIC_ROOT
で定義された静的メディア ディレクトリからコピーされます。これは、静的メディアに変更を加えた場合は、 ./manage.py distill-local
実行する前に./manage.py collectstatic
を実行する必要があることを意味します。 django-distill
仕様上、このリクエストをチェーンしませんが、 --collectstatic
引数を使用して有効にすることができます。
既存の Django プロジェクトがあると仮定して、 urls.py
編集して、Django の標準path
関数を置き換え、新しいキーワード引数distill_func
およびdistill_file
サポートするdistill_path
関数を含めます。
distill_func
引数には、反復可能またはNone
返す関数または呼び出し可能クラスを指定する必要があります。
distill_file
引数は完全にオプションであり、URL 正規表現の逆から生成される URL をオーバーライドできます。これにより/example
のような URL の名前をexample.html
のような他の名前に変更できます。 v0.8 以降、スラッシュ/
で終わる URI は、 /index.html
で終わるように自動的に変更されます。 distill_file
でフォーマット文字列パラメータを使用してファイル名をカスタマイズできます。URL の引数値は、たとえば、位置引数の場合は{}
、名前付き引数の場合は{param_name}
に置き換えられます。
理論上のブログ アプリの蒸留セットアップの例は次のようになります。
# Replaces the standard django.conf.path, identical syntax
from django_distill import distill_path
# Views and models from a theoretical blogging app
from blog . views import PostIndex , PostView , PostYear
from blog . models import Post
def get_index ():
# The index URI path, '', contains no parameters, named or otherwise.
# You can simply just return nothing here.
return None
def get_all_blogposts ():
# This function needs to return an iterable of dictionaries. Dictionaries
# are required as the URL this distill function is for has named parameters.
# You can just export a small subset of values here if you wish to
# limit what pages will be generated.
for post in Post . objects . all ():
yield { 'blog_id' : post . id , 'blog_title' : post . title }
def get_years ():
# You can also just return an iterable containing static strings if the
# URL only has one argument and you are using positional URL parameters:
return ( 2014 , 2015 )
# This is really just shorthand for ((2014,), (2015,))
urlpatterns = (
# e.g. / the blog index
distill_path ( '' ,
PostIndex . as_view (),
name = 'blog-index' ,
# Note that for paths which have no paramters
# distill_func is optional
distill_func = get_index ,
# '' is not a valid file name! override it to index.html
distill_file = 'index.html' ),
# e.g. /post/123-some-post-title using named parameters
distill_path ( 'post/<int:blog_id>-<slug:blog_title>.html' ,
PostView . as_view (),
name = 'blog-post' ,
distill_func = get_all_blogposts ),
# e.g. /posts-by-year/2015 using positional parameters
# url ends in / so file path will have /index.html appended
distill_path ( 'posts-by-year/<int:year>/' ,
PostYear . as_view (),
name = 'blog-year' ,
distill_func = get_years ),
)
サイトは上記の変更を行っても同様に機能します。内部的にはdistill_func
パラメータとdistill_file
パラメータが削除され、通常の処理のために URL が Django に戻されます。これはアプリケーションの起動時に 1 回だけ発生するため、実行時のパフォーマンスには影響しません。
パスに/
や/some-static-url
などの URI パラメーターがない場合は、 distill_func
パラメーターを指定する必要はありません。パラメータのないパスの場合、 distill_func
常にNone
返します。これはdistill_func
のデフォルトの動作として設定されています。
デフォルトのdjango.urls.re_path
関数を置き換えるdistill_re_path
関数も使用できます。その使用法は上記と同じです。
from django_distill import distill_re_path
urlpatterns = (
distill_re_path ( r'some/regex'
SomeOtherView . as_view (),
name = 'url-other-view' ,
distill_func = some_other_func ),
)
1.x シリーズの古いバージョンの Django を使用している場合は、 django.conf.urls.url
またはdjango.urls.url
関数を置き換えるdistill_url
関数を代わりに使用できます。その使用法は上記と同じです。
from django_distill import distill_url
urlpatterns = (
distill_url ( r'some/regex'
SomeView . as_view (),
name = 'url-view' ,
distill_func = some_func ),
)
distill_file
で標準の Python 文字列フォーマットを使用して、必要に応じてファイルの出力ファイル パスを変更することもできます。これは Django で使用される URL を更新しないことに注意してください。そのため、これを使用する場合は、 path
パターンがdistill_file
パターンと一致することを確認してください。そうしないと、リンクが Django で機能しない可能性があります。例:
# Override file path with parameters. Values are taken from the URL pattern
urlpatterns = (
distill_path ( 'post/<int:blog_id>-<slug:blog_title>.html' ,
PostView . as_view (),
name = 'blog-post' ,
distill_func = get_all_blogposts ,
distill_file = "post/{blog_id}-{blog_title}.html"
)
django-distill
によって静的ページにレンダリングされるすべてのビューは、HTTP 200 ステータス コードを返す必要があります。何らかの理由で、HTTP 200 ステータス コードを返さないビューをレンダリングする必要がある場合、たとえば、HTTP 404 ステータス コードを (正しく) 返すビューを持つ 404 ページを静的に生成したい場合は、 distill_status_codes
を使用できます。ビューへのオプションの引数。例えば:
from django_distill import distill_url
urlpatterns = (
distill_url ( r'some/regex'
SomeView . as_view (),
name = 'url-view' ,
distill_status_codes = ( 200 , 404 ),
distill_func = some_func ),
)
オプションのdistill_status_codes
引数は、エラーを発生させずにビューが返すことを許可されるステータス コードのタプルを整数として受け入れます。デフォルトでは、これは(200,)
に設定されていますが、サイトで必要に応じてオーバーライドできます。
django-distill
インストールされている Django のバージョンがサポートするものをすべてミラーリングするため、将来、Django 2.x 自体がdjango.conf.urls.url
とdjango.urls.url
関数を廃止すると、ある時点でdistill_url
関数は動作しなくなります。 distill_re_path
ドロップイン置換として使用できます。現在新しいサイトを構築している場合は、 distill_path
またはdistill_re_path
を使用することをお勧めします。
国際化は URL に対してのみサポートされており、ページ コンテンツは動的に翻訳できません。デフォルトでは、サイトはsettings.py
のLANGUAGE_CODE
値を使用して生成されます。 settings.USE_I18N
をTrue
に設定し、 settings.DISTILL_LANGUAGES
値に他の言語コードを設定し、 i18n_patterns(...)
で URL を登録すると、サイトは複数の言語で生成されます。これは、 django-distill
追加する前に、多言語サイトが期待どおりに機能することを前提としています。
たとえば、 settings.LANGUAGE_CODE = 'en'
と設定すると、サイトは 1 つの言語で生成されます。
代わりにsettings.py
に次のようなものがある場合:
USE_I18N = True
DISTILL_LANGUAGES = [
'en' ,
'fr' ,
'de' ,
]
次のようにurls.py
でi18n_patterns
も使用しながら:
from django . conf . urls . i18n import i18n_patterns
from django_distill import distill_path
urlpatterns = i18n_patterns (
distill_path ( 'some-file.html' ,
SomeView . as_view (),
name = 'i18n-view' ,
distill_func = some_func
)
)
その後、ビューは/en/some-file.html
、 /fr/some-file.html
、および/de/some-file.html
として生成されます。これらの URL はサイトですでに機能する (そして翻訳される) はずです。 django-distill
魔法のような翻訳は行わず、言語コードのプレフィックスを付けて URL を呼び出すだけです。
注デフォルトで推奨される方法は、 settings.DISTILL_LANGUAGES
使用して物事を分離することですがdjango-distill
言語コードのsettings.LANGUAGES
もチェックします。
django-distill
に登録されているすべての URL のリストを生成する必要がある場合があります。たとえば、静的に生成された数百ページのブログがあり、すべての URL をsitemap.xml
またはその他の同様のすべての URL リストに簡単にリストしたいとします。サイトマップ ビューをdistill_path
でラップし、 urls.py
からビューのdistill_func
をインポートしてこれらをすべて手動で生成することで、すべての URL 生成ロジックを複製することもできますが、これは非常に面倒であることを考慮して、すべての URL を生成するための組み込みヘルパーがあります。抽出される URL。
from django_distill import distilled_urls
for uri , file_name in distilled_urls ():
# URI is the generated, complete URI for the page
print ( uri ) # for example: /blog/my-post-123/
# file_name is the actual file name on disk, this may be None or a string
print ( file_name ) # for example: /blog/my-post-123/index.html
distilled_urls()
は、 urls.py
内のすべての URL がdistill_path(...)
でロードされた後にのみ URL を返すことに注意してください。
distill-local
コマンド静的に生成したい URL をラップしたら、以下を使用して完全に機能する静的サイトを生成できます。
$ ./manage.py distill-local [optional /path/to/export/directory]
内部的には、これは単純にdistill_url
に登録されたすべての URL を反復し、Django テスト フレームワークの一部を使用してリクエストを偽装するページを生成します。サイト ページがレンダリングされると、 STATIC_ROOT
のファイルがコピーされます。ターゲット ディレクトリ内の同じ名前の既存のファイルは置き換えられ、孤立したファイルは削除されます。
distill-local
次のオプションの引数をサポートしています。
--collectstatic
: レンダリング前にサイトでcollectstatic
自動的に実行します。これは、追加のコマンドの入力を省略するための単なるショートカットです。
--quiet
: 確認の質問以外のすべての出力を無効にします。
--force
: すべての確認の質問に対して「はい」と仮定します。
--exclude-staticfiles
: 静的ファイルはまったくコピーせず、Django ビューからの出力のみをレンダリングします。
--parallel-render [number of threads]
: 複数のスレッドでファイルを並行してレンダリングします。これにより、レンダリングが高速化されます。デフォルトは1
スレッドです。
--generate-redirects
: django.contrib.redirects
アプリに保存されている静的リダイレクトの生成を試みます。 /old/
から/new/
へのリダイレクトがある場合、このフラグを使用すると、静的 HTML <meta http-equiv="refresh" content="...">
スタイルのリダイレクトが/old/index.html
から/new/
に作成されます。 /new/
。
注:ビューのいずれかに Python エラーが含まれている場合、レンダリングは失敗し、スタック トレースがターミナルに出力され、レンダリング コマンドはステータス コード 1 で終了します。
distill-publish
コマンド$ ./manage.py distill-publish [optional destination here]
少なくとも 1 つの公開先を設定している場合 (以下を参照)、 distill-publish
コマンドを使用してサイトをリモートの場所に公開できます。
これにより完全な同期が実行され、生成された静的サイトに存在しないリモート ファイルが削除され、新しいファイルまたは変更されたファイルがアップロードされます。サイトは公開時に最初にローカルの一時ディレクトリに構築されますが、サイトが公開されると削除されます。各ファイルは、 PUBLIC_URL
経由でリクエストすることにより、正しく公開されたかどうかチェックされます。
distill-publish
次のオプションの引数をサポートしています。
--collectstatic
: レンダリング前にサイトでcollectstatic
自動的に実行します。これは、追加のコマンドの入力を省略するための単なるショートカットです。
--quiet
: 確認の質問以外のすべての出力を無効にします。
--force
: すべての確認の質問に対して「はい」と仮定します。
--exclude-staticfiles
: 静的ファイルはまったくコピーせず、Django ビューからの出力のみをレンダリングします。
--skip-verify
: ファイルがサーバーに正しくアップロードされているかどうかをテストしません。
--ignore-remote-content
: リモート ファイルのリストをフェッチしません。これは、すべてのファイルがアップロードされ、既存のリモート ファイルが削除されないことを意味します。これは、リモート サーバー上に多数のファイルがあり、それらのほとんどを更新する必要があり、古いファイルがサーバー上に残っていても気にしない場合に便利です。
--parallel-publish [number of threads]
: 複数のスレッドで並行してファイルをパブリッシュします。これにより、パブリッシュを高速化できます。デフォルトは1
スレッドです。
--parallel-render [number of threads]
: 複数のスレッドでファイルを並行してレンダリングします。これにより、レンダリングが高速化されます。デフォルトは1
スレッドです。
--generate-redirects
: django.contrib.redirects
アプリに保存されている静的リダイレクトの生成を試みます。 /old/
から/new/
へのリダイレクトがある場合、このフラグを使用すると、静的 HTML <meta http-equiv="refresh" content="...">
スタイルのリダイレクトが/old/index.html
から/new/
に作成されます。 /new/
。
これは、 --force
および--quiet
使用すると、出力ディレクトリからサイト エクスポートの一部ではないすべてのファイルが確認なしで削除されることを意味することに注意してください。
注:ビューのいずれかに Python エラーが含まれている場合、レンダリングは失敗し、スタック トレースがターミナルに出力され、レンダリング コマンドはステータス コード 1 で終了します。
distill-test-publish
コマンド$ ./manage.py distill-test-publish [optional destination here]
これにより、公開ターゲットに接続し、認証され、ランダムな名前のファイルがアップロードされ、そのファイルがPUBLIC_URL
に存在することを確認してから、再度削除されます。これを使用して、公開設定が正しいことを確認します。
distill-test-publish
は引数がありません。
次のオプションのsettings.py
変数を設定できます。
DISTILL_DIR : 文字列、エクスポート先のデフォルトのディレクトリ:
DISTILL_DIR = '/path/to/export/directory'
DISTILL_PUBLISH : 辞書は、Django のsettings.DATABASES
と同様に、 default
サポートします。
DISTILL_PUBLISH = {
'default' : {
... options ...
},
'some-other-target' : {
... options ...
},
}
DISTILL_SKIP_ADMIN_DIRS : ブール値、デフォルトはTrue
DISTILL_SKIP_ADMIN_DIRS = True
django-distill
でstatic/admin
ディレクトリ内の静的ファイルもコピーする場合は、 DISTILL_SKIP_ADMIN_DIRS
をFalse
に設定します。通常、これらは静的に生成されたサイトには必要ありません。デフォルトの動作では、静的管理ファイルはスキップされます。
DISTILL_SKIP_STATICFILES_DIRS : リスト、デフォルトは[]
DISTILL_SKIP_STATICFILES_DIRS = [ 'some_dir' ]
DISTILL_SKIP_STATICFILES_DIRS
、定義したstatic/
ディレクトリ内のディレクトリをdjango-distill
に無視させるディレクトリ名のリストに設定します。これを使用すると、 collect-static
によってstatic/
ディレクトリにバンドルされる、使用していないアプリからのファイルを含むディレクトリのコピーを無視できます。たとえば、 DISTILL_SKIP_STATICFILES_DIRS
['some_dir']
に設定すると、静的ファイル ディレクトリstatic/some_dir
がスキップされます。
DISTILL_LANGUAGES : リスト、デフォルトは[]
DISTILL_LANGUAGES = [
'en' ,
'fr' ,
'de' ,
]
DISTILL_LANGUAGES
、URL のレンダリングに使用する言語コードのリストに設定します。詳細については、「国際化」セクションを参照してください。
HTTPS をサポートするローカル開発環境を使用している場合は、リクエストが予想される HTTP/200 応答コードではなく 301 リダイレクトを返したときにCommandError
が発生しないように、 SECURE_SSL_REDIRECT = False
settings.py
に追加する必要がある場合があります。
django-distill
バージョン3.0.0
では、 django_distill.renderer.render_single_file
メソッドを使用して、 django_distill
を使用して単一のファイルをディスクに書き出すことができます。これは、単一のファイルをディスクに書き出す場合に便利です。たとえば、 django_distill
によって書き込まれたディレクトリに静的ファイルがいくつかある Django サイトがありますが、サイトの残りの部分は通常の動的 Django サイトです。モデル インスタンスが保存されるたびに、静的 HTML ファイルを更新できます。これを実現するには、シグナルを使用した単一ファイルの書き込みを使用できます。例えば:
# in models.py
from django . db . models . signals import post_save
from django . dispatch import receiver
from django_distill . renderer import render_single_file
@ receiver ( post_save , sender = SomeBlogPostModel )
def write_blog_post_static_file_post_save ( sender , ** kwargs ):
render_single_file (
'/path/to/output/directory' ,
'blog-post-view-name' ,
blog_id = sender . pk ,
blog_slug = sender . slug
)
render_single_file
の構文は、Django のurl.reverse
に似ています。完全な使用インターフェースは次のとおりです。
render_single_file (
'/path/to/output/directory' ,
'view-name-set-in-urls-py' ,
* view_args ,
** view_kwargs
)
たとえば、ブログ投稿の URL が次のように定義されているとします。
# in urls.py
distill_path ( 'post/<int:blog_id>_<slug:blog_slug>.html' ,
PostView . as_view (),
name = 'blog-post' ,
distill_func = get_all_blogposts ),
使用法は次のようになります。
render_single_file (
'/path/to/output/directory' ,
'blog-post' ,
blog_id = 123 ,
blog_slug = 'blog-title-slug' ,
)
これにより、 /post/123_blog-title-slug.html
の内容が/path/to/output/directory
に/path/to/output/directory/post/123_blog-title-slug.html
ファイルとして書き込まれます。必要なサブディレクトリ (この例では/path/to/output/directory/post
) が存在しない場合は自動的に作成されることに注意してください。すべてのdjango-distill
ルールが適用されます。たとえば、 /
で終わる URL は、ディスク上の物理ファイルとして意味をなすように/index.html
として保存されます。
また、 render_single_file
、初期化された Django プロジェクトにのみインポートして使用できることに注意してください。
バックエンド データベース エンジンを変更することで、Django で MySQL、SQLite、PostgreSQL などを使用するのと同じように、バックエンドを通じてサポートされているさまざまなリモート ターゲットにサイトを自動的に公開できます。現在、 django-distill
でサポートされているエンジンは次のとおりです。
django_distill.backends.amazon_s3 : Amazon S3 バケットに公開します。 Python ライブラリboto3
( $ pip install django-distill[amazon]
) が必要です。バケットはすでに存在している必要があります (AWS コントロール パネルを使用します)。オプション:
'some-s3-container' : {
'ENGINE' : 'django_distill.backends.amazon_s3' ,
'PUBLIC_URL' : 'http://.../' ,
'ACCESS_KEY_ID' : '...' ,
'SECRET_ACCESS_KEY' : '...' ,
'BUCKET' : '...' ,
'ENDPOINT_URL' : 'https://.../' , # Optional, set to use a different S3 endpoint
'DEFAULT_CONTENT_TYPE' : 'application/octet-stream' , # Optional
},
django_distill.backends.google_storage : Google Cloud Storage バケットに公開します。 Python ライブラリgoogle-api-python-client
およびgoogle-cloud-storage
( $ pip install django-distill[google]
) が必要です。バケットはすでに存在しており、公開静的ウェブサイトをホストするように設定されている必要があります (Google Cloud コントロール パネルを使用)。オプション:
'some-google-storage-bucket' : {
'ENGINE' : 'django_distill.backends.google_storage' ,
'PUBLIC_URL' : 'https://storage.googleapis.com/[bucket.name.here]/' ,
'BUCKET' : '[bucket.name.here]' ,
'JSON_CREDENTIALS' : '/path/to/some/credentials.json' ,
},
JSON_CREDENTIALS
オプションであることに注意してください。指定されていない場合、Google ライブラリは、https://cloud.google.com/docs/authentication/application-default-credentials で説明されている検索順序で他の認証方法を試行します (例: GOOGLE_APPLICATION_CREDENTIALS
環境変数、接続されたサービス)アカウントなど)。
django_distill.backends.microsoft_azure_storage : Microsoft Azure Blob Storage コンテナーに発行します。 Python ライブラリazure-storage-blob
( $ pip install django-distill[microsoft]
) が必要です。ストレージ アカウントがすでに存在しており、パブリック静的 Web サイトをホストするように設定されている必要があります (Microsoft Azure コントロール パネルを使用します)。オプション:
'some-microsoft-storage-account' : {
'ENGINE' : 'django_distill.backends.microsoft_azure_storage' ,
'PUBLIC_URL' : 'https://[storage-account-name]...windows.net/' ,
'CONNECTION_STRING' : '...' ,
},
各 Azure ストレージ アカウントは、 django-distill
がサイトの公開を試みるマジック コンテナー$web
使用して 1 つの静的 Web サイトをサポートしていることに注意してください。
最小限のテスト スイートがあり、このリポジトリを閉じ、 requirements.txt
に必要な依存関係をインストールして、次のコマンドを実行することで実行できます。
# ./run-tests.py
適切にフォーマットされた賢明なプルリクエスト、問題、コメントはすべて歓迎されます。