Repository files navigation

License: MITPyPI versionPyPI pyversionsPyPI djversionsPyPI statusPyPI - TypesDocumentation StatusCode CovTest StatusLint StatusRuffPublished on Django PackagesOpenSSF Scorecard

django-render-static

Use Django's template engines to render static files that are collected during the collectstatic routine and likely served above Django at runtime. Files rendered by django-render-static are immediately available to participate in the normal static file collection pipeline.

For example, a frequently occurring pattern that violates the DRY principle is the presence of defines, or enum like structures in server side Python code that are simply replicated in client side JavaScript. Another example might be rebuilding Django URLs from arguments in a Single Page Application. Single-sourcing these structures by transpiling client side code from the server side code keeps the stack bone DRY.

django-render-static includes Python to Javascript transpilers for:

  • Django's reverse function (urls_to_js)
  • PEP 435 style Python enumerations (enums_to_js)
  • Plain data define-like structures in Python classes and modules (defines_to_js)

Transpilation is extremely flexible and may be customized by using override blocks or extending the provided transpilers.

django-render-static also formalizes the concept of a package-time or deployment-time static file rendering step. It piggybacks off the existing templating engines and configurations and should therefore be familiar to Django developers. It supports both standard Django templating and Jinja templates and allows contexts to be specified in python, json or YAML.

You can report bugs and discuss features on the issues page.

Contributions are encouraged!

Full documentation at read the docs.

Installation

  1. Clone django-render-static from GitHub or install a release off PyPI:
pip install django-render-static
  1. Add 'render_static' to your INSTALLED_APPS :
INSTALLED_APPS= [
'render_static',
]
  1. Add a STATIC_TEMPLATES configuration directive to your settings file:
