django-distill
ahora tiene un sitio web. Leer más en:
django-distill
es un generador y editor de sitios estáticos de configuración mínima para Django. La mayoría de las versiones de Django son compatibles; sin embargo, se recomiendan versiones actualizadas, incluidas las versiones de Django 3.x. django-distill
a partir de la versión 1.7 solo es compatible con Python 3. Se ha eliminado la compatibilidad con Python 2. Si necesita compatibilidad con Python 2, fije django-distill
a la versión 1.6 en su require.txt o Pipfile. Se recomienda Python 3.6 o superior.
django-distill
amplía los sitios Django existentes con la capacidad de exportar sitios estáticos completamente funcionales. Es adecuado para sitios como blogs que tienen una interfaz mayoritariamente estática pero que aun así desean utilizar un CMS para gestionar el contenido.
django-distill
itera sobre las URL en su proyecto Django utilizando funciones iterables fáciles de escribir para generar los parámetros de cualquier página que desee guardar como HTML estático. Estos archivos estáticos se pueden cargar automáticamente en un contenedor remoto estilo depósito, como Amazon S3, Googe Cloud Files, Microsoft Azure Storage o escribirse en un directorio local como una versión estática local completamente funcional de su proyecto. El proceso de generación o destilación de sitios se puede integrar fácilmente en los flujos de trabajo de CI/CD para implementar automáticamente sitios estáticos en el momento de la confirmación. django-distill
se puede definir como una extensión de Django para hacer que los proyectos de Django sean compatibles con la arquitectura de sitios de estilo "Jamstack".
django-distill
se conecta directamente al marco Django existente sin la necesidad de escribir renderizadores personalizados u otro código más detallado. También puedes integrar django-distill
con sitios dinámicos existentes y simplemente generar páginas estáticas para una pequeña subsección de páginas en lugar de todo el sitio.
Para archivos estáticos en CDN, puede utilizar la siguiente biblioteca 'cache buster' para permitir actualizaciones rápidas de medios estáticos al enviar cambios:
? meeb/django-cachekiller
Hay un sitio de ejemplo completo que crea un blog estático y usa django-distill
con django-cachekiller
mediante implementación continua en Netlify disponible aquí:
? meeb/django-distill-ejemplo
Instalar desde pip:
$ pip install django-distill
Agregue django_distill
a sus INSTALLED_APPS
en su settings.py
:
INSTALLED_APPS = [
# ... other apps here ...
'django_distill' ,
]
Eso es todo.
django-distill
genera páginas estáticas y, por lo tanto, solo se admiten vistas que permiten solicitudes GET
que devuelven un código de estado HTTP 200
.
Se supone que está utilizando parámetros de URI como /blog/123-abc
y no parámetros de cadena de consulta como /blog?post_id=123&title=abc
. Los parámetros de cadena de consulta no tienen sentido para la generación de páginas estáticas por razones obvias.
Los archivos de medios estáticos, como imágenes y hojas de estilo, se copian desde su directorio de medios estáticos definido en STATIC_ROOT
. Esto significa que querrás ejecutar ./manage.py collectstatic
antes de ejecutar ./manage.py distill-local
si has realizado cambios en los medios estáticos. django-distill
no encadena esta solicitud por diseño, sin embargo, puedes habilitarla con el argumento --collectstatic
.
Suponiendo que tiene un proyecto Django existente, edite un urls.py
para incluir la función distill_path
que reemplaza la función path
estándar de Django y admite los nuevos argumentos de palabras clave distill_func
y distill_file
.
El argumento distill_func
debe proporcionarse con una función o clase invocable que devuelva un iterable o None
.
El argumento distill_file
es completamente opcional y le permite anular la URL que de otro modo se generaría a partir del reverso de la expresión regular de la URL. Esto le permite cambiar el nombre de URL como /example
a cualquier otro nombre como example.html
. A partir de la versión 0.8, cualquier URI que termine en una barra diagonal /
se modifica automáticamente para terminar en /index.html
. Puede usar parámetros de cadena de formato en distill_file
para personalizar el nombre del archivo; los valores de argumento de la URL se sustituirán, por ejemplo, {}
para argumentos posicionales o {param_name}
para argumentos con nombre.
Un ejemplo de configuración destilada para una aplicación de blogs teórica sería:
# 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 ),
)
Su sitio seguirá funcionando de manera idéntica con los cambios anteriores. Internamente, los parámetros distill_func
y distill_file
se eliminan y la URL se devuelve a Django para su procesamiento normal. Esto no tiene ningún impacto en el rendimiento del tiempo de ejecución, ya que ocurre solo una vez al iniciar la aplicación.
Si su ruta no tiene parámetros de URI, como /
o /some-static-url
no tiene que especificar el parámetro distill_func
si no lo desea. En cuanto a las rutas sin parámetros, distill_func
siempre devuelve None
, esto está configurado como el comportamiento predeterminado para distill_func
s.
También puedes usar la función distill_re_path
, que reemplaza la función predeterminada django.urls.re_path
. Su uso es idéntico al anterior:
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 ),
)
Si está utilizando una versión anterior de Django en la serie 1.x, puede usar la función distill_url
que reemplaza las funciones django.conf.urls.url
o django.urls.url
. Su uso es idéntico al anterior:
from django_distill import distill_url
urlpatterns = (
distill_url ( r'some/regex'
SomeView . as_view (),
name = 'url-view' ,
distill_func = some_func ),
)
También puede usar el formato de cadena de Python estándar en distill_file
para permitirle cambiar la ruta del archivo de salida de un archivo si lo desea. Tenga en cuenta que esto no actualiza la URL utilizada por Django, por lo que si usa esto, asegúrese de que su patrón path
coincida con el patrón distill_file
o sus enlaces podrían no funcionar en Django. Un ejemplo:
# 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"
)
Todas las vistas representadas por django-distill
en páginas estáticas deben devolver un código de estado HTTP 200. Si por algún motivo necesita representar una vista que no devuelve un código de estado HTTP 200, por ejemplo, también desea generar estáticamente una página 404 que tenga una vista que (correctamente) devuelva un código de estado HTTP 404, puede usar distill_status_codes
Argumento opcional para una vista. Por ejemplo:
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 ),
)
El argumento opcional distill_status_codes
acepta una tupla de códigos de estado como números enteros que la vista puede devolver sin generar un error. De forma predeterminada, esto está configurado en (200,)
pero puede anularlo si lo necesita para su sitio.
django-distill
reflejará cualquier versión instalada de Django que admita, por lo tanto, en algún momento la función distill_url
dejará de funcionar en el futuro cuando Django 2.x deprecie las funciones django.conf.urls.url
y django.urls.url
. Puede utilizar distill_re_path
como reemplazo directo. Es recomendable utilizar distill_path
o distill_re_path
si estás creando un sitio nuevo ahora.
La internacionalización solo se admite para URL; el contenido de la página no se puede traducir dinámicamente. De forma predeterminada, su sitio se generará utilizando el valor LANGUAGE_CODE
en su settings.py
. Si también configura settings.USE_I18N
en True
, luego establece otros códigos de idioma en su valor settings.DISTILL_LANGUAGES
y registra las URL con i18n_patterns(...)
entonces su sitio se generará en varios idiomas. Esto supone que su sitio multilingüe funciona como se esperaba antes de agregar django-distill
.
Por ejemplo, si configura settings.LANGUAGE_CODE = 'en'
su sitio se generará en un idioma.
Si tienes algo como esto en tu settings.py
en su lugar:
USE_I18N = True
DISTILL_LANGUAGES = [
'en' ,
'fr' ,
'de' ,
]
Mientras también usas i18n_patterns
en tu urls.py
así:
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
)
)
Luego, sus vistas se generarán como /en/some-file.html
, /fr/some-file.html
y /de/some-file.html
. Estas URL ya deberían funcionar (y estar traducidas) en su sitio. django-distill
no hace ninguna traducción mágica, simplemente llama a las URL con el prefijo del código de idioma.
Nota Si bien el método sugerido predeterminado es usar settings.DISTILL_LANGUAGES
para mantener las cosas separadas, django-distill
también verificará settings.LANGUAGES
para los códigos de idioma.
Es posible que necesites generar una lista de todas las URL registradas con django-distill
. Por ejemplo, tiene un blog generado estáticamente con unos cientos de páginas y desea enumerar todas las URL fácilmente en un sitemap.xml
u otra lista similar de todas las URL. Puede envolver la vista de su mapa del sitio en distill_path
y luego replicar toda la lógica de generación de URL importando sus vistas distill_func
s desde su urls.py
y generándolas todas manualmente, pero dado que esto es bastante complicado, hay un asistente incorporado para generar todas sus URL que se destilarán para usted.
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
Tenga en cuenta que distilled_urls()
solo devolverá URL después de que todas sus URL en urls.py
se hayan cargado con distill_path(...)
.
distill-local
Una vez que haya empaquetado las URL que desea generar estáticamente, ahora puede generar un sitio estático que funcione completamente con:
$ ./manage.py distill-local [optional /path/to/export/directory]
En el fondo, esto simplemente itera todas las URL registradas con distill_url
y genera las páginas para ellas utilizando partes del marco de prueba de Django para falsificar solicitudes. Una vez que se han renderizado las páginas del sitio, se copian los archivos de STATIC_ROOT
. Los archivos existentes con el mismo nombre se reemplazan en el directorio de destino y los archivos huérfanos se eliminan.
distill-local
admite los siguientes argumentos opcionales:
--collectstatic
: ejecuta automáticamente collectstatic
en tu sitio antes de renderizarlo, este es solo un atajo para evitar que tengas que escribir un comando adicional.
--quiet
: deshabilita todos los resultados excepto hacer preguntas de confirmación.
--force
: Asuma "sí" a todas las preguntas de confirmación.
--exclude-staticfiles
: No copie ningún archivo estático, solo renderice la salida de las vistas de Django.
--parallel-render [number of threads]
: renderiza archivos en paralelo en varios subprocesos, esto puede acelerar el renderizado. El valor predeterminado es 1
hilo.
--generate-redirects
: intenta generar redirecciones estáticas almacenadas en la aplicación django.contrib.redirects
. Si tiene una redirección de /old/
a /new/
el uso de esta bandera creará una redirección de estilo HTML estático <meta http-equiv="refresh" content="...">
en /old/index.html
a /new/
.
Nota Si alguna de sus vistas contiene un error de Python, la renderización fallará, el seguimiento de la pila se imprimirá en la terminal y el comando de renderización saldrá con un código de estado de 1.
distill-publish
$ ./manage.py distill-publish [optional destination here]
Si ha configurado al menos un destino de publicación (ver a continuación), puede usar el comando distill-publish
para publicar el sitio en una ubicación remota.
Esto realizará una sincronización completa, eliminando cualquier archivo remoto que ya no esté presente en el sitio estático generado y cargando cualquier archivo nuevo o modificado. El sitio se integrará localmente primero en un directorio temporal durante la publicación, que se eliminará una vez que se haya publicado el sitio. Se comprobará que cada archivo ha sido publicado correctamente solicitándolo a través de la PUBLIC_URL
.
distill-publish
admite los siguientes argumentos opcionales:
--collectstatic
: ejecuta automáticamente collectstatic
en tu sitio antes de renderizarlo, este es solo un atajo para evitar que tengas que escribir un comando adicional.
--quiet
: deshabilita todos los resultados excepto hacer preguntas de confirmación.
--force
: Asuma "sí" a todas las preguntas de confirmación.
--exclude-staticfiles
: No copie ningún archivo estático, solo renderice la salida de las vistas de Django.
--skip-verify
: No prueba si los archivos se cargan correctamente en el servidor.
--ignore-remote-content
: no recupera la lista de archivos remotos. Significa que se cargarán todos los archivos y no se eliminará ningún archivo remoto existente. Esto puede resultar útil si tiene muchos archivos en el servidor remoto y sabe que desea actualizar la mayoría de ellos y no le importa si quedan archivos antiguos en el servidor.
--parallel-publish [number of threads]
: publique archivos en paralelo en varios subprocesos, esto puede acelerar la publicación. El valor predeterminado es 1
hilo.
--parallel-render [number of threads]
: renderiza archivos en paralelo en varios subprocesos, esto puede acelerar el renderizado. El valor predeterminado es 1
hilo.
--generate-redirects
: intenta generar redirecciones estáticas almacenadas en la aplicación django.contrib.redirects
. Si tiene una redirección de /old/
a /new/
el uso de esta bandera creará una redirección de estilo HTML estático <meta http-equiv="refresh" content="...">
en /old/index.html
a /new/
.
Tenga en cuenta que esto significa que si usa --force
y --quiet
, el directorio de salida tendrá todos los archivos que no forman parte de la exportación del sitio eliminados sin ninguna confirmación.
Nota Si alguna de sus vistas contiene un error de Python, la renderización fallará, el seguimiento de la pila se imprimirá en la terminal y el comando de renderización saldrá con un código de estado de 1.
distill-test-publish
$ ./manage.py distill-test-publish [optional destination here]
Esto se conectará a su destino de publicación, se autenticará en él, cargará un archivo con nombre aleatorio, verificará que existe en PUBLIC_URL
y luego lo eliminará nuevamente. Utilice esto para comprobar que la configuración de publicación sea correcta.
distill-test-publish
no tiene argumentos.
Puede configurar las siguientes variables settings.py
opcionales:
DISTILL_DIR : cadena, directorio predeterminado para exportar:
DISTILL_DIR = '/path/to/export/directory'
DISTILL_PUBLISH : diccionario, como settings.DATABASES
de Django, admite default
:
DISTILL_PUBLISH = {
'default' : {
... options ...
},
'some-other-target' : {
... options ...
},
}
DISTILL_SKIP_ADMIN_DIRS : bool, por defecto es True
DISTILL_SKIP_ADMIN_DIRS = True
Establezca DISTILL_SKIP_ADMIN_DIRS
en False
si desea que django-distill
también copie archivos estáticos en el directorio static/admin
. Por lo general, estos no son necesarios ni deseados para los sitios generados estáticamente. El comportamiento predeterminado es omitir los archivos de administración estáticos.
DISTILL_SKIP_STATICFILES_DIRS : lista, por defecto []
DISTILL_SKIP_STATICFILES_DIRS = [ 'some_dir' ]
Configure DISTILL_SKIP_STATICFILES_DIRS
en una lista de nombres de directorios que desea que django-distill
ignore los directorios en su directorio static/
definido. Puedes usar esto para ignorar la copia de directorios que contienen archivos de aplicaciones que no estás usando y que se incluyen en tu directorio static/
mediante collect-static
. Por ejemplo, si configura DISTILL_SKIP_STATICFILES_DIRS
en ['some_dir']
se omitirá el directorio de archivos estáticos static/some_dir
.
DISTILL_LANGUAGES : lista, por defecto []
DISTILL_LANGUAGES = [
'en' ,
'fr' ,
'de' ,
]
Establezca DISTILL_LANGUAGES
en una lista de códigos de idioma para intentar representar las URL. Consulte la sección "Internacionalización" para más detalles.
Si está utilizando un entorno de desarrollo local que admite HTTPS, es posible que deba agregar SECURE_SSL_REDIRECT = False
a su settings.py
para evitar que se genere un CommandError
cuando una solicitud devuelva una redirección 301 en lugar del código de respuesta HTTP/200 esperado.
A partir de la versión 3.0.0
django-distill
, puedes usar el método django_distill.renderer.render_single_file
para escribir un solo archivo en el disco usando django_distill
. Esto es útil para escribir archivos individuales en el disco; por ejemplo, tiene un sitio Django que tiene algunos archivos estáticos en un directorio escrito por django_distill
pero el resto del sitio es un sitio Django dinámico normal. Puede actualizar un archivo HTML estático cada vez que se guarda una instancia de modelo. Puede utilizar la escritura de un solo archivo con señales para lograr esto. Por ejemplo:
# 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
)
La sintaxis de render_single_file
es similar a url.reverse
de Django. La interfaz de uso completa es:
render_single_file (
'/path/to/output/directory' ,
'view-name-set-in-urls-py' ,
* view_args ,
** view_kwargs
)
Por ejemplo, si tuviera la URL de una publicación de blog definida como:
# in urls.py
distill_path ( 'post/<int:blog_id>_<slug:blog_slug>.html' ,
PostView . as_view (),
name = 'blog-post' ,
distill_func = get_all_blogposts ),
Su uso sería:
render_single_file (
'/path/to/output/directory' ,
'blog-post' ,
blog_id = 123 ,
blog_slug = 'blog-title-slug' ,
)
lo que escribiría el contenido de /post/123_blog-title-slug.html
en /path/to/output/directory
como el archivo /path/to/output/directory/post/123_blog-title-slug.html
. Tenga en cuenta que los subdirectorios necesarios ( /path/to/output/directory/post
en este ejemplo) se crearán automáticamente si aún no existen. Se aplican todas las reglas django-distill
, como las URL que terminan en /
se guardarán como /index.html
para que tengan sentido para un archivo físico en el disco.
También tenga en cuenta que render_single_file
solo se puede importar y utilizar en un proyecto Django inicializado.
Puede publicar sitios automáticamente en varios objetivos remotos compatibles a través de backends, de la misma manera que puede usar MySQL, SQLite, PostgreSQL, etc. con Django cambiando el motor de base de datos backend. Actualmente los motores soportados por django-distill
son:
django_distill.backends.amazon_s3 : publicar en un depósito de Amazon S3. Requiere la biblioteca Python boto3
( $ pip install django-distill[amazon]
). El depósito ya debe existir (use el panel de control de AWS). Opciones:
'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 : publicar en un depósito de Google Cloud Storage. Requiere las bibliotecas de Python google-api-python-client
y google-cloud-storage
( $ pip install django-distill[google]
). El depósito ya debe existir y estar configurado para alojar un sitio web estático público (use el panel de control de Google Cloud). Opciones:
'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' ,
},
Tenga en cuenta que JSON_CREDENTIALS
es opcional; si no se especifica, las bibliotecas de Google probarán otros métodos de autenticación, en el orden de búsqueda que se describe aquí: https://cloud.google.com/docs/authentication/application-default-credentials (por ejemplo, la variable de entorno GOOGLE_APPLICATION_CREDENTIALS
, servicio adjunto cuenta, etc.).
django_distill.backends.microsoft_azure_storage : publicar en un contenedor de Microsoft Azure Blob Storage. Requiere la biblioteca de Python azure-storage-blob
( $ pip install django-distill[microsoft]
). La cuenta de almacenamiento ya debe existir y estar configurada para alojar un sitio web estático público (use el panel de control de Microsoft Azure). Opciones:
'some-microsoft-storage-account' : {
'ENGINE' : 'django_distill.backends.microsoft_azure_storage' ,
'PUBLIC_URL' : 'https://[storage-account-name]...windows.net/' ,
'CONNECTION_STRING' : '...' ,
},
Tenga en cuenta que cada cuenta de almacenamiento de Azure admite un sitio web estático utilizando el contenedor mágico $web
, que es donde django-distill
intentará publicar su sitio.
Hay un conjunto de pruebas mínimo, puede ejecutarlo cerrando este repositorio, instalando las dependencias requeridas en requirements.txt
y luego ejecutando:
# ./run-tests.py
Todas las solicitudes de extracción, problemas y comentarios sensatos y con el formato adecuado son bienvenidos.