STATIC_TEMPLATES= {
'templates' : [
('path/to/template':, {'context' {'variable': 'value'})
]
}
  1. Run renderstatic preceding every run of collectstatic :
$> manage.py renderstatic
$> manage.py collectstatic

Usage

Transpiling URL reversal

You'd like to be able to call something like reverse on path names from your client JavaScript code the same way you do from Python Django code.

Your settings file might look like:

STATIC_TEMPLATES={
'ENGINES': [{
'BACKEND': 'render_static.backends.StaticDjangoTemplates',
'OPTIONS': {
'loaders': [
('render_static.loaders.StaticLocMemLoader', {
'urls.js': '{% urls_to_js %}'
})
]
},
}],
'templates': ['urls.js']
}

Then call renderstatic before collectstatic:

$> ./manage.py renderstatic
$> ./manage.py collectstatic

If your root urls.py looks like this:

fromdjango.contribimportadminfromdjango.urlsimportpathfrom .viewsimportMyViewurlpatterns= [
path('admin/', admin.site.urls),
path('simple', MyView.as_view(), name='simple'),
path('simple/<int:arg1>', MyView.as_view(), name='simple'),
path('different/<int:arg1>/<str:arg2>', MyView.as_view(), name='different'),
]

So you can now fetch paths like this, in a way that is roughly API-equivalent to Django's reverse function:

import{URLResolver}from'/static/urls.js';consturls=newURLResolver();// /different/143/emmaurls.reverse('different',{kwargs: {'arg1': 143,'arg2': 'emma'}});// reverse also supports query parameters// /different/143/emma?intarg=0&listarg=A&listarg=B&listarg=Curls.reverse('different',{kwargs: {arg1: 143,arg2: 'emma'},query: {intarg: 0,listarg: ['A','B','C']}});

URLGenerationFailed Exceptions & Placeholders

If you encounter a URLGenerationFailed exception you most likely need to register a placeholder for the argument in question. A placeholder is just a string or object that can be coerced to a string that matches the regular expression for the argument:

fromrender_static.placeholdersimportregister_variable_placeholderapp_name='year_app'urlpatterns= [
re_path(r'^fetch/(?P<year>\d{4})/$', YearView.as_view(), name='fetch_year')
]
register_variable_placeholder('year', 2000, app_name=app_name)

Users should typically use a path instead of re_path and register their own custom converters when needed. Placeholders can be directly registered on the converter (and are then conveniently available to users of your app!):

fromdjango.urls.convertersimportregister_converterclassYearConverter:
regex='[0-9]{4}'placeholder=2000# this attribute is used by `url_to_js` to reverse pathsdefto_python(self, value):
returnint(value)
defto_url(self, value):
returnstr(value)
register_converter(YearConverter, 'year')
urlpatterns= [
path('fetch/<year:year>', YearView.as_view(), name='fetch_year')
]

Transpiling Enumerations

Say instead of the usual choices tuple you're using PEP 435 style python enumerations as model fields using django-enum and enum-properties. For example we might define a simple color enumeration like so:

fromdjango.dbimportmodelsfromdjango_enumimportEnumField, TextChoicesfromenum_propertiesimportp, sclassExampleModel(models.Model):
classColor(TextChoices, s('rgb'), s('hex', case_fold=True)):
# name value label rgb hexRED='R', 'Red', (1, 0, 0), 'ff0000'GREEN='G', 'Green', (0, 1, 0), '00ff00'BLUE='B', 'Blue', (0, 0, 1), '0000ff'color=EnumField(Color, null=True, default=None)

If we define an enum.js template that looks like this:


{% enums_to_js enums="examples.models.ExampleModel.Color" %}

It will contain a javascript class transpilation of the Color enum that looks like this:

classColor{staticRED=newColor("R","RED","Red",[1,0,0],"ff0000");staticGREEN=newColor("G","GREEN","Green",[0,1,0],"00ff00");staticBLUE=newColor("B","BLUE","Blue",[0,0,1],"0000ff");constructor(value,name,label,rgb,hex){this.value=value;this.name=name;this.label=label;this.rgb=rgb;this.hex=hex;}toString(){returnthis.value;}staticget(value){switch(value){case"R":
returnColor.RED;case"G":
returnColor.GREEN;case"B":
returnColor.BLUE;}thrownewTypeError(`No Color enumeration maps to value ${value}`);}static[Symbol.iterator](){return[Color.RED,Color.GREEN,Color.BLUE][Symbol.iterator]();}}

We can now use our enumeration like so:

Color.BLUE===Color.get('B');for(constcolorofColor){console.log(color);}

Transpiling Model Field Choices

You have an app with a model with a character field that has several valid choices defined in an enumeration type way, and you'd like to export those defines to JavaScript. You'd like to include a template for other's using your app to use to generate a defines.js file. Say your app structure looks like this::

.
└── examples
├── __init__.py
├── apps.py
├── defines.py
├── models.py
├── static_templates
│ └── examples
│ └── defines.js
└── urls.py

Your defines/model classes might look like this:

classExampleModel(Defines, models.Model):
DEFINE1='D1'DEFINE2='D2'DEFINE3='D3'DEFINES= (
(DEFINE1, 'Define 1'),
(DEFINE2, 'Define 2'),
(DEFINE3, 'Define 3')
)
define_field=models.CharField(choices=DEFINES, max_length=2)

And your defines.js template might look like this:

{% defines_to_js modules="examples.models" %}

If someone wanted to use your defines template to generate a JavaScript version of your Python class their settings file might look like this:

STATIC_TEMPLATES= {
'templates': [
'examples/defines.js'
]
}

And then of course they would call renderstatic before collectstatic:

$> ./manage.py renderstatic
$> ./manage.py collectstatic

This would create the following file::

.
└── examples
└── static
└── examples
└── defines.js

Which would look like this:

constdefines={ExampleModel: {DEFINE1: "D1",DEFINE2: "D2",DEFINE3: "D3",DEFINES: [["D1","Define 1"],["D2","Define 2"],["D3","Define 3"]]}};

About

Use Django's template engines to render static files at deployment or package time. Includes transpilers for extending Django's url reversal and enums to JavaScript.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

24 stars

Watchers

1 watching

Forks

Releases

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

License: MITPyPI versionPyPI pyversionsPyPI djversionsPyPI statusPyPI - TypesDocumentation StatusCode CovTest StatusLint StatusRuffPublished on Django PackagesOpenSSF Scorecard

django-render-static

Use Django's template engines to render static files that are collected during the collectstatic routine and likely served above Django at runtime. Files rendered by django-render-static are immediately available to participate in the normal static file collection pipeline.

For example, a frequently occurring pattern that violates the DRY principle is the presence of defines, or enum like structures in server side Python code that are simply replicated in client side JavaScript. Another example might be rebuilding Django URLs from arguments in a Single Page Application. Single-sourcing these structures by transpiling client side code from the server side code keeps the stack bone DRY.

django-render-static includes Python to Javascript transpilers for:

  • Django's reverse function (urls_to_js)
  • PEP 435 style Python enumerations (enums_to_js)
  • Plain data define-like structures in Python classes and modules (defines_to_js)

Transpilation is extremely flexible and may be customized by using override blocks or extending the provided transpilers.

django-render-static also formalizes the concept of a package-time or deployment-time static file rendering step. It piggybacks off the existing templating engines and configurations and should therefore be familiar to Django developers. It supports both standard Django templating and Jinja templates and allows contexts to be specified in python, json or YAML.

You can report bugs and discuss features on the issues page.

Contributions are encouraged!

Full documentation at read the docs.

Installation

  1. Clone django-render-static from GitHub or install a release off PyPI:
pip install django-render-static
  1. Add 'render_static' to your INSTALLED_APPS :
INSTALLED_APPS= [
'render_static',
]
  1. Add a STATIC_TEMPLATES configuration directive to your settings file:
STATIC_TEMPLATES= {
'templates' : [
('path/to/template':, {'context' {'variable': 'value'})
]
}
  1. Run renderstatic preceding every run of collectstatic :
$> manage.py renderstatic
$> manage.py collectstatic

Usage

Transpiling URL reversal

You'd like to be able to call something like reverse on path names from your client JavaScript code the same way you do from Python Django code.

Your settings file might look like:

STATIC_TEMPLATES={
'ENGINES': [{
'BACKEND': 'render_static.backends.StaticDjangoTemplates',
'OPTIONS': {
'loaders': [
('render_static.loaders.StaticLocMemLoader', {
'urls.js': '{% urls_to_js %}'
})
]
},
}],
'templates': ['urls.js']
}

Then call renderstatic before collectstatic:

$> ./manage.py renderstatic
$> ./manage.py collectstatic

If your root urls.py looks like this:

fromdjango.contribimportadminfromdjango.urlsimportpathfrom .viewsimportMyViewurlpatterns= [
path('admin/', admin.site.urls),
path('simple', MyView.as_view(), name='simple'),
path('simple/<int:arg1>', MyView.as_view(), name='simple'),
path('different/<int:arg1>/<str:arg2>', MyView.as_view(), name='different'),
]

So you can now fetch paths like this, in a way that is roughly API-equivalent to Django's reverse function:

import{URLResolver}from'/static/urls.js';consturls=newURLResolver();// /different/143/emmaurls.reverse('different',{kwargs: {'arg1': 143,'arg2': 'emma'}});// reverse also supports query parameters// /different/143/emma?intarg=0&listarg=A&listarg=B&listarg=Curls.reverse('different',{kwargs: {arg1: 143,arg2: 'emma'},query: {intarg: 0,listarg: ['A','B','C']}});

URLGenerationFailed Exceptions & Placeholders

If you encounter a URLGenerationFailed exception you most likely need to register a placeholder for the argument in question. A placeholder is just a string or object that can be coerced to a string that matches the regular expression for the argument:

fromrender_static.placeholdersimportregister_variable_placeholderapp_name='year_app'urlpatterns= [
re_path(r'^fetch/(?P<year>\d{4})/$', YearView.as_view(), name='fetch_year')
]
register_variable_placeholder('year', 2000, app_name=app_name)

Users should typically use a path instead of re_path and register their own custom converters when needed. Placeholders can be directly registered on the converter (and are then conveniently available to users of your app!):

fromdjango.urls.convertersimportregister_converterclassYearConverter:
regex='[0-9]{4}'placeholder=2000# this attribute is used by `url_to_js` to reverse pathsdefto_python(self, value):
returnint(value)
defto_url(self, value):
returnstr(value)
register_converter(YearConverter, 'year')
urlpatterns= [
path('fetch/<year:year>', YearView.as_view(), name='fetch_year')
]

Transpiling Enumerations

Say instead of the usual choices tuple you're using PEP 435 style python enumerations as model fields using django-enum and enum-properties. For example we might define a simple color enumeration like so:

fromdjango.dbimportmodelsfromdjango_enumimportEnumField, TextChoicesfromenum_propertiesimportp, sclassExampleModel(models.Model):
classColor(TextChoices, s('rgb'), s('hex', case_fold=True)):
# name value label rgb hexRED='R', 'Red', (1, 0, 0), 'ff0000'GREEN='G', 'Green', (0, 1, 0), '00ff00'BLUE='B', 'Blue', (0, 0, 1), '0000ff'color=EnumField(Color, null=True, default=None)

If we define an enum.js template that looks like this:


{% enums_to_js enums="examples.models.ExampleModel.Color" %}

It will contain a javascript class transpilation of the Color enum that looks like this:

classColor{staticRED=newColor("R","RED","Red",[1,0,0],"ff0000");staticGREEN=newColor("G","GREEN","Green",[0,1,0],"00ff00");staticBLUE=newColor("B","BLUE","Blue",[0,0,1],"0000ff");constructor(value,name,label,rgb,hex){this.value=value;this.name=name;this.label=label;this.rgb=rgb;this.hex=hex;}toString(){returnthis.value;}staticget(value){switch(value){case"R":
returnColor.RED;case"G":
returnColor.GREEN;case"B":
returnColor.BLUE;}thrownewTypeError(`No Color enumeration maps to value ${value}`);}static[Symbol.iterator](){return[Color.RED,Color.GREEN,Color.BLUE][Symbol.iterator]();}}

We can now use our enumeration like so:

Color.BLUE===Color.get('B');for(constcolorofColor){console.log(color);}

Transpiling Model Field Choices

You have an app with a model with a character field that has several valid choices defined in an enumeration type way, and you'd like to export those defines to JavaScript. You'd like to include a template for other's using your app to use to generate a defines.js file. Say your app structure looks like this::

.
└── examples
├── __init__.py
├── apps.py
├── defines.py
├── models.py
├── static_templates
│ └── examples
│ └── defines.js
└── urls.py

Your defines/model classes might look like this:

classExampleModel(Defines, models.Model):
DEFINE1='D1'DEFINE2='D2'DEFINE3='D3'DEFINES= (
(DEFINE1, 'Define 1'),
(DEFINE2, 'Define 2'),
(DEFINE3, 'Define 3')
)
define_field=models.CharField(choices=DEFINES, max_length=2)

And your defines.js template might look like this:

{% defines_to_js modules="examples.models" %}

If someone wanted to use your defines template to generate a JavaScript version of your Python class their settings file might look like this:

STATIC_TEMPLATES= {
'templates': [
'examples/defines.js'
]
}

And then of course they would call renderstatic before collectstatic:

$> ./manage.py renderstatic
$> ./manage.py collectstatic

This would create the following file::

.
└── examples
└── static
└── examples
└── defines.js

Which would look like this:

constdefines={ExampleModel: {DEFINE1: "D1",DEFINE2: "D2",DEFINE3: "D3",DEFINES: [["D1","Define 1"],["D2","Define 2"],["D3","Define 3"]]}};

About

Use Django's template engines to render static files at deployment or package time. Includes transpilers for extending Django's url reversal and enums to JavaScript.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

24 stars

Watchers

1 watching

Forks

Releases

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

License: MITPyPI versionPyPI pyversionsPyPI djversionsPyPI statusPyPI - TypesDocumentation StatusCode CovTest StatusLint StatusRuffPublished on Django PackagesOpenSSF Scorecard

django-render-static

Use Django's template engines to render static files that are collected during the collectstatic routine and likely served above Django at runtime. Files rendered by django-render-static are immediately available to participate in the normal static file collection pipeline.

For example, a frequently occurring pattern that violates the DRY principle is the presence of defines, or enum like structures in server side Python code that are simply replicated in client side JavaScript. Another example might be rebuilding Django URLs from arguments in a Single Page Application. Single-sourcing these structures by transpiling client side code from the server side code keeps the stack bone DRY.

django-render-static includes Python to Javascript transpilers for:

  • Django's reverse function (urls_to_js)
  • PEP 435 style Python enumerations (enums_to_js)
  • Plain data define-like structures in Python classes and modules (defines_to_js)

Transpilation is extremely flexible and may be customized by using override blocks or extending the provided transpilers.

django-render-static also formalizes the concept of a package-time or deployment-time static file rendering step. It piggybacks off the existing templating engines and configurations and should therefore be familiar to Django developers. It supports both standard Django templating and Jinja templates and allows contexts to be specified in python, json or YAML.

You can report bugs and discuss features on the issues page.

Contributions are encouraged!

Full documentation at read the docs.

Installation

  1. Clone django-render-static from GitHub or install a release off PyPI:
pip install django-render-static
  1. Add 'render_static' to your INSTALLED_APPS :
INSTALLED_APPS= [
'render_static',
]
  1. Add a STATIC_TEMPLATES configuration directive to your settings file:
STATIC_TEMPLATES= {
'templates' : [
('path/to/template':, {'context' {'variable': 'value'})
]
}
  1. Run renderstatic preceding every run of collectstatic :
$> manage.py renderstatic
$> manage.py collectstatic

Usage

Transpiling URL reversal

You'd like to be able to call something like reverse on path names from your client JavaScript code the same way you do from Python Django code.

Your settings file might look like:

STATIC_TEMPLATES={
'ENGINES': [{
'BACKEND': 'render_static.backends.StaticDjangoTemplates',
'OPTIONS': {
'loaders': [
('render_static.loaders.StaticLocMemLoader', {
'urls.js': '{% urls_to_js %}'
})
]
},
}],
'templates': ['urls.js']
}

Then call renderstatic before collectstatic:

$> ./manage.py renderstatic
$> ./manage.py collectstatic

If your root urls.py looks like this:

fromdjango.contribimportadminfromdjango.urlsimportpathfrom .viewsimportMyViewurlpatterns= [
path('admin/', admin.site.urls),
path('simple', MyView.as_view(), name='simple'),
path('simple/<int:arg1>', MyView.as_view(), name='simple'),
path('different/<int:arg1>/<str:arg2>', MyView.as_view(), name='different'),
]

So you can now fetch paths like this, in a way that is roughly API-equivalent to Django's reverse function:

import{URLResolver}from'/static/urls.js';consturls=newURLResolver();// /different/143/emmaurls.reverse('different',{kwargs: {'arg1': 143,'arg2': 'emma'}});// reverse also supports query parameters// /different/143/emma?intarg=0&listarg=A&listarg=B&listarg=Curls.reverse('different',{kwargs: {arg1: 143,arg2: 'emma'},query: {intarg: 0,listarg: ['A','B','C']}});

URLGenerationFailed Exceptions & Placeholders

If you encounter a URLGenerationFailed exception you most likely need to register a placeholder for the argument in question. A placeholder is just a string or object that can be coerced to a string that matches the regular expression for the argument:

fromrender_static.placeholdersimportregister_variable_placeholderapp_name='year_app'urlpatterns= [
re_path(r'^fetch/(?P<year>\d{4})/$', YearView.as_view(), name='fetch_year')
]
register_variable_placeholder('year', 2000, app_name=app_name)

Users should typically use a path instead of re_path and register their own custom converters when needed. Placeholders can be directly registered on the converter (and are then conveniently available to users of your app!):

fromdjango.urls.convertersimportregister_converterclassYearConverter:
regex='[0-9]{4}'placeholder=2000# this attribute is used by `url_to_js` to reverse pathsdefto_python(self, value):
returnint(value)
defto_url(self, value):
returnstr(value)
register_converter(YearConverter, 'year')
urlpatterns= [
path('fetch/<year:year>', YearView.as_view(), name='fetch_year')
]

Transpiling Enumerations

Say instead of the usual choices tuple you're using PEP 435 style python enumerations as model fields using django-enum and enum-properties. For example we might define a simple color enumeration like so:

fromdjango.dbimportmodelsfromdjango_enumimportEnumField, TextChoicesfromenum_propertiesimportp, sclassExampleModel(models.Model):
classColor(TextChoices, s('rgb'), s('hex', case_fold=True)):
# name value label rgb hexRED='R', 'Red', (1, 0, 0), 'ff0000'GREEN='G', 'Green', (0, 1, 0), '00ff00'BLUE='B', 'Blue', (0, 0, 1), '0000ff'color=EnumField(Color, null=True, default=None)

If we define an enum.js template that looks like this:


{% enums_to_js enums="examples.models.ExampleModel.Color" %}

It will contain a javascript class transpilation of the Color enum that looks like this:

classColor{staticRED=newColor("R","RED","Red",[1,0,0],"ff0000");staticGREEN=newColor("G","GREEN","Green",[0,1,0],"00ff00");staticBLUE=newColor("B","BLUE","Blue",[0,0,1],"0000ff");constructor(value,name,label,rgb,hex){this.value=value;this.name=name;this.label=label;this.rgb=rgb;this.hex=hex;}toString(){returnthis.value;}staticget(value){switch(value){case"R":
returnColor.RED;case"G":
returnColor.GREEN;case"B":
returnColor.BLUE;}thrownewTypeError(`No Color enumeration maps to value ${value}`);}static[Symbol.iterator](){return[Color.RED,Color.GREEN,Color.BLUE][Symbol.iterator]();}}

We can now use our enumeration like so:

Color.BLUE===Color.get('B');for(constcolorofColor){console.log(color);}

Transpiling Model Field Choices

You have an app with a model with a character field that has several valid choices defined in an enumeration type way, and you'd like to export those defines to JavaScript. You'd like to include a template for other's using your app to use to generate a defines.js file. Say your app structure looks like this::

.
└── examples
├── __init__.py
├── apps.py
├── defines.py
├── models.py
├── static_templates
│ └── examples
│ └── defines.js
└── urls.py

Your defines/model classes might look like this:

classExampleModel(Defines, models.Model):
DEFINE1='D1'DEFINE2='D2'DEFINE3='D3'DEFINES= (
(DEFINE1, 'Define 1'),
(DEFINE2, 'Define 2'),
(DEFINE3, 'Define 3')
)
define_field=models.CharField(choices=DEFINES, max_length=2)

And your defines.js template might look like this:

{% defines_to_js modules="examples.models" %}

If someone wanted to use your defines template to generate a JavaScript version of your Python class their settings file might look like this:

STATIC_TEMPLATES= {
'templates': [
'examples/defines.js'
]
}

And then of course they would call renderstatic before collectstatic:

$> ./manage.py renderstatic
$> ./manage.py collectstatic

This would create the following file::

.
└── examples
└── static
└── examples
└── defines.js

Which would look like this:

constdefines={ExampleModel: {DEFINE1: "D1",DEFINE2: "D2",DEFINE3: "D3",DEFINES: [["D1","Define 1"],["D2","Define 2"],["D3","Define 3"]]}};

About

Use Django's template engines to render static files at deployment or package time. Includes transpilers for extending Django's url reversal and enums to JavaScript.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

24 stars

Watchers

1 watching

Forks

Releases

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

License: MITPyPI versionPyPI pyversionsPyPI djversionsPyPI statusPyPI - TypesDocumentation StatusCode CovTest StatusLint StatusRuffPublished on Django PackagesOpenSSF Scorecard

django-render-static

Use Django's template engines to render static files that are collected during the collectstatic routine and likely served above Django at runtime. Files rendered by django-render-static are immediately available to participate in the normal static file collection pipeline.

For example, a frequently occurring pattern that violates the DRY principle is the presence of defines, or enum like structures in server side Python code that are simply replicated in client side JavaScript. Another example might be rebuilding Django URLs from arguments in a Single Page Application. Single-sourcing these structures by transpiling client side code from the server side code keeps the stack bone DRY.

django-render-static includes Python to Javascript transpilers for:

  • Django's reverse function (urls_to_js)
  • PEP 435 style Python enumerations (enums_to_js)
  • Plain data define-like structures in Python classes and modules (defines_to_js)

Transpilation is extremely flexible and may be customized by using override blocks or extending the provided transpilers.

django-render-static also formalizes the concept of a package-time or deployment-time static file rendering step. It piggybacks off the existing templating engines and configurations and should therefore be familiar to Django developers. It supports both standard Django templating and Jinja templates and allows contexts to be specified in python, json or YAML.

You can report bugs and discuss features on the issues page.

Contributions are encouraged!

Full documentation at read the docs.

Installation

  1. Clone django-render-static from GitHub or install a release off PyPI:
pip install django-render-static
  1. Add 'render_static' to your INSTALLED_APPS :
INSTALLED_APPS= [
'render_static',
]
  1. Add a STATIC_TEMPLATES configuration directive to your settings file:
STATIC_TEMPLATES= {
'templates' : [
('path/to/template':, {'context' {'variable': 'value'})
]
}
  1. Run renderstatic preceding every run of collectstatic :
$> manage.py renderstatic
$> manage.py collectstatic

Usage

Transpiling URL reversal

You'd like to be able to call something like reverse on path names from your client JavaScript code the same way you do from Python Django code.

Your settings file might look like:

STATIC_TEMPLATES={
'ENGINES': [{
'BACKEND': 'render_static.backends.StaticDjangoTemplates',
'OPTIONS': {
'loaders': [
('render_static.loaders.StaticLocMemLoader', {
'urls.js': '{% urls_to_js %}'
})
]
},
}],
'templates': ['urls.js']
}

Then call renderstatic before collectstatic:

$> ./manage.py renderstatic
$> ./manage.py collectstatic

If your root urls.py looks like this:

fromdjango.contribimportadminfromdjango.urlsimportpathfrom .viewsimportMyViewurlpatterns= [
path('admin/', admin.site.urls),
path('simple', MyView.as_view(), name='simple'),
path('simple/<int:arg1>', MyView.as_view(), name='simple'),
path('different/<int:arg1>/<str:arg2>', MyView.as_view(), name='different'),
]

So you can now fetch paths like this, in a way that is roughly API-equivalent to Django's reverse function:

import{URLResolver}from'/static/urls.js';consturls=newURLResolver();// /different/143/emmaurls.reverse('different',{kwargs: {'arg1': 143,'arg2': 'emma'}});// reverse also supports query parameters// /different/143/emma?intarg=0&listarg=A&listarg=B&listarg=Curls.reverse('different',{kwargs: {arg1: 143,arg2: 'emma'},query: {intarg: 0,listarg: ['A','B','C']}});

URLGenerationFailed Exceptions & Placeholders

If you encounter a URLGenerationFailed exception you most likely need to register a placeholder for the argument in question. A placeholder is just a string or object that can be coerced to a string that matches the regular expression for the argument:

fromrender_static.placeholdersimportregister_variable_placeholderapp_name='year_app'urlpatterns= [
re_path(r'^fetch/(?P<year>\d{4})/$', YearView.as_view(), name='fetch_year')
]
register_variable_placeholder('year', 2000, app_name=app_name)

Users should typically use a path instead of re_path and register their own custom converters when needed. Placeholders can be directly registered on the converter (and are then conveniently available to users of your app!):

fromdjango.urls.convertersimportregister_converterclassYearConverter:
regex='[0-9]{4}'placeholder=2000# this attribute is used by `url_to_js` to reverse pathsdefto_python(self, value):
returnint(value)
defto_url(self, value):
returnstr(value)
register_converter(YearConverter, 'year')
urlpatterns= [
path('fetch/<year:year>', YearView.as_view(), name='fetch_year')
]

Transpiling Enumerations

Say instead of the usual choices tuple you're using PEP 435 style python enumerations as model fields using django-enum and enum-properties. For example we might define a simple color enumeration like so:

fromdjango.dbimportmodelsfromdjango_enumimportEnumField, TextChoicesfromenum_propertiesimportp, sclassExampleModel(models.Model):
classColor(TextChoices, s('rgb'), s('hex', case_fold=True)):
# name value label rgb hexRED='R', 'Red', (1, 0, 0), 'ff0000'GREEN='G', 'Green', (0, 1, 0), '00ff00'BLUE='B', 'Blue', (0, 0, 1), '0000ff'color=EnumField(Color, null=True, default=None)

If we define an enum.js template that looks like this:


{% enums_to_js enums="examples.models.ExampleModel.Color" %}

It will contain a javascript class transpilation of the Color enum that looks like this:

classColor{staticRED=newColor("R","RED","Red",[1,0,0],"ff0000");staticGREEN=newColor("G","GREEN","Green",[0,1,0],"00ff00");staticBLUE=newColor("B","BLUE","Blue",[0,0,1],"0000ff");constructor(value,name,label,rgb,hex){this.value=value;this.name=name;this.label=label;this.rgb=rgb;this.hex=hex;}toString(){returnthis.value;}staticget(value){switch(value){case"R":
returnColor.RED;case"G":
returnColor.GREEN;case"B":
returnColor.BLUE;}thrownewTypeError(`No Color enumeration maps to value ${value}`);}static[Symbol.iterator](){return[Color.RED,Color.GREEN,Color.BLUE][Symbol.iterator]();}}

We can now use our enumeration like so:

Color.BLUE===Color.get('B');for(constcolorofColor){console.log(color);}

Transpiling Model Field Choices

You have an app with a model with a character field that has several valid choices defined in an enumeration type way, and you'd like to export those defines to JavaScript. You'd like to include a template for other's using your app to use to generate a defines.js file. Say your app structure looks like this::

.
└── examples
├── __init__.py
├── apps.py
├── defines.py
├── models.py
├── static_templates
│ └── examples
│ └── defines.js
└── urls.py

Your defines/model classes might look like this:

classExampleModel(Defines, models.Model):
DEFINE1='D1'DEFINE2='D2'DEFINE3='D3'DEFINES= (
(DEFINE1, 'Define 1'),
(DEFINE2, 'Define 2'),
(DEFINE3, 'Define 3')
)
define_field=models.CharField(choices=DEFINES, max_length=2)

And your defines.js template might look like this:

{% defines_to_js modules="examples.models" %}

If someone wanted to use your defines template to generate a JavaScript version of your Python class their settings file might look like this:

STATIC_TEMPLATES= {
'templates': [
'examples/defines.js'
]
}

And then of course they would call renderstatic before collectstatic:

$> ./manage.py renderstatic
$> ./manage.py collectstatic

This would create the following file::

.
└── examples
└── static
└── examples
└── defines.js

Which would look like this:

constdefines={ExampleModel: {DEFINE1: "D1",DEFINE2: "D2",DEFINE3: "D3",DEFINES: [["D1","Define 1"],["D2","Define 2"],["D3","Define 3"]]}};

About

Use Django's template engines to render static files at deployment or package time. Includes transpilers for extending Django's url reversal and enums to JavaScript.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

24 stars

Watchers

1 watching

Forks

Releases

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

License: MITPyPI versionPyPI pyversionsPyPI djversionsPyPI statusPyPI - TypesDocumentation StatusCode CovTest StatusLint StatusRuffPublished on Django PackagesOpenSSF Scorecard

django-render-static

Use Django's template engines to render static files that are collected during the collectstatic routine and likely served above Django at runtime. Files rendered by django-render-static are immediately available to participate in the normal static file collection pipeline.

For example, a frequently occurring pattern that violates the DRY principle is the presence of defines, or enum like structures in server side Python code that are simply replicated in client side JavaScript. Another example might be rebuilding Django URLs from arguments in a Single Page Application. Single-sourcing these structures by transpiling client side code from the server side code keeps the stack bone DRY.

django-render-static includes Python to Javascript transpilers for:

  • Django's reverse function (urls_to_js)
  • PEP 435 style Python enumerations (enums_to_js)
  • Plain data define-like structures in Python classes and modules (defines_to_js)

Transpilation is extremely flexible and may be customized by using override blocks or extending the provided transpilers.

django-render-static also formalizes the concept of a package-time or deployment-time static file rendering step. It piggybacks off the existing templating engines and configurations and should therefore be familiar to Django developers. It supports both standard Django templating and Jinja templates and allows contexts to be specified in python, json or YAML.

You can report bugs and discuss features on the issues page.

Contributions are encouraged!

Full documentation at read the docs.

Installation

  1. Clone django-render-static from GitHub or install a release off PyPI:
pip install django-render-static
  1. Add 'render_static' to your INSTALLED_APPS :
INSTALLED_APPS= [
'render_static',
]
  1. Add a STATIC_TEMPLATES configuration directive to your settings file:
STATIC_TEMPLATES= {
'templates' : [
('path/to/template':, {'context' {'variable': 'value'})
]
}
  1. Run renderstatic preceding every run of collectstatic :
$> manage.py renderstatic
$> manage.py collectstatic

Usage

Transpiling URL reversal

You'd like to be able to call something like reverse on path names from your client JavaScript code the same way you do from Python Django code.

Your settings file might look like:

STATIC_TEMPLATES={
'ENGINES': [{
'BACKEND': 'render_static.backends.StaticDjangoTemplates',
'OPTIONS': {
'loaders': [
('render_static.loaders.StaticLocMemLoader', {
'urls.js': '{% urls_to_js %}'
})
]
},
}],
'templates': ['urls.js']
}

Then call renderstatic before collectstatic:

$> ./manage.py renderstatic
$> ./manage.py collectstatic

If your root urls.py looks like this:

fromdjango.contribimportadminfromdjango.urlsimportpathfrom .viewsimportMyViewurlpatterns= [
path('admin/', admin.site.urls),
path('simple', MyView.as_view(), name='simple'),
path('simple/<int:arg1>', MyView.as_view(), name='simple'),
path('different/<int:arg1>/<str:arg2>', MyView.as_view(), name='different'),
]

So you can now fetch paths like this, in a way that is roughly API-equivalent to Django's reverse function:

import{URLResolver}from'/static/urls.js';consturls=newURLResolver();// /different/143/emmaurls.reverse('different',{kwargs: {'arg1': 143,'arg2': 'emma'}});// reverse also supports query parameters// /different/143/emma?intarg=0&listarg=A&listarg=B&listarg=Curls.reverse('different',{kwargs: {arg1: 143,arg2: 'emma'},query: {intarg: 0,listarg: ['A','B','C']}});

URLGenerationFailed Exceptions & Placeholders

If you encounter a URLGenerationFailed exception you most likely need to register a placeholder for the argument in question. A placeholder is just a string or object that can be coerced to a string that matches the regular expression for the argument:

fromrender_static.placeholdersimportregister_variable_placeholderapp_name='year_app'urlpatterns= [
re_path(r'^fetch/(?P<year>\d{4})/$', YearView.as_view(), name='fetch_year')
]
register_variable_placeholder('year', 2000, app_name=app_name)

Users should typically use a path instead of re_path and register their own custom converters when needed. Placeholders can be directly registered on the converter (and are then conveniently available to users of your app!):

fromdjango.urls.convertersimportregister_converterclassYearConverter:
regex='[0-9]{4}'placeholder=2000# this attribute is used by `url_to_js` to reverse pathsdefto_python(self, value):
returnint(value)
defto_url(self, value):
returnstr(value)
register_converter(YearConverter, 'year')
urlpatterns= [
path('fetch/<year:year>', YearView.as_view(), name='fetch_year')
]

Transpiling Enumerations

Say instead of the usual choices tuple you're using PEP 435 style python enumerations as model fields using django-enum and enum-properties. For example we might define a simple color enumeration like so:

fromdjango.dbimportmodelsfromdjango_enumimportEnumField, TextChoicesfromenum_propertiesimportp, sclassExampleModel(models.Model):
classColor(TextChoices, s('rgb'), s('hex', case_fold=True)):
# name value label rgb hexRED='R', 'Red', (1, 0, 0), 'ff0000'GREEN='G', 'Green', (0, 1, 0), '00ff00'BLUE='B', 'Blue', (0, 0, 1), '0000ff'color=EnumField(Color, null=True, default=None)

If we define an enum.js template that looks like this:


{% enums_to_js enums="examples.models.ExampleModel.Color" %}

It will contain a javascript class transpilation of the Color enum that looks like this:

classColor{staticRED=newColor("R","RED","Red",[1,0,0],"ff0000");staticGREEN=newColor("G","GREEN","Green",[0,1,0],"00ff00");staticBLUE=newColor("B","BLUE","Blue",[0,0,1],"0000ff");constructor(value,name,label,rgb,hex){this.value=value;this.name=name;this.label=label;this.rgb=rgb;this.hex=hex;}toString(){returnthis.value;}staticget(value){switch(value){case"R":
returnColor.RED;case"G":
returnColor.GREEN;case"B":
returnColor.BLUE;}thrownewTypeError(`No Color enumeration maps to value ${value}`);}static[Symbol.iterator](){return[Color.RED,Color.GREEN,Color.BLUE][Symbol.iterator]();}}

We can now use our enumeration like so:

Color.BLUE===Color.get('B');for(constcolorofColor){console.log(color);}

Transpiling Model Field Choices

You have an app with a model with a character field that has several valid choices defined in an enumeration type way, and you'd like to export those defines to JavaScript. You'd like to include a template for other's using your app to use to generate a defines.js file. Say your app structure looks like this::

.
└── examples
├── __init__.py
├── apps.py
├── defines.py
├── models.py
├── static_templates
│ └── examples
│ └── defines.js
└── urls.py

Your defines/model classes might look like this:

classExampleModel(Defines, models.Model):
DEFINE1='D1'DEFINE2='D2'DEFINE3='D3'DEFINES= (
(DEFINE1, 'Define 1'),
(DEFINE2, 'Define 2'),
(DEFINE3, 'Define 3')
)
define_field=models.CharField(choices=DEFINES, max_length=2)

And your defines.js template might look like this:

{% defines_to_js modules="examples.models" %}

If someone wanted to use your defines template to generate a JavaScript version of your Python class their settings file might look like this:

STATIC_TEMPLATES= {
'templates': [
'examples/defines.js'
]
}

And then of course they would call renderstatic before collectstatic:

$> ./manage.py renderstatic
$> ./manage.py collectstatic

This would create the following file::

.
└── examples
└── static
└── examples
└── defines.js

Which would look like this:

constdefines={ExampleModel: {DEFINE1: "D1",DEFINE2: "D2",DEFINE3: "D3",DEFINES: [["D1","Define 1"],["D2","Define 2"],["D3","Define 3"]]}};

About

Use Django's template engines to render static files at deployment or package time. Includes transpilers for extending Django's url reversal and enums to JavaScript.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

24 stars

Watchers

1 watching

Forks

Releases

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

License: MITPyPI versionPyPI pyversionsPyPI djversionsPyPI statusPyPI - TypesDocumentation StatusCode CovTest StatusLint StatusRuffPublished on Django PackagesOpenSSF Scorecard

django-render-static

Use Django's template engines to render static files that are collected during the collectstatic routine and likely served above Django at runtime. Files rendered by django-render-static are immediately available to participate in the normal static file collection pipeline.

For example, a frequently occurring pattern that violates the DRY principle is the presence of defines, or enum like structures in server side Python code that are simply replicated in client side JavaScript. Another example might be rebuilding Django URLs from arguments in a Single Page Application. Single-sourcing these structures by transpiling client side code from the server side code keeps the stack bone DRY.

django-render-static includes Python to Javascript transpilers for:

  • Django's reverse function (urls_to_js)
  • PEP 435 style Python enumerations (enums_to_js)
  • Plain data define-like structures in Python classes and modules (defines_to_js)

Transpilation is extremely flexible and may be customized by using override blocks or extending the provided transpilers.

django-render-static also formalizes the concept of a package-time or deployment-time static file rendering step. It piggybacks off the existing templating engines and configurations and should therefore be familiar to Django developers. It supports both standard Django templating and Jinja templates and allows contexts to be specified in python, json or YAML.

You can report bugs and discuss features on the issues page.

Contributions are encouraged!

Full documentation at read the docs.

Installation

  1. Clone django-render-static from GitHub or install a release off PyPI:
pip install django-render-static
  1. Add 'render_static' to your INSTALLED_APPS :
INSTALLED_APPS= [
'render_static',
]
  1. Add a STATIC_TEMPLATES configuration directive to your settings file:
STATIC_TEMPLATES= {
'templates' : [
('path/to/template':, {'context' {'variable': 'value'})
]
}
  1. Run renderstatic preceding every run of collectstatic :
$> manage.py renderstatic
$> manage.py collectstatic

Usage

Transpiling URL reversal

You'd like to be able to call something like reverse on path names from your client JavaScript code the same way you do from Python Django code.

Your settings file might look like:

STATIC_TEMPLATES={
'ENGINES': [{
'BACKEND': 'render_static.backends.StaticDjangoTemplates',
'OPTIONS': {
'loaders': [
('render_static.loaders.StaticLocMemLoader', {
'urls.js': '{% urls_to_js %}'
})
]
},
}],
'templates': ['urls.js']
}

Then call renderstatic before collectstatic:

$> ./manage.py renderstatic
$> ./manage.py collectstatic

If your root urls.py looks like this:

fromdjango.contribimportadminfromdjango.urlsimportpathfrom .viewsimportMyViewurlpatterns= [
path('admin/', admin.site.urls),
path('simple', MyView.as_view(), name='simple'),
path('simple/<int:arg1>', MyView.as_view(), name='simple'),
path('different/<int:arg1>/<str:arg2>', MyView.as_view(), name='different'),
]

So you can now fetch paths like this, in a way that is roughly API-equivalent to Django's reverse function:

import{URLResolver}from'/static/urls.js';consturls=newURLResolver();// /different/143/emmaurls.reverse('different',{kwargs: {'arg1': 143,'arg2': 'emma'}});// reverse also supports query parameters// /different/143/emma?intarg=0&listarg=A&listarg=B&listarg=Curls.reverse('different',{kwargs: {arg1: 143,arg2: 'emma'},query: {intarg: 0,listarg: ['A','B','C']}});

URLGenerationFailed Exceptions & Placeholders

If you encounter a URLGenerationFailed exception you most likely need to register a placeholder for the argument in question. A placeholder is just a string or object that can be coerced to a string that matches the regular expression for the argument:

fromrender_static.placeholdersimportregister_variable_placeholderapp_name='year_app'urlpatterns= [
re_path(r'^fetch/(?P<year>\d{4})/$', YearView.as_view(), name='fetch_year')
]
register_variable_placeholder('year', 2000, app_name=app_name)

Users should typically use a path instead of re_path and register their own custom converters when needed. Placeholders can be directly registered on the converter (and are then conveniently available to users of your app!):

fromdjango.urls.convertersimportregister_converterclassYearConverter:
regex='[0-9]{4}'placeholder=2000# this attribute is used by `url_to_js` to reverse pathsdefto_python(self, value):
returnint(value)
defto_url(self, value):
returnstr(value)
register_converter(YearConverter, 'year')
urlpatterns= [
path('fetch/<year:year>', YearView.as_view(), name='fetch_year')
]

Transpiling Enumerations

Say instead of the usual choices tuple you're using PEP 435 style python enumerations as model fields using django-enum and enum-properties. For example we might define a simple color enumeration like so:

fromdjango.dbimportmodelsfromdjango_enumimportEnumField, TextChoicesfromenum_propertiesimportp, sclassExampleModel(models.Model):
classColor(TextChoices, s('rgb'), s('hex', case_fold=True)):
# name value label rgb hexRED='R', 'Red', (1, 0, 0), 'ff0000'GREEN='G', 'Green', (0, 1, 0), '00ff00'BLUE='B', 'Blue', (0, 0, 1), '0000ff'color=EnumField(Color, null=True, default=None)

If we define an enum.js template that looks like this:


{% enums_to_js enums="examples.models.ExampleModel.Color" %}

It will contain a javascript class transpilation of the Color enum that looks like this:

classColor{staticRED=newColor("R","RED","Red",[1,0,0],"ff0000");staticGREEN=newColor("G","GREEN","Green",[0,1,0],"00ff00");staticBLUE=newColor("B","BLUE","Blue",[0,0,1],"0000ff");constructor(value,name,label,rgb,hex){this.value=value;this.name=name;this.label=label;this.rgb=rgb;this.hex=hex;}toString(){returnthis.value;}staticget(value){switch(value){case"R":
returnColor.RED;case"G":
returnColor.GREEN;case"B":
returnColor.BLUE;}thrownewTypeError(`No Color enumeration maps to value ${value}`);}static[Symbol.iterator](){return[Color.RED,Color.GREEN,Color.BLUE][Symbol.iterator]();}}

We can now use our enumeration like so:

Color.BLUE===Color.get('B');for(constcolorofColor){console.log(color);}

Transpiling Model Field Choices

You have an app with a model with a character field that has several valid choices defined in an enumeration type way, and you'd like to export those defines to JavaScript. You'd like to include a template for other's using your app to use to generate a defines.js file. Say your app structure looks like this::

.
└── examples
├── __init__.py
├── apps.py
├── defines.py
├── models.py
├── static_templates
│ └── examples
│ └── defines.js
└── urls.py

Your defines/model classes might look like this:

classExampleModel(Defines, models.Model):
DEFINE1='D1'DEFINE2='D2'DEFINE3='D3'DEFINES= (
(DEFINE1, 'Define 1'),
(DEFINE2, 'Define 2'),
(DEFINE3, 'Define 3')
)
define_field=models.CharField(choices=DEFINES, max_length=2)

And your defines.js template might look like this:

{% defines_to_js modules="examples.models" %}

If someone wanted to use your defines template to generate a JavaScript version of your Python class their settings file might look like this:

STATIC_TEMPLATES= {
'templates': [
'examples/defines.js'
]
}

And then of course they would call renderstatic before collectstatic:

$> ./manage.py renderstatic
$> ./manage.py collectstatic

This would create the following file::

.
└── examples
└── static
└── examples
└── defines.js

Which would look like this:

constdefines={ExampleModel: {DEFINE1: "D1",DEFINE2: "D2",DEFINE3: "D3",DEFINES: [["D1","Define 1"],["D2","Define 2"],["D3","Define 3"]]}};

About

Use Django's template engines to render static files at deployment or package time. Includes transpilers for extending Django's url reversal and enums to JavaScript.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

24 stars

Watchers

1 watching

Forks

Releases

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

License: MITPyPI versionPyPI pyversionsPyPI djversionsPyPI statusPyPI - TypesDocumentation StatusCode CovTest StatusLint StatusRuffPublished on Django PackagesOpenSSF Scorecard

django-render-static

Use Django's template engines to render static files that are collected during the collectstatic routine and likely served above Django at runtime. Files rendered by django-render-static are immediately available to participate in the normal static file collection pipeline.

For example, a frequently occurring pattern that violates the DRY principle is the presence of defines, or enum like structures in server side Python code that are simply replicated in client side JavaScript. Another example might be rebuilding Django URLs from arguments in a Single Page Application. Single-sourcing these structures by transpiling client side code from the server side code keeps the stack bone DRY.

django-render-static includes Python to Javascript transpilers for:

  • Django's reverse function (urls_to_js)
  • PEP 435 style Python enumerations (enums_to_js)
  • Plain data define-like structures in Python classes and modules (defines_to_js)

Transpilation is extremely flexible and may be customized by using override blocks or extending the provided transpilers.

django-render-static also formalizes the concept of a package-time or deployment-time static file rendering step. It piggybacks off the existing templating engines and configurations and should therefore be familiar to Django developers. It supports both standard Django templating and Jinja templates and allows contexts to be specified in python, json or YAML.

You can report bugs and discuss features on the issues page.

Contributions are encouraged!

Full documentation at read the docs.

Installation

  1. Clone django-render-static from GitHub or install a release off PyPI:
pip install django-render-static
  1. Add 'render_static' to your INSTALLED_APPS :
INSTALLED_APPS= [
'render_static',
]
  1. Add a STATIC_TEMPLATES configuration directive to your settings file:
STATIC_TEMPLATES= {
'templates' : [
('path/to/template':, {'context' {'variable': 'value'})
]
}
  1. Run renderstatic preceding every run of collectstatic :
$> manage.py renderstatic
$> manage.py collectstatic

Usage

Transpiling URL reversal

You'd like to be able to call something like reverse on path names from your client JavaScript code the same way you do from Python Django code.

Your settings file might look like:

STATIC_TEMPLATES={
'ENGINES': [{
'BACKEND': 'render_static.backends.StaticDjangoTemplates',
'OPTIONS': {
'loaders': [
('render_static.loaders.StaticLocMemLoader', {
'urls.js': '{% urls_to_js %}'
})
]
},
}],
'templates': ['urls.js']
}

Then call renderstatic before collectstatic:

$> ./manage.py renderstatic
$> ./manage.py collectstatic

If your root urls.py looks like this:

fromdjango.contribimportadminfromdjango.urlsimportpathfrom .viewsimportMyViewurlpatterns= [
path('admin/', admin.site.urls),
path('simple', MyView.as_view(), name='simple'),
path('simple/<int:arg1>', MyView.as_view(), name='simple'),
path('different/<int:arg1>/<str:arg2>', MyView.as_view(), name='different'),
]

So you can now fetch paths like this, in a way that is roughly API-equivalent to Django's reverse function:

import{URLResolver}from'/static/urls.js';consturls=newURLResolver();// /different/143/emmaurls.reverse('different',{kwargs: {'arg1': 143,'arg2': 'emma'}});// reverse also supports query parameters// /different/143/emma?intarg=0&listarg=A&listarg=B&listarg=Curls.reverse('different',{kwargs: {arg1: 143,arg2: 'emma'},query: {intarg: 0,listarg: ['A','B','C']}});

URLGenerationFailed Exceptions & Placeholders

If you encounter a URLGenerationFailed exception you most likely need to register a placeholder for the argument in question. A placeholder is just a string or object that can be coerced to a string that matches the regular expression for the argument:

fromrender_static.placeholdersimportregister_variable_placeholderapp_name='year_app'urlpatterns= [
re_path(r'^fetch/(?P<year>\d{4})/$', YearView.as_view(), name='fetch_year')
]
register_variable_placeholder('year', 2000, app_name=app_name)

Users should typically use a path instead of re_path and register their own custom converters when needed. Placeholders can be directly registered on the converter (and are then conveniently available to users of your app!):

fromdjango.urls.convertersimportregister_converterclassYearConverter:
regex='[0-9]{4}'placeholder=2000# this attribute is used by `url_to_js` to reverse pathsdefto_python(self, value):
returnint(value)
defto_url(self, value):
returnstr(value)
register_converter(YearConverter, 'year')
urlpatterns= [
path('fetch/<year:year>', YearView.as_view(), name='fetch_year')
]

Transpiling Enumerations

Say instead of the usual choices tuple you're using PEP 435 style python enumerations as model fields using django-enum and enum-properties. For example we might define a simple color enumeration like so:

fromdjango.dbimportmodelsfromdjango_enumimportEnumField, TextChoicesfromenum_propertiesimportp, sclassExampleModel(models.Model):
classColor(TextChoices, s('rgb'), s('hex', case_fold=True)):
# name value label rgb hexRED='R', 'Red', (1, 0, 0), 'ff0000'GREEN='G', 'Green', (0, 1, 0), '00ff00'BLUE='B', 'Blue', (0, 0, 1), '0000ff'color=EnumField(Color, null=True, default=None)

If we define an enum.js template that looks like this:


{% enums_to_js enums="examples.models.ExampleModel.Color" %}

It will contain a javascript class transpilation of the Color enum that looks like this:

classColor{staticRED=newColor("R","RED","Red",[1,0,0],"ff0000");staticGREEN=newColor("G","GREEN","Green",[0,1,0],"00ff00");staticBLUE=newColor("B","BLUE","Blue",[0,0,1],"0000ff");constructor(value,name,label,rgb,hex){this.value=value;this.name=name;this.label=label;this.rgb=rgb;this.hex=hex;}toString(){returnthis.value;}staticget(value){switch(value){case"R":
returnColor.RED;case"G":
returnColor.GREEN;case"B":
returnColor.BLUE;}thrownewTypeError(`No Color enumeration maps to value ${value}`);}static[Symbol.iterator](){return[Color.RED,Color.GREEN,Color.BLUE][Symbol.iterator]();}}

We can now use our enumeration like so:

Color.BLUE===Color.get('B');for(constcolorofColor){console.log(color);}

Transpiling Model Field Choices

You have an app with a model with a character field that has several valid choices defined in an enumeration type way, and you'd like to export those defines to JavaScript. You'd like to include a template for other's using your app to use to generate a defines.js file. Say your app structure looks like this::

.
└── examples
├── __init__.py
├── apps.py
├── defines.py
├── models.py
├── static_templates
│ └── examples
│ └── defines.js
└── urls.py

Your defines/model classes might look like this:

classExampleModel(Defines, models.Model):
DEFINE1='D1'DEFINE2='D2'DEFINE3='D3'DEFINES= (
(DEFINE1, 'Define 1'),
(DEFINE2, 'Define 2'),
(DEFINE3, 'Define 3')
)
define_field=models.CharField(choices=DEFINES, max_length=2)

And your defines.js template might look like this:

{% defines_to_js modules="examples.models" %}

If someone wanted to use your defines template to generate a JavaScript version of your Python class their settings file might look like this:

STATIC_TEMPLATES= {
'templates': [
'examples/defines.js'
]
}

And then of course they would call renderstatic before collectstatic:

$> ./manage.py renderstatic
$> ./manage.py collectstatic

This would create the following file::

.
└── examples
└── static
└── examples
└── defines.js

Which would look like this:

constdefines={ExampleModel: {DEFINE1: "D1",DEFINE2: "D2",DEFINE3: "D3",DEFINES: [["D1","Define 1"],["D2","Define 2"],["D3","Define 3"]]}};

About

Use Django's template engines to render static files at deployment or package time. Includes transpilers for extending Django's url reversal and enums to JavaScript.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

24 stars

Watchers

1 watching

Forks

Releases

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

License: MITPyPI versionPyPI pyversionsPyPI djversionsPyPI statusPyPI - TypesDocumentation StatusCode CovTest StatusLint StatusRuffPublished on Django PackagesOpenSSF Scorecard

django-render-static

Use Django's template engines to render static files that are collected during the collectstatic routine and likely served above Django at runtime. Files rendered by django-render-static are immediately available to participate in the normal static file collection pipeline.

For example, a frequently occurring pattern that violates the DRY principle is the presence of defines, or enum like structures in server side Python code that are simply replicated in client side JavaScript. Another example might be rebuilding Django URLs from arguments in a Single Page Application. Single-sourcing these structures by transpiling client side code from the server side code keeps the stack bone DRY.

django-render-static includes Python to Javascript transpilers for:

  • Django's reverse function (urls_to_js)
  • PEP 435 style Python enumerations (enums_to_js)
  • Plain data define-like structures in Python classes and modules (defines_to_js)

Transpilation is extremely flexible and may be customized by using override blocks or extending the provided transpilers.

django-render-static also formalizes the concept of a package-time or deployment-time static file rendering step. It piggybacks off the existing templating engines and configurations and should therefore be familiar to Django developers. It supports both standard Django templating and Jinja templates and allows contexts to be specified in python, json or YAML.

You can report bugs and discuss features on the issues page.

Contributions are encouraged!

Full documentation at read the docs.

Installation

  1. Clone django-render-static from GitHub or install a release off PyPI:
pip install django-render-static
  1. Add 'render_static' to your INSTALLED_APPS :
INSTALLED_APPS= [
'render_static',
]
  1. Add a STATIC_TEMPLATES configuration directive to your settings file:
STATIC_TEMPLATES= {
'templates' : [
('path/to/template':, {'context' {'variable': 'value'})
]
}
  1. Run renderstatic preceding every run of collectstatic :
$> manage.py renderstatic
$> manage.py collectstatic

Usage

Transpiling URL reversal

You'd like to be able to call something like reverse on path names from your client JavaScript code the same way you do from Python Django code.

Your settings file might look like:

STATIC_TEMPLATES={
'ENGINES': [{
'BACKEND': 'render_static.backends.StaticDjangoTemplates',
'OPTIONS': {
'loaders': [
('render_static.loaders.StaticLocMemLoader', {
'urls.js': '{% urls_to_js %}'
})
]
},
}],
'templates': ['urls.js']
}

Then call renderstatic before collectstatic:

$> ./manage.py renderstatic
$> ./manage.py collectstatic

If your root urls.py looks like this:

fromdjango.contribimportadminfromdjango.urlsimportpathfrom .viewsimportMyViewurlpatterns= [
path('admin/', admin.site.urls),
path('simple', MyView.as_view(), name='simple'),
path('simple/<int:arg1>', MyView.as_view(), name='simple'),
path('different/<int:arg1>/<str:arg2>', MyView.as_view(), name='different'),
]

So you can now fetch paths like this, in a way that is roughly API-equivalent to Django's reverse function:

import{URLResolver}from'/static/urls.js';consturls=newURLResolver();// /different/143/emmaurls.reverse('different',{kwargs: {'arg1': 143,'arg2': 'emma'}});// reverse also supports query parameters// /different/143/emma?intarg=0&listarg=A&listarg=B&listarg=Curls.reverse('different',{kwargs: {arg1: 143,arg2: 'emma'},query: {intarg: 0,listarg: ['A','B','C']}});

URLGenerationFailed Exceptions & Placeholders

If you encounter a URLGenerationFailed exception you most likely need to register a placeholder for the argument in question. A placeholder is just a string or object that can be coerced to a string that matches the regular expression for the argument:

fromrender_static.placeholdersimportregister_variable_placeholderapp_name='year_app'urlpatterns= [
re_path(r'^fetch/(?P<year>\d{4})/$', YearView.as_view(), name='fetch_year')
]
register_variable_placeholder('year', 2000, app_name=app_name)

Users should typically use a path instead of re_path and register their own custom converters when needed. Placeholders can be directly registered on the converter (and are then conveniently available to users of your app!):

fromdjango.urls.convertersimportregister_converterclassYearConverter:
regex='[0-9]{4}'placeholder=2000# this attribute is used by `url_to_js` to reverse pathsdefto_python(self, value):
returnint(value)
defto_url(self, value):
returnstr(value)
register_converter(YearConverter, 'year')
urlpatterns= [
path('fetch/<year:year>', YearView.as_view(), name='fetch_year')
]

Transpiling Enumerations

Say instead of the usual choices tuple you're using PEP 435 style python enumerations as model fields using django-enum and enum-properties. For example we might define a simple color enumeration like so:

fromdjango.dbimportmodelsfromdjango_enumimportEnumField, TextChoicesfromenum_propertiesimportp, sclassExampleModel(models.Model):
classColor(TextChoices, s('rgb'), s('hex', case_fold=True)):
# name value label rgb hexRED='R', 'Red', (1, 0, 0), 'ff0000'GREEN='G', 'Green', (0, 1, 0), '00ff00'BLUE='B', 'Blue', (0, 0, 1), '0000ff'color=EnumField(Color, null=True, default=None)

If we define an enum.js template that looks like this:


{% enums_to_js enums="examples.models.ExampleModel.Color" %}

It will contain a javascript class transpilation of the Color enum that looks like this:

classColor{staticRED=newColor("R","RED","Red",[1,0,0],"ff0000");staticGREEN=newColor("G","GREEN","Green",[0,1,0],"00ff00");staticBLUE=newColor("B","BLUE","Blue",[0,0,1],"0000ff");constructor(value,name,label,rgb,hex){this.value=value;this.name=name;this.label=label;this.rgb=rgb;this.hex=hex;}toString(){returnthis.value;}staticget(value){switch(value){case"R":
returnColor.RED;case"G":
returnColor.GREEN;case"B":
returnColor.BLUE;}thrownewTypeError(`No Color enumeration maps to value ${value}`);}static[Symbol.iterator](){return[Color.RED,Color.GREEN,Color.BLUE][Symbol.iterator]();}}

We can now use our enumeration like so:

Color.BLUE===Color.get('B');for(constcolorofColor){console.log(color);}

Transpiling Model Field Choices

You have an app with a model with a character field that has several valid choices defined in an enumeration type way, and you'd like to export those defines to JavaScript. You'd like to include a template for other's using your app to use to generate a defines.js file. Say your app structure looks like this::

.
└── examples
├── __init__.py
├── apps.py
├── defines.py
├── models.py
├── static_templates
│ └── examples
│ └── defines.js
└── urls.py

Your defines/model classes might look like this:

classExampleModel(Defines, models.Model):
DEFINE1='D1'DEFINE2='D2'DEFINE3='D3'DEFINES= (
(DEFINE1, 'Define 1'),
(DEFINE2, 'Define 2'),
(DEFINE3, 'Define 3')
)
define_field=models.CharField(choices=DEFINES, max_length=2)

And your defines.js template might look like this:

{% defines_to_js modules="examples.models" %}

If someone wanted to use your defines template to generate a JavaScript version of your Python class their settings file might look like this:

STATIC_TEMPLATES= {
'templates': [
'examples/defines.js'
]
}

And then of course they would call renderstatic before collectstatic:

$> ./manage.py renderstatic
$> ./manage.py collectstatic

This would create the following file::

.
└── examples
└── static
└── examples
└── defines.js

Which would look like this:

constdefines={ExampleModel: {DEFINE1: "D1",DEFINE2: "D2",DEFINE3: "D3",DEFINES: [["D1","Define 1"],["D2","Define 2"],["D3","Define 3"]]}};

About

Use Django's template engines to render static files at deployment or package time. Includes transpilers for extending Django's url reversal and enums to JavaScript.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

24 stars

Watchers

1 watching

Forks

Releases

Used by

Contributors

Languages