mirror of
https://github.com/jazzband/django-dbtemplates.git
synced 2026-03-17 06:30:29 +00:00
Compare commits
No commits in common. "master" and "0.7.2" have entirely different histories.
89 changed files with 1592 additions and 2849 deletions
|
|
@ -1,6 +0,0 @@
|
|||
[run]
|
||||
source = dbtemplates
|
||||
branch = 1
|
||||
|
||||
[report]
|
||||
omit = *tests*,*/migrations/*,test_*
|
||||
40
.github/workflows/release.yml
vendored
40
.github/workflows/release.yml
vendored
|
|
@ -1,40 +0,0 @@
|
|||
name: Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '*'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
if: github.repository == 'jazzband/django-dbtemplates'
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.10"
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install -U pip
|
||||
python -m pip install -U setuptools twine wheel
|
||||
|
||||
- name: Build package
|
||||
run: |
|
||||
python setup.py --version
|
||||
python setup.py sdist --format=gztar bdist_wheel
|
||||
twine check dist/*
|
||||
|
||||
- name: Upload packages to Jazzband
|
||||
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
|
||||
uses: pypa/gh-action-pypi-publish@release/v1
|
||||
with:
|
||||
user: jazzband
|
||||
password: ${{ secrets.JAZZBAND_RELEASE_KEY }}
|
||||
repository_url: https://jazzband.co/projects/django-dbtemplates/upload
|
||||
48
.github/workflows/test.yml
vendored
48
.github/workflows/test.yml
vendored
|
|
@ -1,48 +0,0 @@
|
|||
name: Test
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
max-parallel: 5
|
||||
matrix:
|
||||
python-version: ['3.8', '3.9', '3.10', '3.11', '3.13']
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
|
||||
- name: Get pip cache dir
|
||||
id: pip-cache
|
||||
run: |
|
||||
echo "::set-output name=dir::$(pip cache dir)"
|
||||
|
||||
- name: Cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{ steps.pip-cache.outputs.dir }}
|
||||
key:
|
||||
${{ matrix.python-version }}-v1-${{ hashFiles('**/setup.py') }}-${{ hashFiles('**/tox.ini') }}
|
||||
restore-keys: |
|
||||
${{ matrix.python-version }}-v1-
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
python -m pip install --upgrade tox tox-gh-actions
|
||||
|
||||
- name: Tox tests
|
||||
run: |
|
||||
tox -v
|
||||
|
||||
- name: Upload coverage
|
||||
uses: codecov/codecov-action@v2
|
||||
with:
|
||||
name: Python ${{ matrix.python-version }}
|
||||
10
.gitignore
vendored
10
.gitignore
vendored
|
|
@ -1,14 +1,6 @@
|
|||
.*
|
||||
!.gitignore
|
||||
!.coveragerc
|
||||
*.pyc
|
||||
.*.swp
|
||||
MANIFEST
|
||||
build
|
||||
dist
|
||||
*.egg-info
|
||||
docs/_build
|
||||
.tox/
|
||||
*.egg/
|
||||
.coverage
|
||||
coverage.xml
|
||||
*.egg-info
|
||||
9
.hgignore
Normal file
9
.hgignore
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
syntax: glob
|
||||
*.pyc
|
||||
.*.swp
|
||||
MANIFEST
|
||||
build
|
||||
dist
|
||||
django_dbtemplates.egg-info/
|
||||
example/example.db
|
||||
docs/_build
|
||||
24
.hgtags
Normal file
24
.hgtags
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
bd537cd8beba30f1a26328e02126d3d1b14ebf8f 0.2.5
|
||||
1b426859f05b8a003411964883ed5d42ec6c1b01 0.3.0
|
||||
97da228cc698bfae05f60a68ec978030722b0777 0.3.1
|
||||
50c69325d3758d2e82541b13be2794ebbe9ee449 0.4.0
|
||||
d35a41ea96d3604a3c2654590c5c76b8865c4251 0.4.1
|
||||
a4bd56a7c2ea4c6f16a726e47bb185101934fe08 0.4.2
|
||||
447247c1ce1fbc77ac79c5855630af306f4f8c42 0.4.3
|
||||
5b2e4f7fc267daf71325991e913f98e6f96259bb 0.4.4
|
||||
ea4d636f3459ddbb51d87e921cf23f87e41d658d 0.4.5
|
||||
9a30f34bc5b07376ed6752eed94d9d58e791fbac 0.4.6
|
||||
9dc2a0e48494d6a354f5ca25db31638cede4bae4 0.4.7
|
||||
a3be97628ed8633e2fe232e6680474e7fd3e9fea 0.5.0
|
||||
bf3db2fe192d4a02bf531e61e23df342c36d6b1b 0.5.1
|
||||
67a86cf9f7c8ac8d9da855c13abbef2547033cce 0.5.2
|
||||
6967bbbee378f470e4b1df02b57112dd050d424b 0.5.3
|
||||
5965315c03c1a8c1cfb34752cca3802d68156e27 0.5.4
|
||||
4109e0db4340042cb85ea8a7d2b6ce37245738c6 0.5.5
|
||||
ade167225d06cb6888ea8bfa84e7d020590171c6 0.5.6
|
||||
dff01be9c8af328f8fcbc2fc97edcbe8d97840e2 0.5.7
|
||||
f8f7eaf275c5e8ac52174642265af55691abef7c 0.5.8
|
||||
4b36382cdfd756f45f81b0d042aaf331c3eabe30 0.6.0
|
||||
0ac352fec2c2a03ac801ff0c40f0649ef16e1f64 0.6.1
|
||||
34a0511928629872ce8cc5f94c6bed65f82ac343 0.7.0
|
||||
74c22fa8c4a64ea37f9b6b2515a4162b8b8b1a2a 0.7.1
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
repos:
|
||||
- repo: https://github.com/asottile/pyupgrade
|
||||
rev: v2.34.0
|
||||
hooks:
|
||||
- id: pyupgrade
|
||||
args: [--py37-plus]
|
||||
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.3.0
|
||||
hooks:
|
||||
- id: check-merge-conflict
|
||||
- id: check-yaml
|
||||
|
||||
ci:
|
||||
autoupdate_schedule: quarterly
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
# .readthedocs.yaml
|
||||
# Read the Docs configuration file
|
||||
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
|
||||
|
||||
# Required
|
||||
version: 2
|
||||
|
||||
# Set the version of Python and other tools you might need
|
||||
build:
|
||||
os: ubuntu-20.04
|
||||
tools:
|
||||
python: "3.9"
|
||||
|
||||
# Build documentation in the docs/ directory with Sphinx
|
||||
sphinx:
|
||||
configuration: docs/conf.py
|
||||
|
||||
# If using Sphinx, optionally build your docs in additional formats such as PDF
|
||||
formats:
|
||||
- pdf
|
||||
|
||||
# Optionally declare the Python requirements required to build your docs
|
||||
python:
|
||||
install:
|
||||
- requirements: requirements/docs.txt
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
[django-dbtemplates.main]
|
||||
file_filter = dbtemplates/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_file = dbtemplates/locale/en/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
|
||||
[main]
|
||||
host = https://www.transifex.com
|
||||
18
AUTHORS
18
AUTHORS
|
|
@ -1,18 +0,0 @@
|
|||
Alen Mujezinovic
|
||||
Alex Gaynor
|
||||
Alex Kamedov
|
||||
Alexander Artemenko
|
||||
Arne Brodowski
|
||||
David Paccoud
|
||||
Diego Búrigo Zacarão
|
||||
Dmitry Falk
|
||||
Jannis Leidel
|
||||
Jure Cuhalev
|
||||
Jason Mayfield
|
||||
Kevin Mooney
|
||||
Mark Stahler
|
||||
Matt Dorn
|
||||
Oliver George
|
||||
Selwin Ong
|
||||
Stephan Peijnik <spe@anexia.at>, ANEXIA Internetdienstleistungs GmbH, http://www.anexia.at/
|
||||
Zhang Kun
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
# Code of Conduct
|
||||
|
||||
As contributors and maintainers of the Jazzband projects, and in the interest of
|
||||
fostering an open and welcoming community, we pledge to respect all people who
|
||||
contribute through reporting issues, posting feature requests, updating documentation,
|
||||
submitting pull requests or patches, and other activities.
|
||||
|
||||
We are committed to making participation in the Jazzband a harassment-free experience
|
||||
for everyone, regardless of the level of experience, gender, gender identity and
|
||||
expression, sexual orientation, disability, personal appearance, body size, race,
|
||||
ethnicity, age, religion, or nationality.
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
- The use of sexualized language or imagery
|
||||
- Personal attacks
|
||||
- Trolling or insulting/derogatory comments
|
||||
- Public or private harassment
|
||||
- Publishing other's private information, such as physical or electronic addresses,
|
||||
without explicit permission
|
||||
- Other unethical or unprofessional conduct
|
||||
|
||||
The Jazzband roadies have the right and responsibility to remove, edit, or reject
|
||||
comments, commits, code, wiki edits, issues, and other contributions that are not
|
||||
aligned to this Code of Conduct, or to ban temporarily or permanently any contributor
|
||||
for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
|
||||
|
||||
By adopting this Code of Conduct, the roadies commit themselves to fairly and
|
||||
consistently applying these principles to every aspect of managing the jazzband
|
||||
projects. Roadies who do not follow or enforce the Code of Conduct may be permanently
|
||||
removed from the Jazzband roadies.
|
||||
|
||||
This code of conduct applies both within project spaces and in public spaces when an
|
||||
individual is representing the project or its community.
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by
|
||||
contacting the roadies at `roadies@jazzband.co`. All complaints will be reviewed and
|
||||
investigated and will result in a response that is deemed necessary and appropriate to
|
||||
the circumstances. Roadies are obligated to maintain confidentiality with regard to the
|
||||
reporter of an incident.
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version
|
||||
1.3.0, available at [https://contributor-covenant.org/version/1/3/0/][version]
|
||||
|
||||
[homepage]: https://contributor-covenant.org
|
||||
[version]: https://contributor-covenant.org/version/1/3/0/
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
[](https://jazzband.co/)
|
||||
|
||||
This is a [Jazzband](https://jazzband.co/) project. By contributing you agree to abide by the [Contributor Code of Conduct](https://jazzband.co/docs/conduct) and follow the [guidelines](https://jazzband.co/docs/guidelines).
|
||||
17
INSTALL
Normal file
17
INSTALL
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
To install it, run the following command inside this directory:
|
||||
|
||||
python setup.py install
|
||||
|
||||
Or if you'd prefer you can simply place the included ``dbtemplates``
|
||||
directory somewhere on your Python path, or symlink to it from
|
||||
somewhere on your Python path; this is useful if you're working from a
|
||||
Subversion checkout. Since ``dbtemplates`` is registered in the
|
||||
Python Package Index you can also run ``easy_install django-dbtemplates``
|
||||
or ``pip install django-dbtemplates`` optionally.
|
||||
|
||||
Note that this application requires Python 2.3 or later, and a recent
|
||||
Subversion checkout of Django. You can obtain Python from
|
||||
http://www.python.org/ and Django from http://www.djangoproject.com/.
|
||||
|
||||
This install notice was bluntly stolen from James Bennett's registration
|
||||
package, http://www.bitbucket.org/ubernostrum/django-registration/
|
||||
2
LICENSE
2
LICENSE
|
|
@ -1,4 +1,4 @@
|
|||
Copyright (c) 2007-2019, Jannis Leidel and contributors
|
||||
Copyright (c) 2007-2010, Jannis Leidel and contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
include LICENSE AUTHORS README.rst MANIFEST.in tox.ini .coveragerc CONTRIBUTING.md
|
||||
include INSTALL
|
||||
include LICENSE
|
||||
include README.rst
|
||||
include MANIFEST.in
|
||||
recursive-include docs *.txt
|
||||
recursive-include dbtemplates/locale *
|
||||
recursive-include dbtemplates/static/dbtemplates *.css *.js
|
||||
recursive-include dbtemplates/media/dbtemplates *.css *.js
|
||||
|
|
|
|||
37
README.rst
37
README.rst
|
|
@ -1,30 +1,15 @@
|
|||
django-dbtemplates
|
||||
==================
|
||||
===================================
|
||||
Database template loader for Django
|
||||
===================================
|
||||
|
||||
.. image:: https://jazzband.co/static/img/badge.svg
|
||||
:alt: Jazzband
|
||||
:target: https://jazzband.co/
|
||||
``dbtemplates`` is a Django app that comes with to parts: It allows you to
|
||||
create templates that are saved in your database, and it provides a so called
|
||||
`template loader`_, a function that enables Django to find the templates you
|
||||
created in the database.
|
||||
|
||||
.. image:: https://github.com/jazzband/django-dbtemplates/workflows/Test/badge.svg
|
||||
:target: https://github.com/jazzband/django-dbtemplates/actions
|
||||
It also includes a extensible caching mechanism and supports version control
|
||||
of the templates saved in the database.
|
||||
|
||||
.. image:: https://codecov.io/github/jazzband/django-dbtemplates/coverage.svg?branch=master
|
||||
:alt: Codecov
|
||||
:target: https://codecov.io/github/jazzband/django-dbtemplates?branch=master
|
||||
Please see ``docs/overview.txt`` for more details.
|
||||
|
||||
``dbtemplates`` is a Django app that consists of two parts:
|
||||
|
||||
1. It allows you to store templates in your database
|
||||
2. It provides `template loader`_ that enables Django to load the
|
||||
templates from the database
|
||||
|
||||
It also features optional support for versioned storage and django-admin
|
||||
command, integrates with Django's caching system and the admin actions.
|
||||
|
||||
Please see https://django-dbtemplates.readthedocs.io/ for more details.
|
||||
|
||||
The source code and issue tracker can be found on Github:
|
||||
|
||||
https://github.com/jazzband/django-dbtemplates
|
||||
|
||||
.. _template loader: http://docs.djangoproject.com/en/dev/ref/templates/api/#loader-types
|
||||
.. _template loader: http://docs.djangoproject.com/en/dev/ref/templates/api/#loader-types
|
||||
|
|
@ -1,3 +1 @@
|
|||
import importlib.metadata
|
||||
|
||||
__version__ = importlib.metadata.version("django-dbtemplates")
|
||||
__version__ = "0.7.2"
|
||||
|
|
|
|||
|
|
@ -1,44 +1,35 @@
|
|||
import posixpath
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
from django.contrib import admin
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.utils.translation import ngettext
|
||||
from django.utils.translation import ungettext, ugettext_lazy as _
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from dbtemplates.conf import settings
|
||||
from dbtemplates.models import Template, add_template_to_cache, remove_cached_template
|
||||
from dbtemplates.utils.template import check_template_syntax
|
||||
from dbtemplates.settings import MEDIA_PREFIX, USE_REVERSION, USE_CODEMIRROR
|
||||
from dbtemplates.models import Template, backend, remove_cached_template, \
|
||||
add_template_to_cache
|
||||
|
||||
# Check if either django-reversion-compare or django-reversion is installed and
|
||||
# use reversion_compare's CompareVersionAdmin or reversion's VersionAdmin as
|
||||
# the base admin class if yes
|
||||
if settings.DBTEMPLATES_USE_REVERSION_COMPARE:
|
||||
from reversion_compare.admin import CompareVersionAdmin \
|
||||
as TemplateModelAdmin
|
||||
elif settings.DBTEMPLATES_USE_REVERSION:
|
||||
# Check if django-reversion is installed and use reversions' VersionAdmin
|
||||
# as the base admin class if yes
|
||||
if USE_REVERSION:
|
||||
from reversion.admin import VersionAdmin as TemplateModelAdmin
|
||||
else:
|
||||
from django.contrib.admin import ModelAdmin as TemplateModelAdmin # noqa
|
||||
|
||||
from django.contrib.admin import ModelAdmin as TemplateModelAdmin
|
||||
|
||||
class CodeMirrorTextArea(forms.Textarea):
|
||||
|
||||
"""
|
||||
A custom widget for the CodeMirror browser editor to be used with the
|
||||
A custom widget for the CodeMirror browser editor to be used with the
|
||||
content field of the Template model.
|
||||
"""
|
||||
class Media:
|
||||
css = dict(screen=[posixpath.join(
|
||||
settings.DBTEMPLATES_MEDIA_PREFIX, 'css/editor.css')])
|
||||
js = [posixpath.join(settings.DBTEMPLATES_MEDIA_PREFIX,
|
||||
'js/codemirror.js')]
|
||||
css = dict(screen=[posixpath.join(MEDIA_PREFIX, 'css/editor.css')])
|
||||
js = [posixpath.join(MEDIA_PREFIX, 'js/codemirror.js')]
|
||||
|
||||
def render(self, name, value, attrs=None, renderer=None):
|
||||
def render(self, name, value, attrs=None):
|
||||
result = []
|
||||
result.append(
|
||||
super().render(name, value, attrs))
|
||||
result.append("""
|
||||
super(CodeMirrorTextArea, self).render(name, value, attrs))
|
||||
result.append(u"""
|
||||
<script type="text/javascript">
|
||||
var editor = CodeMirror.fromTextArea('id_%(name)s', {
|
||||
path: "%(media_prefix)sjs/",
|
||||
|
|
@ -51,53 +42,31 @@ class CodeMirrorTextArea(forms.Textarea):
|
|||
lineNumbers: true
|
||||
});
|
||||
</script>
|
||||
""" % dict(media_prefix=settings.DBTEMPLATES_MEDIA_PREFIX, name=name))
|
||||
return mark_safe("".join(result))
|
||||
""" % dict(media_prefix=MEDIA_PREFIX, name=name))
|
||||
return mark_safe(u"".join(result))
|
||||
|
||||
|
||||
if settings.DBTEMPLATES_USE_CODEMIRROR:
|
||||
if USE_CODEMIRROR:
|
||||
TemplateContentTextArea = CodeMirrorTextArea
|
||||
else:
|
||||
TemplateContentTextArea = forms.Textarea
|
||||
|
||||
if settings.DBTEMPLATES_AUTO_POPULATE_CONTENT:
|
||||
content_help_text = _("Leaving this empty causes Django to look for a "
|
||||
"template with the given name and populate this "
|
||||
"field with its content.")
|
||||
else:
|
||||
content_help_text = ""
|
||||
|
||||
if settings.DBTEMPLATES_USE_CODEMIRROR and settings.DBTEMPLATES_USE_TINYMCE:
|
||||
raise ImproperlyConfigured("You may use either CodeMirror or TinyMCE "
|
||||
"with dbtemplates, not both. Please disable "
|
||||
"one of them.")
|
||||
|
||||
if settings.DBTEMPLATES_USE_TINYMCE:
|
||||
from tinymce.widgets import AdminTinyMCE
|
||||
TemplateContentTextArea = AdminTinyMCE
|
||||
elif settings.DBTEMPLATES_USE_REDACTOR:
|
||||
from redactor.widgets import RedactorEditor
|
||||
TemplateContentTextArea = RedactorEditor
|
||||
|
||||
|
||||
class TemplateAdminForm(forms.ModelForm):
|
||||
|
||||
"""
|
||||
Custom AdminForm to make the content textarea wider.
|
||||
"""
|
||||
content = forms.CharField(
|
||||
widget=TemplateContentTextArea(attrs={'rows': '24'}),
|
||||
help_text=content_help_text, required=False)
|
||||
widget=TemplateContentTextArea({'rows': '24'}),
|
||||
help_text=_("Leaving this empty causes Django to look for a template "
|
||||
"with the given name and populate this field with its content."),
|
||||
required=False)
|
||||
|
||||
class Meta:
|
||||
model = Template
|
||||
fields = ('name', 'content', 'sites', 'creation_date', 'last_changed')
|
||||
fields = "__all__"
|
||||
|
||||
|
||||
class TemplateAdmin(TemplateModelAdmin):
|
||||
form = TemplateAdminForm
|
||||
readonly_fields = ['creation_date', 'last_changed']
|
||||
fieldsets = (
|
||||
(None, {
|
||||
'fields': ('name', 'content'),
|
||||
|
|
@ -105,69 +74,47 @@ class TemplateAdmin(TemplateModelAdmin):
|
|||
}),
|
||||
(_('Advanced'), {
|
||||
'fields': (('sites'),),
|
||||
'classes': ('collapse',),
|
||||
}),
|
||||
(_('Date/time'), {
|
||||
'fields': (('creation_date', 'last_changed'),),
|
||||
'classes': ('collapse',),
|
||||
}),
|
||||
)
|
||||
filter_horizontal = ('sites',)
|
||||
list_display = ('name', 'creation_date', 'last_changed', 'site_list')
|
||||
list_filter = ('sites',)
|
||||
save_as = True
|
||||
search_fields = ('name', 'content')
|
||||
actions = ['invalidate_cache', 'repopulate_cache', 'check_syntax']
|
||||
if backend:
|
||||
actions = ['invalidate_cache', 'repopulate_cache']
|
||||
|
||||
def invalidate_cache(self, request, queryset):
|
||||
if not backend:
|
||||
self.message_user(request, ("There is no active cache backend."))
|
||||
return
|
||||
for template in queryset:
|
||||
remove_cached_template(template)
|
||||
count = queryset.count()
|
||||
message = ngettext(
|
||||
message = ungettext(
|
||||
"Cache of one template successfully invalidated.",
|
||||
"Cache of %(count)d templates successfully invalidated.",
|
||||
count)
|
||||
self.message_user(request, message % {'count': count})
|
||||
invalidate_cache.short_description = _("Invalidate cache of "
|
||||
"selected templates")
|
||||
len(queryset))
|
||||
self.message_user(request, message % {'count': len(queryset)})
|
||||
invalidate_cache.short_description = _("Invalidate cache of selected templates")
|
||||
|
||||
def repopulate_cache(self, request, queryset):
|
||||
if not backend:
|
||||
self.message_user(request, ("There is no active cache backend."))
|
||||
return
|
||||
for template in queryset:
|
||||
add_template_to_cache(template)
|
||||
count = queryset.count()
|
||||
message = ngettext(
|
||||
message = ungettext(
|
||||
"Cache successfully repopulated with one template.",
|
||||
"Cache successfully repopulated with %(count)d templates.",
|
||||
count)
|
||||
self.message_user(request, message % {'count': count})
|
||||
repopulate_cache.short_description = _("Repopulate cache with "
|
||||
"selected templates")
|
||||
|
||||
def check_syntax(self, request, queryset):
|
||||
errors = []
|
||||
for template in queryset:
|
||||
valid, error = check_template_syntax(template)
|
||||
if not valid:
|
||||
errors.append(f'{template.name}: {error}')
|
||||
if errors:
|
||||
count = len(errors)
|
||||
message = ngettext(
|
||||
"Template syntax check FAILED for %(names)s.",
|
||||
"Template syntax check FAILED for "
|
||||
"%(count)d templates: %(names)s.",
|
||||
count)
|
||||
self.message_user(request, message %
|
||||
{'count': count, 'names': ', '.join(errors)})
|
||||
else:
|
||||
count = queryset.count()
|
||||
message = ngettext(
|
||||
"Template syntax OK.",
|
||||
"Template syntax OK for %(count)d templates.", count)
|
||||
self.message_user(request, message % {'count': count})
|
||||
check_syntax.short_description = _("Check template syntax")
|
||||
len(queryset))
|
||||
self.message_user(request, message % {'count': len(queryset)})
|
||||
repopulate_cache.short_description = _("Repopulate cache with selected templates")
|
||||
|
||||
def site_list(self, template):
|
||||
return ", ".join([site.name for site in template.sites.all()])
|
||||
return ", ".join([site.name for site in template.sites.all()])
|
||||
site_list.short_description = _('sites')
|
||||
|
||||
|
||||
admin.site.register(Template, TemplateAdmin)
|
||||
|
|
|
|||
|
|
@ -1,9 +0,0 @@
|
|||
from django.apps import AppConfig
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
class DBTemplatesConfig(AppConfig):
|
||||
name = 'dbtemplates'
|
||||
verbose_name = _('Database templates')
|
||||
|
||||
default_auto_field = 'django.db.models.AutoField'
|
||||
102
dbtemplates/cache.py
Normal file
102
dbtemplates/cache.py
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
import os
|
||||
from django.conf import settings
|
||||
from django.core.cache import cache
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.utils.encoding import force_unicode
|
||||
|
||||
class BaseCacheBackend(object):
|
||||
"""
|
||||
Base class for custom cache backend of dbtemplates to be used while
|
||||
subclassing.
|
||||
|
||||
Set DBTEMPLATES_CACHE_BACKEND setting to the Python path to that subclass.
|
||||
"""
|
||||
def _site(self):
|
||||
from django.contrib.sites.models import Site
|
||||
return Site.objects.get_current()
|
||||
site = property(_site)
|
||||
|
||||
def load(self, name):
|
||||
"""
|
||||
Loads a template from the cache with the given name.
|
||||
"""
|
||||
raise NotImplemented
|
||||
|
||||
def save(self, name, content):
|
||||
"""
|
||||
Saves the given template content with the given name in the cache.
|
||||
"""
|
||||
raise NotImplemented
|
||||
|
||||
def remove(self, name):
|
||||
"""
|
||||
Removes the template with the given name from the cache.
|
||||
"""
|
||||
raise NotImplemented
|
||||
|
||||
class DjangoCacheBackend(BaseCacheBackend):
|
||||
"""
|
||||
A cache backend that uses Django's cache mechanism.
|
||||
"""
|
||||
def _cache_key(self, name):
|
||||
return 'dbtemplates::%s::%s' % (name, self.site.pk)
|
||||
|
||||
def load(self, name):
|
||||
cache_key = self._cache_key(name)
|
||||
return cache.get(cache_key)
|
||||
|
||||
def save(self, name, content):
|
||||
cache_key = self._cache_key(name)
|
||||
cache.set(cache_key, content)
|
||||
|
||||
def remove(self, name):
|
||||
cache_key = self._cache_key(name)
|
||||
cache.delete(cache_key)
|
||||
|
||||
class FileSystemBackend(BaseCacheBackend):
|
||||
"""
|
||||
A cache backend that uses simple files to hold the template cache.
|
||||
"""
|
||||
def __init__(self):
|
||||
try:
|
||||
self.cache_dir = getattr(settings, 'DBTEMPLATES_CACHE_DIR', None)
|
||||
self.cache_dir = os.path.normpath(self.cache_dir)
|
||||
if not os.path.isdir(self.cache_dir):
|
||||
pass
|
||||
except:
|
||||
raise ImproperlyConfigured(
|
||||
"You're using the dbtemplates file system cache backend "
|
||||
"without having set the DBTEMPLATES_CACHE_DIR setting to a "
|
||||
"valid value. Make sure the directory exists and is writeable "
|
||||
"for the user your Django instance is running with."
|
||||
)
|
||||
super(FileSystemBackend, self).__init__()
|
||||
|
||||
def _filepath(self, name):
|
||||
return os.path.join(self.cache_dir, self.site.domain, name)
|
||||
|
||||
def load(self, name):
|
||||
try:
|
||||
filepath = self._filepath(name)
|
||||
return open(filepath).read().decode('utf-8')
|
||||
except:
|
||||
return None
|
||||
|
||||
def save(self, name, content, retry=False):
|
||||
try:
|
||||
filepath = self._filepath(name)
|
||||
dirname = os.path.dirname(filepath)
|
||||
if not os.path.exists(dirname):
|
||||
os.makedirs(dirname)
|
||||
cache_file = open(filepath, 'w')
|
||||
cache_file.write(force_unicode(content).encode('utf-8'))
|
||||
cache_file.close()
|
||||
except Exception:
|
||||
raise
|
||||
|
||||
def remove(self, name):
|
||||
try:
|
||||
filepath = self._filepath(name)
|
||||
os.remove(filepath)
|
||||
except:
|
||||
pass
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
import posixpath
|
||||
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.conf import settings
|
||||
|
||||
from appconf import AppConf
|
||||
|
||||
|
||||
class DbTemplatesConf(AppConf):
|
||||
USE_CODEMIRROR = False
|
||||
USE_REVERSION = False
|
||||
USE_REVERSION_COMPARE = False
|
||||
USE_TINYMCE = False
|
||||
USE_REDACTOR = False
|
||||
ADD_DEFAULT_SITE = True
|
||||
AUTO_POPULATE_CONTENT = True
|
||||
MEDIA_PREFIX = None
|
||||
CACHE_BACKEND = None
|
||||
|
||||
def configure_media_prefix(self, value):
|
||||
if value is None:
|
||||
base_url = getattr(settings, "STATIC_URL", None)
|
||||
if base_url is None:
|
||||
base_url = settings.MEDIA_URL
|
||||
value = posixpath.join(base_url, "dbtemplates/")
|
||||
return value
|
||||
|
||||
def configure_cache_backend(self, value):
|
||||
# If we are on Django 1.3 AND using the new CACHES setting..
|
||||
if hasattr(settings, "CACHES"):
|
||||
if "dbtemplates" in settings.CACHES:
|
||||
return "dbtemplates"
|
||||
else:
|
||||
return "default"
|
||||
if isinstance(value, str) and value.startswith("dbtemplates."):
|
||||
raise ImproperlyConfigured("Please upgrade to one of the "
|
||||
"supported backends as defined "
|
||||
"in the Django docs.")
|
||||
return value
|
||||
|
||||
def configure_use_reversion(self, value):
|
||||
if value and 'reversion' not in settings.INSTALLED_APPS:
|
||||
raise ImproperlyConfigured("Please add 'reversion' to your "
|
||||
"INSTALLED_APPS setting to make "
|
||||
"use of it in dbtemplates.")
|
||||
return value
|
||||
|
||||
def configure_use_reversion_compare(self, value):
|
||||
if value and 'reversion_compare' not in settings.INSTALLED_APPS:
|
||||
raise ImproperlyConfigured("Please add 'reversion_compare' to your"
|
||||
" INSTALLED_APPS setting to make "
|
||||
"use of it in dbtemplates.")
|
||||
return value
|
||||
|
||||
def configure_use_tinymce(self, value):
|
||||
if value and 'tinymce' not in settings.INSTALLED_APPS:
|
||||
raise ImproperlyConfigured("Please add 'tinymce' to your "
|
||||
"INSTALLED_APPS setting to make "
|
||||
"use of it in dbtemplates.")
|
||||
return value
|
||||
|
||||
def configure_use_redactor(self, value):
|
||||
if value and 'redactor' not in settings.INSTALLED_APPS:
|
||||
raise ImproperlyConfigured("Please add 'redactor' to your "
|
||||
"INSTALLED_APPS setting to make "
|
||||
"use of it in dbtemplates.")
|
||||
return value
|
||||
|
|
@ -1,14 +1,11 @@
|
|||
from django import VERSION
|
||||
from django.conf import settings
|
||||
from django.contrib.sites.models import Site
|
||||
from django.db import router
|
||||
from django.template import Origin, TemplateDoesNotExist
|
||||
from django.template.loaders.base import Loader as BaseLoader
|
||||
from django.template import TemplateDoesNotExist
|
||||
|
||||
from dbtemplates.models import Template
|
||||
from dbtemplates.utils.cache import (cache, get_cache_key,
|
||||
set_and_return, get_cache_notfound_key)
|
||||
from dbtemplates.models import Template, backend
|
||||
|
||||
|
||||
class Loader(BaseLoader):
|
||||
def load_template_source(template_name, template_dirs=None):
|
||||
"""
|
||||
A custom template loader to load templates from the database.
|
||||
|
||||
|
|
@ -17,71 +14,45 @@ class Loader(BaseLoader):
|
|||
it falls back to query the database field ``name`` with the template path
|
||||
and ``sites`` with the current site.
|
||||
"""
|
||||
is_usable = True
|
||||
|
||||
def get_template_sources(self, template_name, template_dirs=None):
|
||||
yield Origin(
|
||||
name=template_name,
|
||||
template_name=template_name,
|
||||
loader=self,
|
||||
if VERSION[:2] >= (1, 2):
|
||||
# For backward compatibility
|
||||
import warnings
|
||||
warnings.warn(
|
||||
"`dbtemplates.loader.load_template_source` is deprecated; "
|
||||
"use `dbtemplates.loader.Loader` instead.",
|
||||
PendingDeprecationWarning
|
||||
)
|
||||
|
||||
def get_contents(self, origin):
|
||||
content, _ = self._load_template_source(origin.template_name)
|
||||
return content
|
||||
|
||||
def _load_and_store_template(self, template_name, cache_key, site,
|
||||
**params):
|
||||
template = Template.objects.get(name__exact=template_name, **params)
|
||||
db = router.db_for_read(Template, instance=template)
|
||||
display_name = f'dbtemplates:{db}:{template_name}:{site.domain}'
|
||||
return set_and_return(cache_key, template.content, display_name)
|
||||
|
||||
def _load_template_source(self, template_name, template_dirs=None):
|
||||
# The logic should work like this:
|
||||
# * Try to find the template in the cache. If found, return it.
|
||||
# * Now check the cache if a lookup for the given template
|
||||
# has failed lately and hand over control to the next template
|
||||
# loader waiting in line.
|
||||
# * If this still did not fail we first try to find a site-specific
|
||||
# template in the database.
|
||||
# * On a failure from our last attempt we try to load the global
|
||||
# template from the database.
|
||||
# * If all of the above steps have failed we generate a new key
|
||||
# in the cache indicating that queries failed, with the current
|
||||
# timestamp.
|
||||
site = Site.objects.get_current()
|
||||
cache_key = get_cache_key(template_name)
|
||||
if cache:
|
||||
try:
|
||||
backend_template = cache.get(cache_key)
|
||||
if backend_template:
|
||||
return backend_template, template_name
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Not found in cache, move on.
|
||||
cache_notfound_key = get_cache_notfound_key(template_name)
|
||||
if cache:
|
||||
try:
|
||||
notfound = cache.get(cache_notfound_key)
|
||||
if notfound:
|
||||
raise TemplateDoesNotExist(template_name)
|
||||
except Exception:
|
||||
raise TemplateDoesNotExist(template_name)
|
||||
|
||||
# Not marked as not-found, move on...
|
||||
|
||||
site = Site.objects.get_current()
|
||||
display_name = 'db:%s:%s:%s' % (settings.DATABASE_ENGINE,
|
||||
template_name, site.domain)
|
||||
if backend:
|
||||
try:
|
||||
return self._load_and_store_template(template_name, cache_key,
|
||||
site, sites__in=[site.id])
|
||||
except (Template.MultipleObjectsReturned, Template.DoesNotExist):
|
||||
try:
|
||||
return self._load_and_store_template(template_name, cache_key,
|
||||
site, sites__isnull=True)
|
||||
except (Template.MultipleObjectsReturned, Template.DoesNotExist):
|
||||
pass
|
||||
backend_template = backend.load(template_name)
|
||||
if backend_template:
|
||||
return backend_template, template_name
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
template = Template.on_site.get(name__exact=template_name)
|
||||
# Save in cache backend explicitly if manually deleted or invalidated
|
||||
if backend:
|
||||
backend.save(template_name, template.content)
|
||||
return (template.content, display_name)
|
||||
except:
|
||||
pass
|
||||
raise TemplateDoesNotExist(template_name)
|
||||
load_template_source.is_usable = True
|
||||
|
||||
|
||||
if VERSION[:2] >= (1, 2):
|
||||
# providing a class based loader for Django >= 1.2, yay!
|
||||
from django.template.loader import BaseLoader
|
||||
|
||||
class Loader(BaseLoader):
|
||||
__doc__ = load_template_source.__doc__
|
||||
|
||||
is_usable = True
|
||||
|
||||
def load_template_source(self, template_name, template_dirs=None):
|
||||
return load_template_source(template_name, template_dirs)
|
||||
|
||||
# Mark as not-found in cache.
|
||||
cache.set(cache_notfound_key, '1')
|
||||
raise TemplateDoesNotExist(template_name)
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1,108 +1,84 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# django-dbtemplates in Danish.
|
||||
# django-dbtemplates på Dansk.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Michael Lind Mortensen <illio@cs.au.dk>, 2009.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: django-dbtemplates\n"
|
||||
"Report-Msgid-Bugs-To: https://github.com/jezdez/django-dbtemplates/issues\n"
|
||||
"POT-Creation-Date: 2011-08-15 13:13+0200\n"
|
||||
"PO-Revision-Date: 2011-08-15 11:14+0000\n"
|
||||
"Last-Translator: Jannis <jannis@leidel.info>\n"
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2009-10-09 13:45+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: da\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
|
||||
|
||||
#: admin.py:56
|
||||
#: admin.py:29
|
||||
msgid ""
|
||||
"Leaving this empty causes Django to look for a template with the given name "
|
||||
"and populate this field with its content."
|
||||
msgstr ""
|
||||
"Hvis du efterlader dette felt tomt, så vil Django søge efter en template med"
|
||||
" det givne navn og udfylde dette felt med dets indhold."
|
||||
"Hvis du efterlader dette felt tomt, så vil Django søge efter en template med "
|
||||
"det givne navn og udfylde dette felt med dets indhold."
|
||||
|
||||
#: admin.py:82
|
||||
msgid "Advanced"
|
||||
msgstr ""
|
||||
|
||||
#: admin.py:85
|
||||
#: admin.py:43
|
||||
msgid "Date/time"
|
||||
msgstr "Dato/tid"
|
||||
|
||||
#: admin.py:102
|
||||
#: admin.py:61
|
||||
#, python-format
|
||||
msgid "Cache of one template successfully invalidated."
|
||||
msgid_plural "Cache of %(count)d templates successfully invalidated."
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: admin.py:106
|
||||
#: admin.py:65
|
||||
msgid "Invalidate cache of selected templates"
|
||||
msgstr ""
|
||||
|
||||
#: admin.py:114
|
||||
#: admin.py:74
|
||||
#, python-format
|
||||
msgid "Cache successfully repopulated with one template."
|
||||
msgid_plural "Cache successfully repopulated with %(count)d templates."
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: admin.py:118
|
||||
#: admin.py:78
|
||||
msgid "Repopulate cache with selected templates"
|
||||
msgstr ""
|
||||
|
||||
#: admin.py:130
|
||||
#, python-format
|
||||
msgid "Template syntax check FAILED for %(names)s."
|
||||
msgid_plural ""
|
||||
"Template syntax check FAILED for %(count)d templates: %(names)s."
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: admin.py:138
|
||||
#, python-format
|
||||
msgid "Template syntax OK."
|
||||
msgid_plural "Template syntax OK for %(count)d templates."
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: admin.py:141
|
||||
msgid "Check template syntax"
|
||||
msgstr ""
|
||||
|
||||
#: admin.py:145 models.py:25
|
||||
#: admin.py:82
|
||||
msgid "sites"
|
||||
msgstr "websider"
|
||||
|
||||
#: models.py:22
|
||||
#: models.py:18
|
||||
msgid "name"
|
||||
msgstr "navn"
|
||||
|
||||
#: models.py:23
|
||||
#: models.py:19
|
||||
msgid "Example: 'flatpages/default.html'"
|
||||
msgstr "Eksempel: 'flatpages/default.html'"
|
||||
|
||||
#: models.py:24
|
||||
#: models.py:20
|
||||
msgid "content"
|
||||
msgstr "indhold"
|
||||
|
||||
#: models.py:27
|
||||
#: models.py:22
|
||||
msgid "creation date"
|
||||
msgstr "oprettelsesdato"
|
||||
|
||||
#: models.py:29
|
||||
#: models.py:24
|
||||
msgid "last changed"
|
||||
msgstr "sidst ændret"
|
||||
|
||||
#: models.py:37
|
||||
#: models.py:32
|
||||
msgid "template"
|
||||
msgstr "skabelon"
|
||||
|
||||
#: models.py:38
|
||||
#: models.py:33
|
||||
msgid "templates"
|
||||
msgstr "skabeloner"
|
||||
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1,23 +1,18 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Jannis Leidel <jannis@leidel.info>, 2011.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: django-dbtemplates\n"
|
||||
"Report-Msgid-Bugs-To: https://github.com/jezdez/django-dbtemplates/issues\n"
|
||||
"POT-Creation-Date: 2011-08-15 13:13+0200\n"
|
||||
"PO-Revision-Date: 2011-08-15 11:14+0000\n"
|
||||
"Last-Translator: Jannis <jannis@leidel.info>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"Project-Id-Version: 0.4\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2009-10-09 13:45+0200\n"
|
||||
"PO-Revision-Date: 2008-08-19 17:11+0100\n"
|
||||
"Last-Translator: Jannis Leidel <jannis@leidel.info>\n"
|
||||
"Language-Team: Jannis Leidel <jannis@leidel.info>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: de\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
|
||||
"X-Poedit-Language: German\n"
|
||||
|
||||
#: admin.py:56
|
||||
#: admin.py:29
|
||||
msgid ""
|
||||
"Leaving this empty causes Django to look for a template with the given name "
|
||||
"and populate this field with its content."
|
||||
|
|
@ -25,86 +20,60 @@ msgstr ""
|
|||
"Wenn Sie dieses Feld leer lassen, wird Django versuchen, das Template mit "
|
||||
"dem angegebenen Namen zu finden und mit dessen Inhalt das Feld zu füllen."
|
||||
|
||||
#: admin.py:82
|
||||
msgid "Advanced"
|
||||
msgstr "Erweiterte Einstellungen"
|
||||
|
||||
#: admin.py:85
|
||||
#: admin.py:43
|
||||
msgid "Date/time"
|
||||
msgstr "Datum/Uhrzeit"
|
||||
|
||||
#: admin.py:102
|
||||
#: admin.py:61
|
||||
#, python-format
|
||||
msgid "Cache of one template successfully invalidated."
|
||||
msgid_plural "Cache of %(count)d templates successfully invalidated."
|
||||
msgstr[0] "Der Cache eines Templates wurde erfolgreich geleert."
|
||||
msgstr[1] "Der Cache von %(count)d Templates wurde erfolgreich geleert."
|
||||
|
||||
#: admin.py:106
|
||||
#: admin.py:65
|
||||
msgid "Invalidate cache of selected templates"
|
||||
msgstr "Cache der ausgewählten Templates leeren"
|
||||
|
||||
#: admin.py:114
|
||||
#: admin.py:74
|
||||
#, python-format
|
||||
msgid "Cache successfully repopulated with one template."
|
||||
msgid_plural "Cache successfully repopulated with %(count)d templates."
|
||||
msgstr[0] "Der Cache eines Templates wurde erfolgreich geleert und neu gefüllt."
|
||||
msgstr[1] ""
|
||||
"Der Cache von %(count)d Templates wurde erfolgreich geleert und neu gefüllt."
|
||||
msgstr[1] "Der Cache von %(count)d Templates wurde erfolgreich geleert und neu gefüllt."
|
||||
|
||||
#: admin.py:118
|
||||
#: admin.py:78
|
||||
msgid "Repopulate cache with selected templates"
|
||||
msgstr "Cache der ausgewählten Templates neu füllen"
|
||||
|
||||
#: admin.py:130
|
||||
#, python-format
|
||||
msgid "Template syntax check FAILED for %(names)s."
|
||||
msgid_plural ""
|
||||
"Template syntax check FAILED for %(count)d templates: %(names)s."
|
||||
msgstr[0] "Template-Syntax von %(names)s ist FEHLERHAFT."
|
||||
msgstr[1] "Template-Syntax von %(count)d Templates (%(names)s) ist FEHLERHAFT."
|
||||
|
||||
#: admin.py:138
|
||||
#, python-format
|
||||
msgid "Template syntax OK."
|
||||
msgid_plural "Template syntax OK for %(count)d templates."
|
||||
msgstr[0] "Template-Syntax ist OK."
|
||||
msgstr[1] "Template-Syntax von %(count)d Templates ist OK."
|
||||
|
||||
#: admin.py:141
|
||||
msgid "Check template syntax"
|
||||
msgstr "Template-Syntax überprüfen"
|
||||
|
||||
#: admin.py:145 models.py:25
|
||||
#: admin.py:82
|
||||
msgid "sites"
|
||||
msgstr "Seiten"
|
||||
|
||||
#: models.py:22
|
||||
#: models.py:18
|
||||
msgid "name"
|
||||
msgstr "Name"
|
||||
|
||||
#: models.py:23
|
||||
#: models.py:19
|
||||
msgid "Example: 'flatpages/default.html'"
|
||||
msgstr "Zum Beispiel: 'flatpages/default.html'"
|
||||
|
||||
#: models.py:24
|
||||
#: models.py:20
|
||||
msgid "content"
|
||||
msgstr "Inhalt"
|
||||
|
||||
#: models.py:27
|
||||
#: models.py:22
|
||||
msgid "creation date"
|
||||
msgstr "Erstellt"
|
||||
|
||||
#: models.py:29
|
||||
#: models.py:24
|
||||
msgid "last changed"
|
||||
msgstr "Geändert"
|
||||
|
||||
#: models.py:37
|
||||
#: models.py:32
|
||||
msgid "template"
|
||||
msgstr "Template"
|
||||
|
||||
#: models.py:38
|
||||
#: models.py:33
|
||||
msgid "templates"
|
||||
msgstr "Templates"
|
||||
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -8,97 +8,74 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2011-08-15 13:13+0200\n"
|
||||
"POT-Creation-Date: 2009-10-09 13:45+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"Language: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: admin.py:56
|
||||
#: admin.py:29
|
||||
msgid ""
|
||||
"Leaving this empty causes Django to look for a template with the given name "
|
||||
"and populate this field with its content."
|
||||
msgstr ""
|
||||
|
||||
#: admin.py:82
|
||||
msgid "Advanced"
|
||||
msgstr ""
|
||||
|
||||
#: admin.py:85
|
||||
#: admin.py:43
|
||||
msgid "Date/time"
|
||||
msgstr ""
|
||||
|
||||
#: admin.py:102
|
||||
#: admin.py:61
|
||||
#, python-format
|
||||
msgid "Cache of one template successfully invalidated."
|
||||
msgid_plural "Cache of %(count)d templates successfully invalidated."
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: admin.py:106
|
||||
#: admin.py:65
|
||||
msgid "Invalidate cache of selected templates"
|
||||
msgstr ""
|
||||
|
||||
#: admin.py:114
|
||||
#: admin.py:74
|
||||
#, python-format
|
||||
msgid "Cache successfully repopulated with one template."
|
||||
msgid_plural "Cache successfully repopulated with %(count)d templates."
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: admin.py:118
|
||||
#: admin.py:78
|
||||
msgid "Repopulate cache with selected templates"
|
||||
msgstr ""
|
||||
|
||||
#: admin.py:130
|
||||
#, python-format
|
||||
msgid "Template syntax check FAILED for %(names)s."
|
||||
msgid_plural "Template syntax check FAILED for %(count)d templates: %(names)s."
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: admin.py:138
|
||||
#, python-format
|
||||
msgid "Template syntax OK."
|
||||
msgid_plural "Template syntax OK for %(count)d templates."
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: admin.py:141
|
||||
msgid "Check template syntax"
|
||||
msgstr ""
|
||||
|
||||
#: admin.py:145 models.py:25
|
||||
#: admin.py:82
|
||||
msgid "sites"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:22
|
||||
#: models.py:18
|
||||
msgid "name"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:23
|
||||
#: models.py:19
|
||||
msgid "Example: 'flatpages/default.html'"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:24
|
||||
#: models.py:20
|
||||
msgid "content"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:27
|
||||
#: models.py:22
|
||||
msgid "creation date"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:29
|
||||
#: models.py:24
|
||||
msgid "last changed"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:37
|
||||
#: models.py:32
|
||||
msgid "template"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:38
|
||||
#: models.py:33
|
||||
msgid "templates"
|
||||
msgstr ""
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1,109 +0,0 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Ville Säävuori <ville@syneus.fi>, 2011.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: django-dbtemplates\n"
|
||||
"Report-Msgid-Bugs-To: https://github.com/jezdez/django-dbtemplates/issues\n"
|
||||
"POT-Creation-Date: 2011-08-15 13:13+0200\n"
|
||||
"PO-Revision-Date: 2011-08-15 11:14+0000\n"
|
||||
"Last-Translator: Jannis <jannis@leidel.info>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: fi\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
|
||||
|
||||
#: admin.py:56
|
||||
msgid ""
|
||||
"Leaving this empty causes Django to look for a template with the given name "
|
||||
"and populate this field with its content."
|
||||
msgstr ""
|
||||
"Jos tämä jätetään tyhjäksi, Django etsiin annetulla nimellä olevan "
|
||||
"mallipohjan ja täyttää tähän kenttään sen sisällön."
|
||||
|
||||
#: admin.py:82
|
||||
msgid "Advanced"
|
||||
msgstr "Lisäasetukset"
|
||||
|
||||
#: admin.py:85
|
||||
msgid "Date/time"
|
||||
msgstr "Päiväys/aika"
|
||||
|
||||
#: admin.py:102
|
||||
#, python-format
|
||||
msgid "Cache of one template successfully invalidated."
|
||||
msgid_plural "Cache of %(count)d templates successfully invalidated."
|
||||
msgstr[0] "Yhden mallipohjan välimuisti on onnistuneesti tyhjennetty."
|
||||
msgstr[1] "%(count)d mallipohjan välimusti on onnistuneesti tyhjennetty."
|
||||
|
||||
#: admin.py:106
|
||||
msgid "Invalidate cache of selected templates"
|
||||
msgstr "Tyhjennä valittujen mallipohjien välimuisti."
|
||||
|
||||
#: admin.py:114
|
||||
#, python-format
|
||||
msgid "Cache successfully repopulated with one template."
|
||||
msgid_plural "Cache successfully repopulated with %(count)d templates."
|
||||
msgstr[0] "Yhden mallipohjan välimuisti on täytetty onnistuneesti."
|
||||
msgstr[1] "%(count)d mallipohjan välimuisti on täytetty onnistuneesti."
|
||||
|
||||
#: admin.py:118
|
||||
msgid "Repopulate cache with selected templates"
|
||||
msgstr "Täytä valittujen mallipohjien välimuisti."
|
||||
|
||||
#: admin.py:130
|
||||
#, python-format
|
||||
msgid "Template syntax check FAILED for %(names)s."
|
||||
msgid_plural ""
|
||||
"Template syntax check FAILED for %(count)d templates: %(names)s."
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: admin.py:138
|
||||
#, python-format
|
||||
msgid "Template syntax OK."
|
||||
msgid_plural "Template syntax OK for %(count)d templates."
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: admin.py:141
|
||||
msgid "Check template syntax"
|
||||
msgstr ""
|
||||
|
||||
#: admin.py:145 models.py:25
|
||||
msgid "sites"
|
||||
msgstr "sivustot"
|
||||
|
||||
#: models.py:22
|
||||
msgid "name"
|
||||
msgstr "nimi"
|
||||
|
||||
#: models.py:23
|
||||
msgid "Example: 'flatpages/default.html'"
|
||||
msgstr "Esimerkiksi: 'flatpages/default.html'"
|
||||
|
||||
#: models.py:24
|
||||
msgid "content"
|
||||
msgstr "sisätö"
|
||||
|
||||
#: models.py:27
|
||||
msgid "creation date"
|
||||
msgstr "luontipäivä"
|
||||
|
||||
#: models.py:29
|
||||
msgid "last changed"
|
||||
msgstr "viimeksi muutettu"
|
||||
|
||||
#: models.py:37
|
||||
msgid "template"
|
||||
msgstr "mallipohja"
|
||||
|
||||
#: models.py:38
|
||||
msgid "templates"
|
||||
msgstr "mallipohjat"
|
||||
|
||||
|
||||
Binary file not shown.
|
|
@ -1,108 +1,75 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# Roland Frédéric <frederic.roland@creativeconvergence.be>, 2009.
|
||||
#
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: django-dbtemplates\n"
|
||||
"Report-Msgid-Bugs-To: https://github.com/jezdez/django-dbtemplates/issues\n"
|
||||
"POT-Creation-Date: 2011-08-15 13:13+0200\n"
|
||||
"PO-Revision-Date: 2011-08-15 11:14+0000\n"
|
||||
"Last-Translator: Jannis <jannis@leidel.info>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"Project-Id-Version: Django DB Template 0.4\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2009-10-09 13:45+0200\n"
|
||||
"PO-Revision-Date: 2009-10-21 19:16+0200\n"
|
||||
"Last-Translator: David Paccoud <dpaccoud@gmail.com>\n"
|
||||
"Language-Team: French\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: fr\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1)\n"
|
||||
"Content-Transfer-Encoding: 8bit"
|
||||
|
||||
#: admin.py:56
|
||||
#: admin.py:29
|
||||
msgid ""
|
||||
"Leaving this empty causes Django to look for a template with the given name "
|
||||
"and populate this field with its content."
|
||||
msgstr ""
|
||||
"Si vous laissez ceci vide , Django recherchera un modèle avec le nom donné "
|
||||
"et remplira ce champ avec son contenu."
|
||||
msgstr "Si vous laissez ceci vide , Django recherchera un modèle avec le nom donné et remplira ce champ avec son contenu."
|
||||
|
||||
#: admin.py:82
|
||||
msgid "Advanced"
|
||||
msgstr ""
|
||||
|
||||
#: admin.py:85
|
||||
#: admin.py:43
|
||||
msgid "Date/time"
|
||||
msgstr "Date/heure"
|
||||
|
||||
#: admin.py:102
|
||||
#, fuzzy, python-format
|
||||
#: admin.py:61
|
||||
#, python-format
|
||||
msgid "Cache of one template successfully invalidated."
|
||||
msgid_plural "Cache of %(count)d templates successfully invalidated."
|
||||
msgstr[0] "Le cache d'un modèle a été invalidé avec succès."
|
||||
msgstr[1] ""
|
||||
msgstr "Le cache d'un modèle a été invalidé avec succès."
|
||||
|
||||
#: admin.py:106
|
||||
#: admin.py:65
|
||||
msgid "Invalidate cache of selected templates"
|
||||
msgstr "Invalidation du cache des modèles sélectionnés"
|
||||
|
||||
#: admin.py:114
|
||||
#, fuzzy, python-format
|
||||
#: admin.py:74
|
||||
#, python-format
|
||||
msgid "Cache successfully repopulated with one template."
|
||||
msgid_plural "Cache successfully repopulated with %(count)d templates."
|
||||
msgstr[0] "Le cache d'un modèle a été rechargé avec succès."
|
||||
msgstr[1] ""
|
||||
msgstr "Le cache d'un modèle a été rechargé avec succès."
|
||||
|
||||
#: admin.py:118
|
||||
#: admin.py:78
|
||||
msgid "Repopulate cache with selected templates"
|
||||
msgstr "Rechargement du cache des modèles sélectionnés"
|
||||
|
||||
#: admin.py:130
|
||||
#, python-format
|
||||
msgid "Template syntax check FAILED for %(names)s."
|
||||
msgid_plural ""
|
||||
"Template syntax check FAILED for %(count)d templates: %(names)s."
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: admin.py:138
|
||||
#, python-format
|
||||
msgid "Template syntax OK."
|
||||
msgid_plural "Template syntax OK for %(count)d templates."
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: admin.py:141
|
||||
msgid "Check template syntax"
|
||||
msgstr ""
|
||||
|
||||
#: admin.py:145 models.py:25
|
||||
#: admin.py:82
|
||||
msgid "sites"
|
||||
msgstr "sites"
|
||||
|
||||
#: models.py:22
|
||||
#: models.py:18
|
||||
msgid "name"
|
||||
msgstr "nom"
|
||||
|
||||
#: models.py:23
|
||||
#: models.py:19
|
||||
msgid "Example: 'flatpages/default.html'"
|
||||
msgstr "Exemple : 'flatpages/default.html'"
|
||||
|
||||
#: models.py:24
|
||||
#: models.py:20
|
||||
msgid "content"
|
||||
msgstr "contenu"
|
||||
|
||||
#: models.py:27
|
||||
#: models.py:22
|
||||
msgid "creation date"
|
||||
msgstr "date de création"
|
||||
|
||||
#: models.py:29
|
||||
#: models.py:24
|
||||
msgid "last changed"
|
||||
msgstr "dernier changement"
|
||||
|
||||
#: models.py:37
|
||||
#: models.py:32
|
||||
msgid "template"
|
||||
msgstr "modèle"
|
||||
|
||||
#: models.py:38
|
||||
#: models.py:33
|
||||
msgid "templates"
|
||||
msgstr "modèles"
|
||||
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1,106 +1,82 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# translation of PACKAGE.
|
||||
# Copyright (C) 2008 THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# <>, 2008.
|
||||
#
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: django-dbtemplates\n"
|
||||
"Report-Msgid-Bugs-To: https://github.com/jezdez/django-dbtemplates/issues\n"
|
||||
"POT-Creation-Date: 2011-08-15 13:13+0200\n"
|
||||
"PO-Revision-Date: 2011-08-15 11:14+0000\n"
|
||||
"Last-Translator: Jannis <jannis@leidel.info>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2009-10-09 13:45+0200\n"
|
||||
"PO-Revision-Date: 2008-08-21 12:31+0300\n"
|
||||
"Last-Translator: <>\n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: he\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
|
||||
|
||||
#: admin.py:56
|
||||
#: admin.py:29
|
||||
msgid ""
|
||||
"Leaving this empty causes Django to look for a template with the given name "
|
||||
"and populate this field with its content."
|
||||
msgstr "אם זה ריק אז ג'נגו מחפש תבנית עם שם סיפק וממלא את השדה עם תוכנו"
|
||||
|
||||
#: admin.py:82
|
||||
msgid "Advanced"
|
||||
msgstr ""
|
||||
|
||||
#: admin.py:85
|
||||
#: admin.py:43
|
||||
msgid "Date/time"
|
||||
msgstr "תאריך / זמן"
|
||||
|
||||
#: admin.py:102
|
||||
#: admin.py:61
|
||||
#, python-format
|
||||
msgid "Cache of one template successfully invalidated."
|
||||
msgid_plural "Cache of %(count)d templates successfully invalidated."
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: admin.py:106
|
||||
#: admin.py:65
|
||||
msgid "Invalidate cache of selected templates"
|
||||
msgstr ""
|
||||
|
||||
#: admin.py:114
|
||||
#: admin.py:74
|
||||
#, python-format
|
||||
msgid "Cache successfully repopulated with one template."
|
||||
msgid_plural "Cache successfully repopulated with %(count)d templates."
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: admin.py:118
|
||||
#: admin.py:78
|
||||
msgid "Repopulate cache with selected templates"
|
||||
msgstr ""
|
||||
|
||||
#: admin.py:130
|
||||
#, python-format
|
||||
msgid "Template syntax check FAILED for %(names)s."
|
||||
msgid_plural ""
|
||||
"Template syntax check FAILED for %(count)d templates: %(names)s."
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: admin.py:138
|
||||
#, python-format
|
||||
msgid "Template syntax OK."
|
||||
msgid_plural "Template syntax OK for %(count)d templates."
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: admin.py:141
|
||||
msgid "Check template syntax"
|
||||
msgstr ""
|
||||
|
||||
#: admin.py:145 models.py:25
|
||||
#: admin.py:82
|
||||
msgid "sites"
|
||||
msgstr "אתרים"
|
||||
|
||||
#: models.py:22
|
||||
#: models.py:18
|
||||
msgid "name"
|
||||
msgstr "שם"
|
||||
|
||||
#: models.py:23
|
||||
#: models.py:19
|
||||
msgid "Example: 'flatpages/default.html'"
|
||||
msgstr "דוגמא: 'flatpages/default.html'"
|
||||
|
||||
#: models.py:24
|
||||
#: models.py:20
|
||||
msgid "content"
|
||||
msgstr "תוכן"
|
||||
|
||||
#: models.py:27
|
||||
#: models.py:22
|
||||
msgid "creation date"
|
||||
msgstr "נוצר ב"
|
||||
|
||||
#: models.py:29
|
||||
#: models.py:24
|
||||
msgid "last changed"
|
||||
msgstr "שונה ב"
|
||||
|
||||
#: models.py:37
|
||||
#: models.py:32
|
||||
msgid "template"
|
||||
msgstr "תבנית"
|
||||
|
||||
#: models.py:38
|
||||
#: models.py:33
|
||||
msgid "templates"
|
||||
msgstr "תבניות"
|
||||
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1,22 +1,17 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: django-dbtemplates\n"
|
||||
"Report-Msgid-Bugs-To: https://github.com/jezdez/django-dbtemplates/issues\n"
|
||||
"POT-Creation-Date: 2011-08-15 13:13+0200\n"
|
||||
"PO-Revision-Date: 2011-08-15 11:14+0000\n"
|
||||
"Last-Translator: Jannis <jannis@leidel.info>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"Project-Id-Version: 0.4\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2009-10-09 13:45+0200\n"
|
||||
"PO-Revision-Date: 2009-01-22 01:27+0100\n"
|
||||
"Last-Translator: Marco Beri <marcoberi@gmail.com>\n"
|
||||
"Language-Team: Jannis Leidel <jannis@leidel.info>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: it\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
|
||||
"X-Poedit-Language: German\n"
|
||||
|
||||
#: admin.py:56
|
||||
#: admin.py:29
|
||||
msgid ""
|
||||
"Leaving this empty causes Django to look for a template with the given name "
|
||||
"and populate this field with its content."
|
||||
|
|
@ -24,85 +19,60 @@ msgstr ""
|
|||
"Lasciandolo vuoto, Django cercherà un template con lo stesso nome che avete "
|
||||
"indicato sopra e userà il suo contenuto per riempire questo campo."
|
||||
|
||||
#: admin.py:82
|
||||
msgid "Advanced"
|
||||
msgstr ""
|
||||
|
||||
#: admin.py:85
|
||||
#: admin.py:43
|
||||
msgid "Date/time"
|
||||
msgstr ""
|
||||
|
||||
#: admin.py:102
|
||||
#: admin.py:61
|
||||
#, python-format
|
||||
msgid "Cache of one template successfully invalidated."
|
||||
msgid_plural "Cache of %(count)d templates successfully invalidated."
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: admin.py:106
|
||||
#: admin.py:65
|
||||
msgid "Invalidate cache of selected templates"
|
||||
msgstr ""
|
||||
|
||||
#: admin.py:114
|
||||
#: admin.py:74
|
||||
#, python-format
|
||||
msgid "Cache successfully repopulated with one template."
|
||||
msgid_plural "Cache successfully repopulated with %(count)d templates."
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: admin.py:118
|
||||
#: admin.py:78
|
||||
msgid "Repopulate cache with selected templates"
|
||||
msgstr ""
|
||||
|
||||
#: admin.py:130
|
||||
#, python-format
|
||||
msgid "Template syntax check FAILED for %(names)s."
|
||||
msgid_plural ""
|
||||
"Template syntax check FAILED for %(count)d templates: %(names)s."
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: admin.py:138
|
||||
#, python-format
|
||||
msgid "Template syntax OK."
|
||||
msgid_plural "Template syntax OK for %(count)d templates."
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: admin.py:141
|
||||
msgid "Check template syntax"
|
||||
msgstr ""
|
||||
|
||||
#: admin.py:145 models.py:25
|
||||
#: admin.py:82
|
||||
msgid "sites"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:22
|
||||
#: models.py:18
|
||||
msgid "name"
|
||||
msgstr "nome"
|
||||
|
||||
#: models.py:23
|
||||
#: models.py:19
|
||||
msgid "Example: 'flatpages/default.html'"
|
||||
msgstr "Esempio: 'flatpages/default.html'"
|
||||
|
||||
#: models.py:24
|
||||
#: models.py:20
|
||||
msgid "content"
|
||||
msgstr "contenuto"
|
||||
|
||||
#: models.py:27
|
||||
#: models.py:22
|
||||
msgid "creation date"
|
||||
msgstr "data di creazione"
|
||||
|
||||
#: models.py:29
|
||||
#: models.py:24
|
||||
msgid "last changed"
|
||||
msgstr "ultimo cambiamento"
|
||||
|
||||
#: models.py:37
|
||||
#: models.py:32
|
||||
msgid "template"
|
||||
msgstr "template"
|
||||
|
||||
#: models.py:38
|
||||
#: models.py:33
|
||||
msgid "templates"
|
||||
msgstr "template"
|
||||
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1,23 +1,17 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Herson Hersonls <hersonls@gmail.com>, 2011.
|
||||
# Diego Búrigo Zacarão <diegobz@fedoraproject.org> 2009.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: django-dbtemplates\n"
|
||||
"Report-Msgid-Bugs-To: https://github.com/jezdez/django-dbtemplates/issues\n"
|
||||
"POT-Creation-Date: 2011-08-15 13:13+0200\n"
|
||||
"PO-Revision-Date: 2011-08-15 11:14+0000\n"
|
||||
"Last-Translator: Jannis <jannis@leidel.info>\n"
|
||||
"Language-Team: Portuguese (Brazilian) (http://www.transifex.net/projects/p/django-dbtemplates/team/pt_BR/)\n"
|
||||
"Project-Id-Version: 0.4\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2009-10-09 13:45+0200\n"
|
||||
"PO-Revision-Date: 2008-08-31 11:45-0300\n"
|
||||
"Last-Translator: Diego Búrigo Zacarão <diegobz@fedoraproject.org>\n"
|
||||
"Language-Team: Brazilian Portuguese <fedora-trans-pt_br@redhat.com>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: pt_BR\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1)\n"
|
||||
|
||||
#: admin.py:56
|
||||
#: admin.py:29
|
||||
msgid ""
|
||||
"Leaving this empty causes Django to look for a template with the given name "
|
||||
"and populate this field with its content."
|
||||
|
|
@ -25,85 +19,60 @@ msgstr ""
|
|||
"Manter isto vazio faz com que o Django procure por um modelo (template) com "
|
||||
"o dado nome e preencha este campo com o seu conteúdo"
|
||||
|
||||
#: admin.py:82
|
||||
msgid "Advanced"
|
||||
msgstr "Avançado"
|
||||
|
||||
#: admin.py:85
|
||||
#: admin.py:43
|
||||
msgid "Date/time"
|
||||
msgstr "Data/hora"
|
||||
|
||||
#: admin.py:102
|
||||
#: admin.py:61
|
||||
#, python-format
|
||||
msgid "Cache of one template successfully invalidated."
|
||||
msgid_plural "Cache of %(count)d templates successfully invalidated."
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: admin.py:106
|
||||
#: admin.py:65
|
||||
msgid "Invalidate cache of selected templates"
|
||||
msgstr ""
|
||||
|
||||
#: admin.py:114
|
||||
#: admin.py:74
|
||||
#, python-format
|
||||
msgid "Cache successfully repopulated with one template."
|
||||
msgid_plural "Cache successfully repopulated with %(count)d templates."
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: admin.py:118
|
||||
#: admin.py:78
|
||||
msgid "Repopulate cache with selected templates"
|
||||
msgstr ""
|
||||
|
||||
#: admin.py:130
|
||||
#, python-format
|
||||
msgid "Template syntax check FAILED for %(names)s."
|
||||
msgid_plural ""
|
||||
"Template syntax check FAILED for %(count)d templates: %(names)s."
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: admin.py:138
|
||||
#, python-format
|
||||
msgid "Template syntax OK."
|
||||
msgid_plural "Template syntax OK for %(count)d templates."
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: admin.py:141
|
||||
msgid "Check template syntax"
|
||||
msgstr ""
|
||||
|
||||
#: admin.py:145 models.py:25
|
||||
#: admin.py:82
|
||||
msgid "sites"
|
||||
msgstr "sites"
|
||||
|
||||
#: models.py:22
|
||||
#: models.py:18
|
||||
msgid "name"
|
||||
msgstr "Name"
|
||||
|
||||
#: models.py:23
|
||||
#: models.py:19
|
||||
msgid "Example: 'flatpages/default.html'"
|
||||
msgstr "Exemplo: 'flatpages/default.html'"
|
||||
|
||||
#: models.py:24
|
||||
#: models.py:20
|
||||
msgid "content"
|
||||
msgstr "conteúdo"
|
||||
|
||||
#: models.py:27
|
||||
#: models.py:22
|
||||
msgid "creation date"
|
||||
msgstr "Data de criação"
|
||||
|
||||
#: models.py:29
|
||||
#: models.py:24
|
||||
msgid "last changed"
|
||||
msgstr "ultima modificação"
|
||||
|
||||
#: models.py:37
|
||||
#: models.py:32
|
||||
msgid "template"
|
||||
msgstr "modelo"
|
||||
|
||||
#: models.py:38
|
||||
#: models.py:33
|
||||
msgid "templates"
|
||||
msgstr "modelos"
|
||||
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1,106 +0,0 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2013-07-30 14:03+0600\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"Language: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
|
||||
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
|
||||
|
||||
#: admin.py:57
|
||||
msgid ""
|
||||
"Leaving this empty causes Django to look for a template with the given name "
|
||||
"and populate this field with its content."
|
||||
msgstr "Если вы оставите это поле незаполненным, Django будет искать шаблон с введённым именем и заполнит поле его содержимым."
|
||||
|
||||
#: admin.py:92
|
||||
msgid "Advanced"
|
||||
msgstr "Дополнительно"
|
||||
|
||||
#: admin.py:95
|
||||
msgid "Date/time"
|
||||
msgstr "Дата/время"
|
||||
|
||||
#: admin.py:112
|
||||
#, python-format
|
||||
msgid "Cache of one template successfully invalidated."
|
||||
msgid_plural "Cache of %(count)d templates successfully invalidated."
|
||||
msgstr[0] "Кэш для шаблона успешно очищен."
|
||||
msgstr[1] "Кэш для шаблонов (%(count)d шт.) успешно очищен."
|
||||
|
||||
#: admin.py:116
|
||||
msgid "Invalidate cache of selected templates"
|
||||
msgstr "Очистить кэш для выделенных шаблонов"
|
||||
|
||||
#: admin.py:124
|
||||
#, python-format
|
||||
msgid "Cache successfully repopulated with one template."
|
||||
msgid_plural "Cache successfully repopulated with %(count)d templates."
|
||||
msgstr[0] "Кэш для шаблона успешно заполнен."
|
||||
msgstr[1] "Кэш для шаблонов (%(count)d шт.) успешно заполнен."
|
||||
|
||||
#: admin.py:128
|
||||
msgid "Repopulate cache with selected templates"
|
||||
msgstr "Заполнить кэш для выделенных шаблонов"
|
||||
|
||||
#: admin.py:140
|
||||
#, python-format
|
||||
msgid "Template syntax check FAILED for %(names)s."
|
||||
msgid_plural "Template syntax check FAILED for %(count)d templates: %(names)s."
|
||||
msgstr[0] "Неверный синтаксис у шаблона %(names)s."
|
||||
msgstr[1] "Неверный синтаксис у следующих шаблонов: %(names)s."
|
||||
|
||||
#: admin.py:148
|
||||
#, python-format
|
||||
msgid "Template syntax OK."
|
||||
msgid_plural "Template syntax OK for %(count)d templates."
|
||||
msgstr[0] "Синтаксис шаблона корректен."
|
||||
msgstr[1] "Синтаксис шаблонов корректен."
|
||||
|
||||
#: admin.py:151
|
||||
msgid "Check template syntax"
|
||||
msgstr "Проверить синтаксис шаблона"
|
||||
|
||||
#: admin.py:155 models.py:29
|
||||
msgid "sites"
|
||||
msgstr "сайты"
|
||||
|
||||
#: models.py:26
|
||||
msgid "name"
|
||||
msgstr "название"
|
||||
|
||||
#: models.py:27
|
||||
msgid "Example: 'flatpages/default.html'"
|
||||
msgstr "Например: 'flatpages/default.html'"
|
||||
|
||||
#: models.py:28
|
||||
msgid "content"
|
||||
msgstr "содержимое"
|
||||
|
||||
#: models.py:31
|
||||
msgid "creation date"
|
||||
msgstr "дата создания"
|
||||
|
||||
#: models.py:33
|
||||
msgid "last changed"
|
||||
msgstr "последнее изменение"
|
||||
|
||||
#: models.py:41
|
||||
msgid "template"
|
||||
msgstr "шаблон"
|
||||
|
||||
#: models.py:42
|
||||
msgid "templates"
|
||||
msgstr "шаблоны"
|
||||
Binary file not shown.
|
|
@ -1,102 +1,75 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: django-dbtemplates\n"
|
||||
"Report-Msgid-Bugs-To: https://github.com/jezdez/django-dbtemplates/issues\n"
|
||||
"POT-Creation-Date: 2011-08-15 13:13+0200\n"
|
||||
"PO-Revision-Date: 2011-08-15 11:14+0000\n"
|
||||
"Last-Translator: Jannis <jannis@leidel.info>\n"
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2009-10-09 13:45+0200\n"
|
||||
"PO-Revision-Date: 2010-01-05 17:23+0800\n"
|
||||
"Last-Translator: 张昆 <zhangkun@web916.com>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: zh_CN\n"
|
||||
"Plural-Forms: nplurals=1; plural=0\n"
|
||||
|
||||
#: admin.py:56
|
||||
msgid ""
|
||||
"Leaving this empty causes Django to look for a template with the given name "
|
||||
"and populate this field with its content."
|
||||
#: admin.py:29
|
||||
msgid "Leaving this empty causes Django to look for a template with the given name and populate this field with its content."
|
||||
msgstr "此项目留空将使系统用指定的名称寻找模板并应用到该项目。"
|
||||
|
||||
#: admin.py:82
|
||||
msgid "Advanced"
|
||||
msgstr ""
|
||||
|
||||
#: admin.py:85
|
||||
#: admin.py:43
|
||||
msgid "Date/time"
|
||||
msgstr "日期/时间"
|
||||
|
||||
#: admin.py:102
|
||||
#, fuzzy, python-format
|
||||
#: admin.py:61
|
||||
#, python-format
|
||||
msgid "Cache of one template successfully invalidated."
|
||||
msgid_plural "Cache of %(count)d templates successfully invalidated."
|
||||
msgstr[0] "该模板的缓存已经成功撤销。"
|
||||
msgstr "该模板的缓存已经成功撤销。"
|
||||
|
||||
#: admin.py:106
|
||||
#: admin.py:65
|
||||
msgid "Invalidate cache of selected templates"
|
||||
msgstr "撤销选中模板的缓存"
|
||||
|
||||
#: admin.py:114
|
||||
#, fuzzy, python-format
|
||||
#: admin.py:74
|
||||
#, python-format
|
||||
msgid "Cache successfully repopulated with one template."
|
||||
msgid_plural "Cache successfully repopulated with %(count)d templates."
|
||||
msgstr[0] "该模板的缓存已经成功启用。"
|
||||
msgstr "该模板的缓存已经成功启用。"
|
||||
|
||||
#: admin.py:118
|
||||
#: admin.py:78
|
||||
msgid "Repopulate cache with selected templates"
|
||||
msgstr "重新启用选中模板的缓存"
|
||||
|
||||
#: admin.py:130
|
||||
#, python-format
|
||||
msgid "Template syntax check FAILED for %(names)s."
|
||||
msgid_plural ""
|
||||
"Template syntax check FAILED for %(count)d templates: %(names)s."
|
||||
msgstr[0] ""
|
||||
|
||||
#: admin.py:138
|
||||
#, python-format
|
||||
msgid "Template syntax OK."
|
||||
msgid_plural "Template syntax OK for %(count)d templates."
|
||||
msgstr[0] ""
|
||||
|
||||
#: admin.py:141
|
||||
msgid "Check template syntax"
|
||||
msgstr ""
|
||||
|
||||
#: admin.py:145 models.py:25
|
||||
#: admin.py:82
|
||||
msgid "sites"
|
||||
msgstr "站点"
|
||||
|
||||
#: models.py:22
|
||||
#: models.py:18
|
||||
msgid "name"
|
||||
msgstr "名称"
|
||||
|
||||
#: models.py:23
|
||||
#: models.py:19
|
||||
msgid "Example: 'flatpages/default.html'"
|
||||
msgstr "例如: 'flatpages/default.html'"
|
||||
|
||||
#: models.py:24
|
||||
#: models.py:20
|
||||
msgid "content"
|
||||
msgstr "内容"
|
||||
|
||||
#: models.py:27
|
||||
#: models.py:22
|
||||
msgid "creation date"
|
||||
msgstr "创建日期"
|
||||
|
||||
#: models.py:29
|
||||
#: models.py:24
|
||||
msgid "last changed"
|
||||
msgstr "最新变更"
|
||||
|
||||
#: models.py:37
|
||||
#: models.py:32
|
||||
msgid "template"
|
||||
msgstr "模板"
|
||||
|
||||
#: models.py:38
|
||||
#: models.py:33
|
||||
msgid "templates"
|
||||
msgstr "模板"
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,19 +0,0 @@
|
|||
from django.core.management.base import CommandError, BaseCommand
|
||||
|
||||
from dbtemplates.models import Template
|
||||
from dbtemplates.utils.template import check_template_syntax
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = "Ensures templates stored in the database don't have syntax errors."
|
||||
|
||||
def handle(self, **options):
|
||||
errors = []
|
||||
for template in Template.objects.all():
|
||||
valid, error = check_template_syntax(template)
|
||||
if not valid:
|
||||
errors.append(f'{template.name}: {error}')
|
||||
if errors:
|
||||
raise CommandError(
|
||||
'Some templates contained errors\n%s' % '\n'.join(errors))
|
||||
self.stdout.write('OK')
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
import sys
|
||||
from django.core.management.base import CommandError, BaseCommand
|
||||
from optparse import make_option
|
||||
|
||||
from django.core.management.base import CommandError, NoArgsCommand
|
||||
from django.contrib.sites.models import Site
|
||||
|
||||
from dbtemplates.models import Template
|
||||
|
|
@ -23,16 +24,13 @@ TEMPLATES = {
|
|||
""",
|
||||
}
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = "Creates the default error templates as database template objects."
|
||||
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument(
|
||||
"-f", "--force", action="store_true", dest="force",
|
||||
default=False, help="overwrite existing database templates")
|
||||
|
||||
def handle(self, **options):
|
||||
class Command(NoArgsCommand):
|
||||
help = "Creates the 404.html and 500.html error templates as database template objects."
|
||||
option_list = NoArgsCommand.option_list + (
|
||||
make_option("-f", "--force", action="store_true", dest="force",
|
||||
default=False, help="overwrite existing database templates"),
|
||||
)
|
||||
def handle_noargs(self, **options):
|
||||
force = options.get('force')
|
||||
try:
|
||||
site = Site.objects.get_current()
|
||||
|
|
@ -43,15 +41,13 @@ class Command(BaseCommand):
|
|||
verbosity = int(options.get('verbosity', 1))
|
||||
for error_code in (404, 500):
|
||||
template, created = Template.objects.get_or_create(
|
||||
name=f"{error_code}.html")
|
||||
name="%s.html" % error_code)
|
||||
if created or (not created and force):
|
||||
template.content = TEMPLATES.get(error_code, '')
|
||||
template.save()
|
||||
template.sites.add(site)
|
||||
if verbosity >= 1:
|
||||
sys.stdout.write("Created database template "
|
||||
"for %s errors.\n" % error_code)
|
||||
self.stdout.write("Created database template for %s errors.\n" % error_code)
|
||||
else:
|
||||
if verbosity >= 1:
|
||||
sys.stderr.write("A template for %s errors "
|
||||
"already exists.\n" % error_code)
|
||||
self.stderr.write("A template for %s errors already exists.\n" % error_code)
|
||||
|
|
|
|||
|
|
@ -1,153 +1,76 @@
|
|||
import os
|
||||
from optparse import make_option
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.sites.models import Site
|
||||
from django.core.management.base import CommandError, NoArgsCommand
|
||||
from django.template.loaders.app_directories import app_template_dirs
|
||||
|
||||
from dbtemplates.models import Template
|
||||
from django.contrib.sites.models import Site
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
from django.template.loader import _engine_list
|
||||
from django.template.utils import get_app_template_dirs
|
||||
|
||||
ALWAYS_ASK, FILES_TO_DATABASE, DATABASE_TO_FILES = ("0", "1", "2")
|
||||
|
||||
DIRS = []
|
||||
for engine in _engine_list():
|
||||
DIRS.extend(engine.dirs)
|
||||
DIRS = tuple(DIRS)
|
||||
app_template_dirs = get_app_template_dirs("templates")
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
class Command(NoArgsCommand):
|
||||
help = "Syncs file system templates with the database bidirectionally."
|
||||
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument(
|
||||
"-e",
|
||||
"--ext",
|
||||
dest="ext",
|
||||
action="store",
|
||||
default="html",
|
||||
help="extension of the files you want to "
|
||||
"sync with the database [default: %(default)s]",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-f",
|
||||
"--force",
|
||||
action="store_true",
|
||||
dest="force",
|
||||
default=False,
|
||||
help="overwrite existing database templates",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-o",
|
||||
"--overwrite",
|
||||
action="store",
|
||||
dest="overwrite",
|
||||
default="0",
|
||||
help="'0' - ask always, '1' - overwrite database "
|
||||
"templates from template files, '2' - overwrite "
|
||||
"template files from database templates",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-a",
|
||||
"--app-first",
|
||||
action="store_true",
|
||||
dest="app_first",
|
||||
default=False,
|
||||
help="look for templates in applications "
|
||||
"directories before project templates",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-d",
|
||||
"--delete",
|
||||
action="store_true",
|
||||
dest="delete",
|
||||
default=False,
|
||||
help="Delete templates after syncing",
|
||||
)
|
||||
|
||||
def handle(self, **options):
|
||||
extension = options.get("ext")
|
||||
force = options.get("force")
|
||||
overwrite = options.get("overwrite")
|
||||
app_first = options.get("app_first")
|
||||
delete = options.get("delete")
|
||||
option_list = NoArgsCommand.option_list + (
|
||||
make_option("-e", "--ext", dest="ext", action="store", default="html",
|
||||
help="extension of the files you want to sync with the database "
|
||||
"[default: %default]"),
|
||||
make_option("-f", "--force", action="store_true", dest="force",
|
||||
default=False, help="overwrite existing database templates")
|
||||
)
|
||||
def handle_noargs(self, **options):
|
||||
extension = options.get('ext')
|
||||
force = options.get('force')
|
||||
|
||||
if not extension.startswith("."):
|
||||
extension = f".{extension}"
|
||||
extension = ".%s" % extension
|
||||
|
||||
try:
|
||||
site = Site.objects.get_current()
|
||||
except Exception:
|
||||
raise CommandError(
|
||||
"Please make sure to have the sites contrib "
|
||||
"app installed and setup with a site object"
|
||||
)
|
||||
except:
|
||||
raise CommandError("Please make sure to have the sites contrib "
|
||||
"app installed and setup with a site object")
|
||||
|
||||
if app_first:
|
||||
tpl_dirs = app_template_dirs + DIRS
|
||||
else:
|
||||
tpl_dirs = DIRS + app_template_dirs
|
||||
templatedirs = [str(d) for d in tpl_dirs if os.path.isdir(d)]
|
||||
if not type(settings.TEMPLATE_DIRS) in (tuple, list):
|
||||
raise CommandError("Please make sure settings.TEMPLATE_DIRS is a "
|
||||
"list or tuple.")
|
||||
|
||||
templatedirs = [d for d in
|
||||
settings.TEMPLATE_DIRS + app_template_dirs if os.path.isdir(d)]
|
||||
|
||||
for templatedir in templatedirs:
|
||||
for dirpath, subdirs, filenames in os.walk(templatedir):
|
||||
for f in [
|
||||
f
|
||||
for f in filenames
|
||||
if f.endswith(extension) and not f.startswith(".")
|
||||
]:
|
||||
for f in [f for f in filenames if f.endswith(extension)
|
||||
and not f.startswith(".")]:
|
||||
path = os.path.join(dirpath, f)
|
||||
name = path.split(str(templatedir))[1]
|
||||
if name.startswith("/"):
|
||||
name = name[1:]
|
||||
name = path.split(templatedir)[1][1:]
|
||||
try:
|
||||
t = Template.on_site.get(name__exact=name)
|
||||
except Template.DoesNotExist:
|
||||
if not force:
|
||||
confirm = input(
|
||||
"\nA '%s' template doesn't exist in the "
|
||||
"database.\nCreate it with '%s'?"
|
||||
" (y/[n]): "
|
||||
"" % (name, path)
|
||||
)
|
||||
if force or confirm.lower().startswith("y"):
|
||||
with open(path, encoding="utf-8") as f:
|
||||
t = Template(name=name, content=f.read())
|
||||
if force == False:
|
||||
confirm = raw_input(
|
||||
"\nA '%s' template doesn't exist in the database.\n"
|
||||
"Create it with '%s'?"
|
||||
" (y/[n]): """ % (name, path))
|
||||
if confirm.lower().startswith('y') or force:
|
||||
t = Template(name=name,
|
||||
content=open(path, "r").read())
|
||||
t.save()
|
||||
t.sites.add(site)
|
||||
else:
|
||||
while True:
|
||||
if overwrite == ALWAYS_ASK:
|
||||
_i = (
|
||||
"\n%(template)s exists in the database.\n"
|
||||
"(1) Overwrite %(template)s with '%(path)s'\n" # noqa
|
||||
"(2) Overwrite '%(path)s' with %(template)s\n" # noqa
|
||||
"Type 1 or 2 or press <Enter> to skip: "
|
||||
% {"template": t.__repr__(), "path": path}
|
||||
)
|
||||
|
||||
confirm = input(_i)
|
||||
else:
|
||||
confirm = overwrite
|
||||
if confirm in (
|
||||
"",
|
||||
FILES_TO_DATABASE,
|
||||
DATABASE_TO_FILES,
|
||||
):
|
||||
if confirm == FILES_TO_DATABASE:
|
||||
with open(path, encoding="utf-8") as f:
|
||||
t.content = f.read()
|
||||
t.save()
|
||||
t.sites.add(site)
|
||||
if delete:
|
||||
try:
|
||||
os.remove(path)
|
||||
except OSError:
|
||||
raise CommandError(
|
||||
f"Couldn't delete {path}"
|
||||
)
|
||||
elif confirm == DATABASE_TO_FILES:
|
||||
with open(path, "w", encoding="utf-8") as f: # noqa
|
||||
f.write(t.content)
|
||||
if delete:
|
||||
t.delete()
|
||||
while 1:
|
||||
confirm = raw_input(
|
||||
"\n%s exists in the database.\n"
|
||||
"(1) Overwrite %s with '%s'\n"
|
||||
"(2) Overwrite '%s' with %s\n"
|
||||
"Type 1 or 2 or press <Enter> to skip: "
|
||||
% (t.__repr__(),
|
||||
t.__repr__(), path,
|
||||
path, t.__repr__()))
|
||||
if confirm == '' or confirm in ('1', '2'):
|
||||
if confirm == '1':
|
||||
t.content = open(path, 'r').read()
|
||||
t.save()
|
||||
t.sites.add(site)
|
||||
elif confirm == '2':
|
||||
open(path, 'w').write(t.content)
|
||||
break
|
||||
|
|
|
|||
|
|
@ -1,73 +0,0 @@
|
|||
import django
|
||||
import django.utils.timezone
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("sites", "0001_initial"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="Template",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
verbose_name="ID",
|
||||
serialize=False,
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
),
|
||||
),
|
||||
(
|
||||
"name",
|
||||
models.CharField(
|
||||
help_text="Example: 'flatpages/default.html'",
|
||||
max_length=100,
|
||||
verbose_name="name",
|
||||
),
|
||||
),
|
||||
(
|
||||
"content",
|
||||
models.TextField(verbose_name="content", blank=True),
|
||||
), # noqa
|
||||
(
|
||||
"creation_date",
|
||||
models.DateTimeField(
|
||||
default=django.utils.timezone.now,
|
||||
verbose_name="creation date", # noqa
|
||||
),
|
||||
),
|
||||
(
|
||||
"last_changed",
|
||||
models.DateTimeField(
|
||||
default=django.utils.timezone.now,
|
||||
verbose_name="last changed", # noqa
|
||||
),
|
||||
),
|
||||
(
|
||||
"sites",
|
||||
models.ManyToManyField(
|
||||
to="sites.Site", verbose_name="sites", blank=True
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"ordering": ("name",),
|
||||
"db_table": "django_template",
|
||||
"verbose_name": "template",
|
||||
"verbose_name_plural": "templates",
|
||||
},
|
||||
bases=(models.Model,),
|
||||
managers=[
|
||||
("objects", django.db.models.manager.Manager()),
|
||||
(
|
||||
"on_site",
|
||||
django.contrib.sites.managers.CurrentSiteManager("sites"),
|
||||
), # noqa
|
||||
],
|
||||
),
|
||||
]
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
# Generated by Django 5.1 on 2025-05-26 19:59
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('dbtemplates', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='template',
|
||||
name='creation_date',
|
||||
field=models.DateTimeField(auto_now_add=True, verbose_name='creation date'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='template',
|
||||
name='last_changed',
|
||||
field=models.DateTimeField(auto_now=True, verbose_name='last changed'),
|
||||
),
|
||||
]
|
||||
|
|
@ -1,16 +1,17 @@
|
|||
from dbtemplates.conf import settings
|
||||
from dbtemplates.utils.cache import (
|
||||
add_template_to_cache,
|
||||
remove_cached_template,
|
||||
)
|
||||
from dbtemplates.utils.template import get_template_source
|
||||
# -*- coding: utf-8 -*-
|
||||
from datetime import datetime
|
||||
|
||||
from django.contrib.sites.managers import CurrentSiteManager
|
||||
from django.contrib.sites.models import Site
|
||||
from django.db import models
|
||||
from django.db.models import signals
|
||||
from django.template import TemplateDoesNotExist
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.template import TemplateDoesNotExist
|
||||
from django.template.loader import find_template_source
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
|
||||
from django.contrib.sites.models import Site
|
||||
from django.contrib.sites.managers import CurrentSiteManager
|
||||
|
||||
from dbtemplates import settings
|
||||
|
||||
|
||||
class Template(models.Model):
|
||||
|
|
@ -18,15 +19,14 @@ class Template(models.Model):
|
|||
Defines a template model for use with the database template loader.
|
||||
The field ``name`` is the equivalent to the filename of a static template.
|
||||
"""
|
||||
id = models.AutoField(primary_key=True, verbose_name=_('ID'),
|
||||
serialize=False, auto_created=True)
|
||||
name = models.CharField(_('name'), max_length=100,
|
||||
name = models.CharField(_('name'), unique=True, max_length=100,
|
||||
help_text=_("Example: 'flatpages/default.html'"))
|
||||
content = models.TextField(_('content'), blank=True)
|
||||
sites = models.ManyToManyField(Site, verbose_name=_('sites'),
|
||||
blank=True)
|
||||
creation_date = models.DateTimeField(_('creation date'), auto_now_add=True)
|
||||
last_changed = models.DateTimeField(_('last changed'), auto_now=True)
|
||||
sites = models.ManyToManyField(Site)
|
||||
creation_date = models.DateTimeField(_('creation date'),
|
||||
default=datetime.now)
|
||||
last_changed = models.DateTimeField(_('last changed'),
|
||||
default=datetime.now)
|
||||
|
||||
objects = models.Manager()
|
||||
on_site = CurrentSiteManager('sites')
|
||||
|
|
@ -37,44 +37,72 @@ class Template(models.Model):
|
|||
verbose_name_plural = _('templates')
|
||||
ordering = ('name',)
|
||||
|
||||
def __str__(self):
|
||||
def __unicode__(self):
|
||||
return self.name
|
||||
|
||||
def populate(self, name=None):
|
||||
"""
|
||||
Tries to find a template with the same name and populates
|
||||
the content field if found.
|
||||
"""
|
||||
if name is None:
|
||||
name = self.name
|
||||
try:
|
||||
source = get_template_source(name)
|
||||
if source:
|
||||
self.content = source
|
||||
except TemplateDoesNotExist:
|
||||
pass
|
||||
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
self.last_changed = datetime.now()
|
||||
# If content is empty look for a template with the given name and
|
||||
# populate the template instance with its content.
|
||||
if settings.DBTEMPLATES_AUTO_POPULATE_CONTENT and not self.content:
|
||||
self.populate()
|
||||
super().save(*args, **kwargs)
|
||||
if not self.content:
|
||||
try:
|
||||
source, origin = find_template_source(self.name)
|
||||
if source:
|
||||
self.content = source
|
||||
except TemplateDoesNotExist:
|
||||
pass
|
||||
super(Template, self).save(*args, **kwargs)
|
||||
|
||||
def get_cache_backend():
|
||||
path = settings.CACHE_BACKEND
|
||||
if path:
|
||||
i = path.rfind('.')
|
||||
module, attr = path[:i], path[i+1:]
|
||||
try:
|
||||
mod = __import__(module, {}, {}, [attr])
|
||||
except ImportError, e:
|
||||
raise ImproperlyConfigured(
|
||||
'Error importing dbtemplates cache backend %s: "%s"' %
|
||||
(module, e))
|
||||
try:
|
||||
cls = getattr(mod, attr)
|
||||
except AttributeError:
|
||||
raise ImproperlyConfigured(
|
||||
'Module "%s" does not define a "%s" cache backend' %
|
||||
(module, attr))
|
||||
return cls()
|
||||
return False
|
||||
|
||||
backend = get_cache_backend()
|
||||
|
||||
def add_default_site(instance, **kwargs):
|
||||
"""
|
||||
Called via Django's signals to cache the templates, if the template
|
||||
in the database was added or changed, only if
|
||||
DBTEMPLATES_ADD_DEFAULT_SITE setting is set.
|
||||
in the database was added or changed, only if DBTEMPLATES_ADD_DEFAULT_SITE
|
||||
setting is set.
|
||||
"""
|
||||
if not settings.DBTEMPLATES_ADD_DEFAULT_SITE:
|
||||
return
|
||||
current_site = Site.objects.get_current()
|
||||
if current_site not in instance.sites.all():
|
||||
instance.sites.add(current_site)
|
||||
|
||||
if settings.ADD_DEFAULT_SITE:
|
||||
current_site = Site.objects.get_current()
|
||||
if current_site not in instance.sites.all():
|
||||
instance.sites.add(current_site)
|
||||
|
||||
signals.post_save.connect(add_default_site, sender=Template)
|
||||
signals.post_save.connect(add_template_to_cache, sender=Template)
|
||||
signals.pre_delete.connect(remove_cached_template, sender=Template)
|
||||
|
||||
def add_template_to_cache(instance, **kwargs):
|
||||
"""
|
||||
Called via Django's signals to cache the templates, if the template
|
||||
in the database was added or changed.
|
||||
"""
|
||||
remove_cached_template(instance)
|
||||
backend.save(instance.name, instance.content)
|
||||
|
||||
def remove_cached_template(instance, **kwargs):
|
||||
"""
|
||||
Called via Django's signals to remove cached templates, if the template
|
||||
in the database was changed or deleted.
|
||||
"""
|
||||
backend.remove(instance.name)
|
||||
|
||||
if backend:
|
||||
signals.post_save.connect(add_template_to_cache, sender=Template)
|
||||
signals.pre_delete.connect(remove_cached_template, sender=Template)
|
||||
|
|
|
|||
17
dbtemplates/settings.py
Normal file
17
dbtemplates/settings.py
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
import os
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
|
||||
CACHE_BACKEND = getattr(settings, 'DBTEMPLATES_CACHE_BACKEND', None)
|
||||
|
||||
ADD_DEFAULT_SITE = getattr(settings, 'DBTEMPLATES_ADD_DEFAULT_SITE', True)
|
||||
|
||||
MEDIA_PREFIX = getattr(settings, 'DBTEMPLATES_MEDIA_PREFIX',
|
||||
os.path.join(settings.MEDIA_ROOT, 'dbtemplates'))
|
||||
|
||||
USE_REVERSION = getattr(settings, 'DBTEMPLATES_USE_REVERSION', False)
|
||||
|
||||
if USE_REVERSION and 'reversion'not in settings.INSTALLED_APPS:
|
||||
raise ImproperlyConfigured("Please add reversion to your INSTALLED_APPS setting to make use of it in dbtemplates.")
|
||||
|
||||
USE_CODEMIRROR = getattr(settings, 'DBTEMPLATES_USE_CODEMIRROR', False)
|
||||
|
|
@ -1,175 +0,0 @@
|
|||
import os
|
||||
import shutil
|
||||
import tempfile
|
||||
from unittest import mock
|
||||
|
||||
from django.conf import settings as django_settings
|
||||
from django.core.cache.backends.base import BaseCache
|
||||
from django.core.management import call_command
|
||||
from django.template import loader, TemplateDoesNotExist
|
||||
from django.test import TestCase
|
||||
|
||||
from django.contrib.sites.models import Site
|
||||
|
||||
from dbtemplates.conf import settings
|
||||
from dbtemplates.models import Template
|
||||
from dbtemplates.utils.cache import get_cache_backend, get_cache_key
|
||||
from dbtemplates.utils.template import (get_template_source,
|
||||
check_template_syntax)
|
||||
from dbtemplates.management.commands.sync_templates import (FILES_TO_DATABASE,
|
||||
DATABASE_TO_FILES)
|
||||
|
||||
|
||||
class DbTemplatesTestCase(TestCase):
|
||||
def setUp(self):
|
||||
self.old_TEMPLATES = settings.TEMPLATES
|
||||
if 'dbtemplates.loader.Loader' not in settings.TEMPLATES:
|
||||
loader.template_source_loaders = None
|
||||
settings.TEMPLATES = list(settings.TEMPLATES) + [
|
||||
'dbtemplates.loader.Loader'
|
||||
]
|
||||
|
||||
self.site1, created1 = Site.objects.get_or_create(
|
||||
domain="example.com", name="example.com")
|
||||
self.site2, created2 = Site.objects.get_or_create(
|
||||
domain="example.org", name="example.org")
|
||||
self.t1, _ = Template.objects.get_or_create(
|
||||
name='base.html', content='base')
|
||||
self.t2, _ = Template.objects.get_or_create(
|
||||
name='sub.html', content='sub')
|
||||
self.t2.sites.add(self.site2)
|
||||
|
||||
def tearDown(self):
|
||||
loader.template_source_loaders = None
|
||||
settings.TEMPLATES = self.old_TEMPLATES
|
||||
|
||||
def test_basics(self):
|
||||
self.assertEqual(list(self.t1.sites.all()), [self.site1])
|
||||
self.assertTrue("base" in self.t1.content)
|
||||
self.assertEqual(list(Template.objects.filter(sites=self.site1)),
|
||||
[self.t1, self.t2])
|
||||
self.assertEqual(list(self.t2.sites.all()), [self.site1, self.site2])
|
||||
|
||||
def test_empty_sites(self):
|
||||
old_add_default_site = settings.DBTEMPLATES_ADD_DEFAULT_SITE
|
||||
try:
|
||||
settings.DBTEMPLATES_ADD_DEFAULT_SITE = False
|
||||
self.t3 = Template.objects.create(
|
||||
name='footer.html', content='footer')
|
||||
self.assertEqual(list(self.t3.sites.all()), [])
|
||||
finally:
|
||||
settings.DBTEMPLATES_ADD_DEFAULT_SITE = old_add_default_site
|
||||
|
||||
def test_load_templates_sites(self):
|
||||
old_add_default_site = settings.DBTEMPLATES_ADD_DEFAULT_SITE
|
||||
old_site_id = django_settings.SITE_ID
|
||||
try:
|
||||
settings.DBTEMPLATES_ADD_DEFAULT_SITE = False
|
||||
t_site1 = Template.objects.create(
|
||||
name='copyright.html', content='(c) example.com')
|
||||
t_site1.sites.add(self.site1)
|
||||
t_site2 = Template.objects.create(
|
||||
name='copyright.html', content='(c) example.org')
|
||||
t_site2.sites.add(self.site2)
|
||||
|
||||
django_settings.SITE_ID = Site.objects.create(
|
||||
domain="example.net", name="example.net").id
|
||||
Site.objects.clear_cache()
|
||||
|
||||
self.assertRaises(TemplateDoesNotExist,
|
||||
loader.get_template, "copyright.html")
|
||||
finally:
|
||||
django_settings.SITE_ID = old_site_id
|
||||
settings.DBTEMPLATES_ADD_DEFAULT_SITE = old_add_default_site
|
||||
|
||||
def test_load_templates(self):
|
||||
result = loader.get_template("base.html").render()
|
||||
self.assertEqual(result, 'base')
|
||||
result2 = loader.get_template("sub.html").render()
|
||||
self.assertEqual(result2, 'sub')
|
||||
|
||||
def test_error_templates_creation(self):
|
||||
call_command('create_error_templates', force=True, verbosity=0)
|
||||
self.assertEqual(list(Template.objects.filter(sites=self.site1)),
|
||||
list(Template.objects.filter()))
|
||||
self.assertTrue(Template.objects.filter(name='404.html').exists())
|
||||
|
||||
def test_automatic_sync(self):
|
||||
admin_base_template = get_template_source('admin/base.html')
|
||||
template = Template.objects.create(name='admin/base.html')
|
||||
self.assertEqual(admin_base_template, template.content)
|
||||
|
||||
def test_sync_templates(self):
|
||||
old_template_dirs = settings.TEMPLATES[0].get('DIRS', [])
|
||||
temp_template_dir = tempfile.mkdtemp('dbtemplates')
|
||||
temp_template_path = os.path.join(temp_template_dir, 'temp_test.html')
|
||||
temp_template = open(temp_template_path, 'w', encoding='utf-8')
|
||||
try:
|
||||
temp_template.write('temp test')
|
||||
settings.TEMPLATES[0]['DIRS'] = (temp_template_dir,)
|
||||
# these works well if is not settings patched at runtime
|
||||
# for supporting django < 1.7 tests we must patch dirs in runtime
|
||||
from dbtemplates.management.commands import sync_templates
|
||||
sync_templates.DIRS = settings.TEMPLATES[0]['DIRS']
|
||||
|
||||
self.assertFalse(
|
||||
Template.objects.filter(name='temp_test.html').exists())
|
||||
call_command('sync_templates', force=True,
|
||||
verbosity=0, overwrite=FILES_TO_DATABASE)
|
||||
self.assertTrue(
|
||||
Template.objects.filter(name='temp_test.html').exists())
|
||||
|
||||
t = Template.objects.get(name='temp_test.html')
|
||||
t.content = 'temp test modified'
|
||||
t.save()
|
||||
call_command('sync_templates', force=True,
|
||||
verbosity=0, overwrite=DATABASE_TO_FILES)
|
||||
self.assertEqual('temp test modified',
|
||||
open(temp_template_path,
|
||||
encoding='utf-8').read())
|
||||
|
||||
call_command('sync_templates', force=True, verbosity=0,
|
||||
delete=True, overwrite=DATABASE_TO_FILES)
|
||||
self.assertTrue(os.path.exists(temp_template_path))
|
||||
self.assertFalse(
|
||||
Template.objects.filter(name='temp_test.html').exists())
|
||||
finally:
|
||||
temp_template.close()
|
||||
settings.TEMPLATES[0]['DIRS'] = old_template_dirs
|
||||
shutil.rmtree(temp_template_dir)
|
||||
|
||||
def test_get_cache(self):
|
||||
self.assertTrue(isinstance(get_cache_backend(), BaseCache))
|
||||
|
||||
def test_check_template_syntax(self):
|
||||
bad_template, _ = Template.objects.get_or_create(
|
||||
name='bad.html', content='{% if foo %}Bar')
|
||||
good_template, _ = Template.objects.get_or_create(
|
||||
name='good.html', content='{% if foo %}Bar{% endif %}')
|
||||
self.assertFalse(check_template_syntax(bad_template)[0])
|
||||
self.assertTrue(check_template_syntax(good_template)[0])
|
||||
|
||||
def test_get_cache_name(self):
|
||||
self.assertEqual(get_cache_key('name with spaces'),
|
||||
'dbtemplates::name-with-spaces::1')
|
||||
|
||||
def test_cache_invalidation(self):
|
||||
# Add t1 into the cache of site2
|
||||
self.t1.sites.add(self.site2)
|
||||
with mock.patch('django.contrib.sites.models.SiteManager.get_current',
|
||||
return_value=self.site2):
|
||||
result = loader.get_template("base.html").render()
|
||||
self.assertEqual(result, 'base')
|
||||
|
||||
# Update content
|
||||
self.t1.content = 'new content'
|
||||
self.t1.save()
|
||||
result = loader.get_template("base.html").render()
|
||||
self.assertEqual(result, 'new content')
|
||||
|
||||
# Cache invalidation should work across sites.
|
||||
# Site2 should see the new content.
|
||||
with mock.patch('django.contrib.sites.models.SiteManager.get_current',
|
||||
return_value=self.site2):
|
||||
result = loader.get_template("base.html").render()
|
||||
self.assertEqual(result, 'new content')
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
DBTEMPLATES_CACHE_BACKEND = 'dummy://'
|
||||
|
||||
DATABASE_ENGINE = 'sqlite3'
|
||||
# SQLite does not support removing unique constraints (see #28)
|
||||
SOUTH_TESTS_MIGRATE = False
|
||||
|
||||
SITE_ID = 1
|
||||
|
||||
SECRET_KEY = 'something-something'
|
||||
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.sqlite3',
|
||||
'NAME': ':memory:',
|
||||
}
|
||||
}
|
||||
|
||||
INSTALLED_APPS = [
|
||||
'django.contrib.contenttypes',
|
||||
'django.contrib.sites',
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.admin',
|
||||
'django.contrib.auth',
|
||||
'dbtemplates',
|
||||
]
|
||||
|
||||
MIDDLEWARE = (
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
)
|
||||
|
||||
TEMPLATE_LOADERS = (
|
||||
'django.template.loaders.filesystem.Loader',
|
||||
'django.template.loaders.app_directories.Loader',
|
||||
'dbtemplates.loader.Loader',
|
||||
)
|
||||
|
||||
TEMPLATES = [
|
||||
{
|
||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||
'OPTIONS': {
|
||||
'loaders': TEMPLATE_LOADERS,
|
||||
'context_processors': [
|
||||
'django.contrib.auth.context_processors.auth',
|
||||
'django.contrib.messages.context_processors.messages',
|
||||
]
|
||||
}
|
||||
},
|
||||
]
|
||||
63
dbtemplates/tests.py
Normal file
63
dbtemplates/tests.py
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
from django import VERSION
|
||||
from django.test import TestCase
|
||||
from django.contrib.sites.models import Site
|
||||
from django.template import loader, Context
|
||||
from django.core.management import call_command
|
||||
|
||||
from dbtemplates import settings
|
||||
from dbtemplates.loader import load_template_source
|
||||
|
||||
from dbtemplates.models import Template
|
||||
|
||||
class DbTemplatesTestCase(TestCase):
|
||||
def setUp(self):
|
||||
self.site1, created1 = Site.objects.get_or_create(domain="example.com", name="example.com")
|
||||
self.site2, created2 = Site.objects.get_or_create(domain="example.org", name="example.org")
|
||||
|
||||
def test_basiscs(self):
|
||||
t1 = Template(name='base.html', content='<html><head></head><body>{% block content %}Welcome at {{ title }}{% endblock %}</body></html>')
|
||||
t1.save()
|
||||
self.assertEqual(Site.objects.get_current(), t1.sites.all()[0])
|
||||
self.assertTrue("Welcome at" in t1.content)
|
||||
|
||||
t2 = Template(name='sub.html', content='{% extends "base.html" %}{% block content %}This is {{ title }}{% endblock %}')
|
||||
t2.save()
|
||||
t2.sites.add(self.site2)
|
||||
|
||||
self.assertEqual(list(Template.objects.filter(sites=self.site1)), [t1, t2])
|
||||
self.assertEqual(list(t2.sites.all()), [self.site1, self.site2])
|
||||
|
||||
def test_load_templates(self):
|
||||
self.test_basiscs()
|
||||
loader.template_source_loaders = [load_template_source]
|
||||
result1 = loader.get_template("base.html").render(Context({'title':'MainPage'}))
|
||||
self.assertEqual(result1, u'<html><head></head><body>Welcome at MainPage</body></html>')
|
||||
|
||||
result2 = loader.get_template("sub.html").render(Context({'title':'SubPage'}))
|
||||
self.assertEqual(result2, u'<html><head></head><body>This is SubPage</body></html>')
|
||||
|
||||
if VERSION[:2] >= (1, 2):
|
||||
from dbtemplates.loader import Loader
|
||||
dbloader = Loader()
|
||||
loader.template_source_loaders = [dbloader.load_template_source]
|
||||
result = loader.get_template("base.html").render(Context({'title':'MainPage'}))
|
||||
self.assertEqual(result, u'<html><head></head><body>Welcome at MainPage</body></html>')
|
||||
result2 = loader.get_template("sub.html").render(Context({'title':'SubPage'}))
|
||||
self.assertEqual(result2, u'<html><head></head><body>This is SubPage</body></html>')
|
||||
|
||||
def test_error_templates_creation(self):
|
||||
call_command('create_error_templates', force=True, verbosity=0)
|
||||
self.assertEqual(list(Template.objects.filter(sites=self.site1)),
|
||||
list(Template.objects.filter()))
|
||||
|
||||
def test_disabling_default_site(self):
|
||||
old_add_default_site = settings.ADD_DEFAULT_SITE
|
||||
settings.ADD_DEFAULT_SITE = False
|
||||
t3 = Template.objects.create(name='footer.html', content='ohai')
|
||||
self.assertEqual(list(t3.sites.all()), [])
|
||||
settings.ADD_DEFAULT_SITE = old_add_default_site
|
||||
|
||||
def test_automatic_sync(self):
|
||||
admin_base_template, origin = loader.find_template_source('admin/base.html')
|
||||
template = Template.objects.create(name='admin/base.html')
|
||||
self.assertEqual(admin_base_template, template.content)
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
from dbtemplates.conf import settings
|
||||
from django.contrib.sites.models import Site
|
||||
from django.core import signals
|
||||
from django.template.defaultfilters import slugify
|
||||
|
||||
|
||||
def get_cache_backend():
|
||||
"""
|
||||
Compatibilty wrapper for getting Django's cache backend instance
|
||||
"""
|
||||
from django.core.cache import caches
|
||||
cache = caches.create_connection(settings.DBTEMPLATES_CACHE_BACKEND)
|
||||
|
||||
# Some caches -- python-memcached in particular -- need to do a cleanup at
|
||||
# the end of a request cycle. If not implemented in a particular backend
|
||||
# cache.close is a no-op
|
||||
signals.request_finished.connect(cache.close)
|
||||
return cache
|
||||
|
||||
|
||||
cache = get_cache_backend()
|
||||
|
||||
|
||||
def get_cache_key(name, site=None):
|
||||
if site is None:
|
||||
site = Site.objects.get_current()
|
||||
return f"dbtemplates::{slugify(name)}::{site.pk}"
|
||||
|
||||
|
||||
def get_cache_notfound_key(name):
|
||||
return get_cache_key(name) + "::notfound"
|
||||
|
||||
|
||||
def remove_notfound_key(instance):
|
||||
# Remove notfound key as soon as we save the template.
|
||||
cache.delete(get_cache_notfound_key(instance.name))
|
||||
|
||||
|
||||
def set_and_return(cache_key, content, display_name):
|
||||
# Save in cache backend explicitly if manually deleted or invalidated
|
||||
if cache:
|
||||
cache.set(cache_key, content)
|
||||
return (content, display_name)
|
||||
|
||||
|
||||
def add_template_to_cache(instance, **kwargs):
|
||||
"""
|
||||
Called via Django's signals to cache the templates, if the template
|
||||
in the database was added or changed.
|
||||
"""
|
||||
remove_cached_template(instance)
|
||||
remove_notfound_key(instance)
|
||||
cache.set(get_cache_key(instance.name), instance.content)
|
||||
|
||||
|
||||
def remove_cached_template(instance, **kwargs):
|
||||
"""
|
||||
Called via Django's signals to remove cached templates, if the template
|
||||
in the database was changed or deleted.
|
||||
"""
|
||||
for site in instance.sites.all():
|
||||
cache.delete(get_cache_key(instance.name, site=site))
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
from django.template import (Template, TemplateDoesNotExist,
|
||||
TemplateSyntaxError)
|
||||
|
||||
|
||||
def get_loaders():
|
||||
from django.template.loader import _engine_list
|
||||
loaders = []
|
||||
for engine in _engine_list():
|
||||
loaders.extend(engine.engine.template_loaders)
|
||||
return loaders
|
||||
|
||||
|
||||
def get_template_source(name):
|
||||
source = None
|
||||
for loader in get_loaders():
|
||||
if loader.__module__.startswith('dbtemplates.'):
|
||||
# Don't give a damn about dbtemplates' own loader.
|
||||
continue
|
||||
for origin in loader.get_template_sources(name):
|
||||
try:
|
||||
source = loader.get_contents(origin)
|
||||
except (NotImplementedError, TemplateDoesNotExist):
|
||||
continue
|
||||
if source:
|
||||
return source
|
||||
|
||||
|
||||
def check_template_syntax(template):
|
||||
try:
|
||||
Template(template.content)
|
||||
except TemplateSyntaxError as e:
|
||||
return (False, e)
|
||||
return (True, None)
|
||||
130
docs/Makefile
130
docs/Makefile
|
|
@ -1,130 +0,0 @@
|
|||
# Makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
# You can set these variables from the command line.
|
||||
SPHINXOPTS =
|
||||
SPHINXBUILD = sphinx-build
|
||||
PAPER =
|
||||
BUILDDIR = _build
|
||||
|
||||
# Internal variables.
|
||||
PAPEROPT_a4 = -D latex_paper_size=a4
|
||||
PAPEROPT_letter = -D latex_paper_size=letter
|
||||
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
|
||||
|
||||
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest
|
||||
|
||||
help:
|
||||
@echo "Please use \`make <target>' where <target> is one of"
|
||||
@echo " html to make standalone HTML files"
|
||||
@echo " dirhtml to make HTML files named index.html in directories"
|
||||
@echo " singlehtml to make a single large HTML file"
|
||||
@echo " pickle to make pickle files"
|
||||
@echo " json to make JSON files"
|
||||
@echo " htmlhelp to make HTML files and a HTML help project"
|
||||
@echo " qthelp to make HTML files and a qthelp project"
|
||||
@echo " devhelp to make HTML files and a Devhelp project"
|
||||
@echo " epub to make an epub"
|
||||
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
|
||||
@echo " latexpdf to make LaTeX files and run them through pdflatex"
|
||||
@echo " text to make text files"
|
||||
@echo " man to make manual pages"
|
||||
@echo " changes to make an overview of all changed/added/deprecated items"
|
||||
@echo " linkcheck to check all external links for integrity"
|
||||
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
|
||||
|
||||
clean:
|
||||
-rm -rf $(BUILDDIR)/*
|
||||
|
||||
html:
|
||||
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
|
||||
|
||||
dirhtml:
|
||||
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
|
||||
|
||||
singlehtml:
|
||||
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
|
||||
@echo
|
||||
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
|
||||
|
||||
pickle:
|
||||
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
|
||||
@echo
|
||||
@echo "Build finished; now you can process the pickle files."
|
||||
|
||||
json:
|
||||
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
|
||||
@echo
|
||||
@echo "Build finished; now you can process the JSON files."
|
||||
|
||||
htmlhelp:
|
||||
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
|
||||
@echo
|
||||
@echo "Build finished; now you can run HTML Help Workshop with the" \
|
||||
".hhp project file in $(BUILDDIR)/htmlhelp."
|
||||
|
||||
qthelp:
|
||||
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
|
||||
@echo
|
||||
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
|
||||
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
|
||||
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/asd.qhcp"
|
||||
@echo "To view the help file:"
|
||||
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/asd.qhc"
|
||||
|
||||
devhelp:
|
||||
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
|
||||
@echo
|
||||
@echo "Build finished."
|
||||
@echo "To view the help file:"
|
||||
@echo "# mkdir -p $$HOME/.local/share/devhelp/asd"
|
||||
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/asd"
|
||||
@echo "# devhelp"
|
||||
|
||||
epub:
|
||||
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
|
||||
@echo
|
||||
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
|
||||
|
||||
latex:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo
|
||||
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
|
||||
@echo "Run \`make' in that directory to run these through (pdf)latex" \
|
||||
"(use \`make latexpdf' here to do that automatically)."
|
||||
|
||||
latexpdf:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo "Running LaTeX files through pdflatex..."
|
||||
make -C $(BUILDDIR)/latex all-pdf
|
||||
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
|
||||
|
||||
text:
|
||||
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
|
||||
@echo
|
||||
@echo "Build finished. The text files are in $(BUILDDIR)/text."
|
||||
|
||||
man:
|
||||
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
|
||||
@echo
|
||||
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
|
||||
|
||||
changes:
|
||||
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
|
||||
@echo
|
||||
@echo "The overview file is in $(BUILDDIR)/changes."
|
||||
|
||||
linkcheck:
|
||||
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
|
||||
@echo
|
||||
@echo "Link check complete; look for any errors in the above output " \
|
||||
"or in $(BUILDDIR)/linkcheck/output.txt."
|
||||
|
||||
doctest:
|
||||
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
|
||||
@echo "Testing of doctests in the sources finished, look at the " \
|
||||
"results in $(BUILDDIR)/doctest/output.txt."
|
||||
230
docs/_theme/nature/static/nature.css_t
vendored
Normal file
230
docs/_theme/nature/static/nature.css_t
vendored
Normal file
|
|
@ -0,0 +1,230 @@
|
|||
/**
|
||||
* Sphinx stylesheet -- default theme
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*/
|
||||
|
||||
@import url("basic.css");
|
||||
|
||||
/* -- page layout ----------------------------------------------------------- */
|
||||
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
font-size: 100%;
|
||||
background-color: #111;
|
||||
color: #555;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
div.documentwrapper {
|
||||
float: left;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
div.bodywrapper {
|
||||
margin: 0 0 0 300px;
|
||||
}
|
||||
|
||||
hr{
|
||||
border: 1px solid #B1B4B6;
|
||||
}
|
||||
|
||||
div.document {
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
div.body {
|
||||
background-color: #ffffff;
|
||||
color: #3E4349;
|
||||
padding: 0 30px 30px 30px;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
div.footer {
|
||||
color: #555;
|
||||
width: 100%;
|
||||
padding: 13px 0;
|
||||
text-align: center;
|
||||
font-size: 75%;
|
||||
}
|
||||
|
||||
div.footer a {
|
||||
color: #444;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
div.related {
|
||||
background-color: #6BA81E;
|
||||
line-height: 32px;
|
||||
color: #fff;
|
||||
text-shadow: 0px 1px 0 #444;
|
||||
font-size: 0.80em;
|
||||
}
|
||||
|
||||
div.related a {
|
||||
color: #E2F3CC;
|
||||
}
|
||||
|
||||
div.sphinxsidebar {
|
||||
font-size: 0.75em;
|
||||
line-height: 1.5em;
|
||||
width: 300px
|
||||
}
|
||||
|
||||
div.sphinxsidebarwrapper{
|
||||
padding: 20px 0;
|
||||
}
|
||||
|
||||
div.sphinxsidebar h3,
|
||||
div.sphinxsidebar h4 {
|
||||
font-family: Arial, sans-serif;
|
||||
color: #222;
|
||||
font-size: 1.2em;
|
||||
font-weight: normal;
|
||||
margin: 0;
|
||||
padding: 5px 10px;
|
||||
background-color: #ddd;
|
||||
text-shadow: 1px 1px 0 white
|
||||
}
|
||||
|
||||
div.sphinxsidebar h4{
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
div.sphinxsidebar h3 a {
|
||||
color: #444;
|
||||
}
|
||||
|
||||
|
||||
div.sphinxsidebar p {
|
||||
color: #888;
|
||||
padding: 5px 20px;
|
||||
}
|
||||
|
||||
div.sphinxsidebar p.topless {
|
||||
}
|
||||
|
||||
div.sphinxsidebar ul {
|
||||
margin: 10px 10px 10px 20px;
|
||||
padding: 0;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
div.sphinxsidebar a {
|
||||
color: #444;
|
||||
}
|
||||
|
||||
div.sphinxsidebar input {
|
||||
border: 1px solid #ccc;
|
||||
font-family: sans-serif;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
div.sphinxsidebar input[type=text]{
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
/* -- body styles ----------------------------------------------------------- */
|
||||
|
||||
a {
|
||||
color: #005B81;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #E32E00;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
div.body h1,
|
||||
div.body h2,
|
||||
div.body h3,
|
||||
div.body h4,
|
||||
div.body h5,
|
||||
div.body h6 {
|
||||
font-family: Arial, sans-serif;
|
||||
background-color: #BED4EB;
|
||||
font-weight: normal;
|
||||
color: #212224;
|
||||
margin: 30px 0px 10px 0px;
|
||||
padding: 5px 0 5px 10px;
|
||||
text-shadow: 0px 1px 0 white
|
||||
}
|
||||
|
||||
div.body h1 { border-top: 20px solid white; margin-top: 0; font-size: 200%; }
|
||||
div.body h2 { font-size: 150%; background-color: #C8D5E3; }
|
||||
div.body h3 { font-size: 120%; background-color: #D8DEE3; }
|
||||
div.body h4 { font-size: 110%; background-color: #D8DEE3; }
|
||||
div.body h5 { font-size: 100%; background-color: #D8DEE3; }
|
||||
div.body h6 { font-size: 100%; background-color: #D8DEE3; }
|
||||
|
||||
a.headerlink {
|
||||
color: #c60f0f;
|
||||
font-size: 0.8em;
|
||||
padding: 0 4px 0 4px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a.headerlink:hover {
|
||||
background-color: #c60f0f;
|
||||
color: white;
|
||||
}
|
||||
|
||||
div.body p, div.body dd, div.body li {
|
||||
line-height: 1.5em;
|
||||
}
|
||||
|
||||
div.admonition p.admonition-title + p {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
div.highlight{
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
div.note {
|
||||
background-color: #eee;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
|
||||
div.seealso {
|
||||
background-color: #ffc;
|
||||
border: 1px solid #ff6;
|
||||
}
|
||||
|
||||
div.topic {
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
div.warning {
|
||||
background-color: #ffe4e4;
|
||||
border: 1px solid #f66;
|
||||
}
|
||||
|
||||
p.admonition-title {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
p.admonition-title:after {
|
||||
content: ":";
|
||||
}
|
||||
|
||||
pre {
|
||||
padding: 10px;
|
||||
background-color: White;
|
||||
color: #222;
|
||||
line-height: 1.2em;
|
||||
border: 1px solid #C6C9CB;
|
||||
font-size: 1.2em;
|
||||
margin: 1.5em 0 1.5em 0;
|
||||
-webkit-box-shadow: 1px 1px 1px #d8d8d8;
|
||||
-moz-box-shadow: 1px 1px 1px #d8d8d8;
|
||||
}
|
||||
|
||||
tt {
|
||||
background-color: #ecf0f3;
|
||||
color: #222;
|
||||
padding: 1px 2px;
|
||||
font-size: 1.2em;
|
||||
font-family: monospace;
|
||||
}
|
||||
54
docs/_theme/nature/static/pygments.css
vendored
Normal file
54
docs/_theme/nature/static/pygments.css
vendored
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
.c { color: #999988; font-style: italic } /* Comment */
|
||||
.k { font-weight: bold } /* Keyword */
|
||||
.o { font-weight: bold } /* Operator */
|
||||
.cm { color: #999988; font-style: italic } /* Comment.Multiline */
|
||||
.cp { color: #999999; font-weight: bold } /* Comment.preproc */
|
||||
.c1 { color: #999988; font-style: italic } /* Comment.Single */
|
||||
.gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
|
||||
.ge { font-style: italic } /* Generic.Emph */
|
||||
.gr { color: #aa0000 } /* Generic.Error */
|
||||
.gh { color: #999999 } /* Generic.Heading */
|
||||
.gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
|
||||
.go { color: #111 } /* Generic.Output */
|
||||
.gp { color: #555555 } /* Generic.Prompt */
|
||||
.gs { font-weight: bold } /* Generic.Strong */
|
||||
.gu { color: #aaaaaa } /* Generic.Subheading */
|
||||
.gt { color: #aa0000 } /* Generic.Traceback */
|
||||
.kc { font-weight: bold } /* Keyword.Constant */
|
||||
.kd { font-weight: bold } /* Keyword.Declaration */
|
||||
.kp { font-weight: bold } /* Keyword.Pseudo */
|
||||
.kr { font-weight: bold } /* Keyword.Reserved */
|
||||
.kt { color: #445588; font-weight: bold } /* Keyword.Type */
|
||||
.m { color: #009999 } /* Literal.Number */
|
||||
.s { color: #bb8844 } /* Literal.String */
|
||||
.na { color: #008080 } /* Name.Attribute */
|
||||
.nb { color: #999999 } /* Name.Builtin */
|
||||
.nc { color: #445588; font-weight: bold } /* Name.Class */
|
||||
.no { color: #ff99ff } /* Name.Constant */
|
||||
.ni { color: #800080 } /* Name.Entity */
|
||||
.ne { color: #990000; font-weight: bold } /* Name.Exception */
|
||||
.nf { color: #990000; font-weight: bold } /* Name.Function */
|
||||
.nn { color: #555555 } /* Name.Namespace */
|
||||
.nt { color: #000080 } /* Name.Tag */
|
||||
.nv { color: purple } /* Name.Variable */
|
||||
.ow { font-weight: bold } /* Operator.Word */
|
||||
.mf { color: #009999 } /* Literal.Number.Float */
|
||||
.mh { color: #009999 } /* Literal.Number.Hex */
|
||||
.mi { color: #009999 } /* Literal.Number.Integer */
|
||||
.mo { color: #009999 } /* Literal.Number.Oct */
|
||||
.sb { color: #bb8844 } /* Literal.String.Backtick */
|
||||
.sc { color: #bb8844 } /* Literal.String.Char */
|
||||
.sd { color: #bb8844 } /* Literal.String.Doc */
|
||||
.s2 { color: #bb8844 } /* Literal.String.Double */
|
||||
.se { color: #bb8844 } /* Literal.String.Escape */
|
||||
.sh { color: #bb8844 } /* Literal.String.Heredoc */
|
||||
.si { color: #bb8844 } /* Literal.String.Interpol */
|
||||
.sx { color: #bb8844 } /* Literal.String.Other */
|
||||
.sr { color: #808000 } /* Literal.String.Regex */
|
||||
.s1 { color: #bb8844 } /* Literal.String.Single */
|
||||
.ss { color: #bb8844 } /* Literal.String.Symbol */
|
||||
.bp { color: #999999 } /* Name.Builtin.Pseudo */
|
||||
.vc { color: #ff99ff } /* Name.Variable.Class */
|
||||
.vg { color: #ff99ff } /* Name.Variable.Global */
|
||||
.vi { color: #ff99ff } /* Name.Variable.Instance */
|
||||
.il { color: #009999 } /* Literal.Number.Integer.Long */
|
||||
4
docs/_theme/nature/theme.conf
vendored
Normal file
4
docs/_theme/nature/theme.conf
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
[theme]
|
||||
inherit = basic
|
||||
stylesheet = nature.css
|
||||
pygments_style = tango
|
||||
|
|
@ -1,125 +0,0 @@
|
|||
=================
|
||||
Advanced features
|
||||
=================
|
||||
|
||||
.. _caching:
|
||||
|
||||
Caching
|
||||
=======
|
||||
|
||||
``dbtemplates`` uses Django's default caching infrastructure for caching, and
|
||||
operates automatically when creating, updating or deleting templates in
|
||||
the database.
|
||||
|
||||
To enable one of them you need to specify a setting called
|
||||
``DBTEMPLATES_CACHE_BACKEND`` to one of the valid values Django's
|
||||
``CACHE_BACKEND`` can be set to. E.g.::
|
||||
|
||||
DBTEMPLATES_CACHE_BACKEND = 'memcached://127.0.0.1:11211/'
|
||||
|
||||
.. note::
|
||||
Starting in version 1.0 ``dbtemplates`` allows you also to set the new
|
||||
dict-based ``CACHES`` setting, which was introduced in Django 1.3.
|
||||
|
||||
All you have to do is to provide a new entry in the ``CACHES`` dict
|
||||
named ``'dbtemplates'``, e.g.::
|
||||
|
||||
CACHES = {
|
||||
'dbtemplates': {
|
||||
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
|
||||
'LOCATION': '127.0.0.1:11211',
|
||||
}
|
||||
}
|
||||
|
||||
Please see the `cache documentation`_ if you want to know more about it.
|
||||
|
||||
.. _cache documentation: http://docs.djangoproject.com/en/dev/topics/cache/#setting-up-the-cache
|
||||
|
||||
.. _versioned:
|
||||
|
||||
Versioned storage
|
||||
=================
|
||||
|
||||
``dbtemplates`` comes prepared to use the third party Django app
|
||||
`django-reversion`_, that once installed besides ``dbtemplates`` allows you
|
||||
to jump back to old versions of your templates. It automatically saves every
|
||||
state when you save the template in your database and provides an easy to use
|
||||
interface.
|
||||
|
||||
Please refer to `django-reversion's documentation`_ for more information
|
||||
about how it works.
|
||||
|
||||
.. hint::
|
||||
Just visit the "History" section of each template instance and browse its history.
|
||||
|
||||
Short installation howto
|
||||
------------------------
|
||||
|
||||
1. Get the source from the `django-reversion`_ project site and put it
|
||||
somewhere on your `PYTHONPATH`.
|
||||
2. Add ``reversion`` to the ``INSTALLED_APPS`` setting of your Django project
|
||||
3. Sync your database with ``python manage.py syncdb``
|
||||
4. Set ``DBTEMPLATES_USE_REVERSION`` setting to ``True``
|
||||
|
||||
History compare view
|
||||
--------------------
|
||||
|
||||
You can also use ``dbtemplates`` together with `django-reversion-compare`_ which
|
||||
provides a history compare view to compare two versions of a model which is under
|
||||
reversion.
|
||||
|
||||
.. _django-reversion: https://github.com/etianen/django-reversion
|
||||
.. _django-reversion's documentation: https://django-reversion.readthedocs.io/en/latest/
|
||||
.. _django-reversion-compare: https://github.com/jedie/django-reversion-compare
|
||||
|
||||
|
||||
.. _commands:
|
||||
|
||||
Management commands
|
||||
===================
|
||||
|
||||
``dbtemplates`` comes with two `Django management commands`_ to be used with
|
||||
``django-admin.py`` or ``manage.py``:
|
||||
|
||||
* ``sync_templates``
|
||||
|
||||
Enables you to sync your already existing file systems templates with the
|
||||
database. It will guide you through the whole process.
|
||||
|
||||
* ``create_error_templates``
|
||||
|
||||
Tries to add the two templates ``404.html`` and ``500.html`` that are used
|
||||
by Django when a error occurs.
|
||||
|
||||
* ``check_template_syntax``
|
||||
|
||||
.. versionadded:: 1.2
|
||||
|
||||
Checks the saved templates whether they are valid Django templates.
|
||||
|
||||
.. _Django management commands: http://docs.djangoproject.com/en/dev/ref/django-admin/
|
||||
|
||||
.. _admin_actions:
|
||||
|
||||
Admin actions
|
||||
=============
|
||||
|
||||
``dbtemplates`` provides two `admin actions`_ to be used with Django>=1.1.
|
||||
|
||||
* ``invalidate_cache``
|
||||
|
||||
Invalidates the cache of the selected templates by calling the appropriate
|
||||
cache backend methods.
|
||||
|
||||
* ``repopulate_cache``
|
||||
|
||||
Repopulates the cache with selected templates by invalidating it first and
|
||||
filling then after that.
|
||||
|
||||
* ``check_syntax``
|
||||
|
||||
.. versionadded:: 1.2
|
||||
|
||||
Checks the selected tempaltes for syntax errors.
|
||||
|
||||
.. _admin actions: http://docs.djangoproject.com/en/dev/ref/contrib/admin/actions/
|
||||
|
|
@ -1,428 +0,0 @@
|
|||
Changelog
|
||||
=========
|
||||
|
||||
v5.0 (unreleased)
|
||||
-----------------
|
||||
|
||||
.. warning::
|
||||
|
||||
This is a backwards-incompatible release!
|
||||
|
||||
* Dropped support for Python 3.7 and Django < 4.2.
|
||||
|
||||
* Added support for Python 3.11, 3.12, 3.13.
|
||||
|
||||
* Django 5.x support
|
||||
|
||||
v4.0 (2022-09-3)
|
||||
-----------------
|
||||
|
||||
.. warning::
|
||||
|
||||
This is a backwards-incompatible release!
|
||||
|
||||
* Dropped support for Python 2.7 and Django < 3.2.
|
||||
|
||||
* Added support for Python 3.8, 3.9, 3.10.
|
||||
|
||||
* Moved test runner to GitHub Actions:
|
||||
|
||||
http://github.com/jazzband/django-dbtemplates/actions
|
||||
|
||||
* Django 4.x support
|
||||
|
||||
v3.0 (2019-01-27)
|
||||
-----------------
|
||||
|
||||
.. warning::
|
||||
|
||||
This is a backwards-incompatible release!
|
||||
|
||||
* Dropped support for Django < 1.11.
|
||||
|
||||
* Added support for Django 2.0 and 2.1.
|
||||
|
||||
* Added support for Python 3.7.
|
||||
|
||||
* Recompiled Russian locale.
|
||||
|
||||
* Fixed byte string in migration file that caused the migration
|
||||
system to falsely think that there are new changes.
|
||||
|
||||
* Fixed string representation of template model, e.g. to improve
|
||||
readability in choice fields.
|
||||
|
||||
v2.0 (2016-09-29)
|
||||
-----------------
|
||||
|
||||
.. warning::
|
||||
|
||||
This is a backwards-incompatible release!
|
||||
|
||||
* Moved maintenance to the `Jazzband <https://jazzband.co/>`_
|
||||
|
||||
* Dropped support for Python 2.6
|
||||
|
||||
* Added support for Python 3.4 and 3.5
|
||||
|
||||
* Dropped support for Django < 1.8
|
||||
|
||||
* Removed South migrations. Please use Django's native migration system instead
|
||||
|
||||
* Removed the example project since it's out-of-date quickly
|
||||
|
||||
v1.3.2 (2015-06-15)
|
||||
-------------------
|
||||
|
||||
* support for Django 1.8 (not full, but usable)
|
||||
* support for RedactorJS
|
||||
|
||||
thanks for contrib - @eculver, @kmooney, @volksman
|
||||
|
||||
v1.3.1 (2012-05-23)
|
||||
-------------------
|
||||
|
||||
* Minor release to move away from nose again and use own
|
||||
`django-discover-runner`_.
|
||||
|
||||
.. _`django-discover-runner`: http://pypi.python.org/pypi/django-discover-runner
|
||||
|
||||
v1.3 (2012-05-07)
|
||||
-----------------
|
||||
|
||||
* Dropped support for Django < 1.3 **backwards incompatible**
|
||||
|
||||
* Dropped using versiontools in favor of home made solution.
|
||||
|
||||
* Added optional support for TinyMCE editor instead of the CodeMirror
|
||||
editor (just enable ``DBTEMPLATES_USE_TINYMCE``).
|
||||
|
||||
* Fixed compatibility to Django 1.4's handling of the ``DATABASES``
|
||||
setting. Should also respect database routers now.
|
||||
|
||||
* Fixed an issue of the cache key generation in combination with
|
||||
memcache's inability to stomach spaces.
|
||||
|
||||
* Moved test runner to use nose_ and a hosted CI project at Travis_:
|
||||
http://travis-ci.org/jazzband/django-dbtemplates
|
||||
|
||||
.. _nose: https://nose.readthedocs.io/
|
||||
.. _Travis: http://travis-ci.org
|
||||
|
||||
v1.2.1 (2011-09-07)
|
||||
-------------------
|
||||
|
||||
* Fixed a wrong use of the non-lazy localization tools.
|
||||
|
||||
* Fixed bugs in the documentation.
|
||||
|
||||
* Make use of django-appconf and versiontools.
|
||||
|
||||
v1.2 (2011-08-15)
|
||||
-----------------
|
||||
|
||||
* Refactored the template loader to be even more cache effective.
|
||||
|
||||
* Added ``check_template_syntax`` management command and admin action
|
||||
to make sure the saved templates are valid Django templates.
|
||||
|
||||
v1.1.1 (2011-07-08)
|
||||
-------------------
|
||||
|
||||
* Fixed bug in cache loading (again).
|
||||
|
||||
* Fixed bugs in the documentation.
|
||||
|
||||
.. note::
|
||||
|
||||
Since ``dbtemplates`` removed support for Django lower than 1.2 you
|
||||
have to use the template loader class in the ``TEMPLATE_LOADERS``
|
||||
(``'dbtemplates.loader.Loader'``) and **not** the previosly included
|
||||
function that ended with ``load_template_source``.
|
||||
|
||||
v1.1 (2011-07-06)
|
||||
-----------------
|
||||
|
||||
* **BACKWARDS-INCOMPATIBLE** Requires Django 1.2 or higher.
|
||||
For previous Django versions use an older versions of ``dbtemplates``,
|
||||
e.g.::
|
||||
|
||||
$ pip install "django-dbtemplates<1.1"
|
||||
|
||||
* Added South migrations.
|
||||
|
||||
.. note::
|
||||
|
||||
If you are using South in your Django project, you can easily enable
|
||||
dbtemplates' migrations, *faking* the first migration by using the
|
||||
``--fake`` option of South's ``migrate`` management command::
|
||||
|
||||
$ manage.py migrate --fake 0001 dbtemplates
|
||||
|
||||
Then run the rest of the migrations::
|
||||
|
||||
$ manage.py migrate dbtemplates
|
||||
|
||||
* Removed uniqueness on the ``name`` field of the ``Template`` model. This is
|
||||
needed because there isn't a ``unique_together`` for M2M fields in Django
|
||||
such as the ``sites`` field in the ``Template`` model.
|
||||
|
||||
* Made the ``sites`` field optional to support a way to apply a template to
|
||||
all sites.
|
||||
|
||||
* Added ``--delete`` option to ``sync_templates`` managment command to delete
|
||||
the file or database entry after syncing (depending on used ``--overwrite``
|
||||
mode).
|
||||
|
||||
* Updated translations.
|
||||
|
||||
* Fixed issue with incorrectly splitting paths in ``sync_templates``.
|
||||
|
||||
* Extended tests.
|
||||
|
||||
* Fixed issue with cache settings handling.
|
||||
|
||||
v1.0.1 (2011-04-14)
|
||||
-------------------
|
||||
|
||||
* Minor bugfixes with regard to the new cache handling.
|
||||
|
||||
v1.0 (2011-04-11)
|
||||
-----------------
|
||||
|
||||
.. warning::
|
||||
This is the first stable release of django-dbtemplates which comes with a
|
||||
series of backwards incompatible changes.
|
||||
|
||||
* Removed own caching mechanism in favor of Django based caching mechanism.
|
||||
The ``DBTEMPLATES_CACHE_BACKEND`` is expected to be a valid cache backend
|
||||
URI, just like Django's own ``CACHE_BACKEND`` setting. In Django >= 1.3
|
||||
an ``'dbtemplates'`` entry in the ``CACHES`` setting is also considered
|
||||
valid.
|
||||
|
||||
* Added tox configuration to test ``dbtemplates`` on Python 2.5, 2.6 and 2.7
|
||||
with Django 1.1.X, 1.2.X and 1.3.X.
|
||||
|
||||
* Added Transifex configuration.
|
||||
|
||||
* Use ``STATIC_URL`` setting instead of ``MEDIA_URL`` for the media prefix.
|
||||
Also moved files from media/* to static/* to follow convention introduced
|
||||
in Django 1.3.
|
||||
|
||||
* Use ReadTheDocs for documentation hosting.
|
||||
|
||||
v0.8.0 (2010-11-07)
|
||||
-------------------
|
||||
|
||||
* Added Finnish translation (by jholster)
|
||||
|
||||
* Added --overwrite and --app-first options to sync_templates command (by Alex Kamedov).
|
||||
|
||||
v0.7.4 (2010-09-23)
|
||||
-------------------
|
||||
|
||||
* Fixed tests.
|
||||
|
||||
v0.7.3 (2010-09-21)
|
||||
-------------------
|
||||
|
||||
* Added ``DBTEMPLATES_AUTO_POPULATE_CONTENT`` setting to be able to disable
|
||||
to auto-populating of template content.
|
||||
|
||||
* Fixed cosmetic issue in admin with collapsable fields.
|
||||
|
||||
v0.7.2 (2010-09-04)
|
||||
-------------------
|
||||
|
||||
* Moved to Github again. Sigh.
|
||||
|
||||
v0.7.1 (2010-07-07)
|
||||
-------------------
|
||||
|
||||
* Fixed problem with the CodeMirror textarea, which wasn't completely
|
||||
disabled before.
|
||||
|
||||
* Fixed problem with the ``DBTEMPLATES_MEDIA_PREFIX`` setting, which defaults
|
||||
now to ``os.path.join(settings.MEDIA_ROOT, 'dbtemplates')`` now.
|
||||
|
||||
In other words, if you don't specify a ``DBTEMPLATES_MEDIA_PREFIX`` setting
|
||||
and have the CodeMirror textarea enabled, dbtemplates will look in a
|
||||
subdirectory of your site's ``MEDIA_ROOT`` for the CodeMirror media files.
|
||||
|
||||
v0.7.0 (2010-06-24)
|
||||
-------------------
|
||||
|
||||
* Added CodeMirror_-based syntax highlighting textarea, based on the amaxing
|
||||
work_ by `Nic Pottier`_. Set the ``DBTEMPLATES_USE_CODEMIRROR`` setting
|
||||
to ``True`` to enable it.
|
||||
|
||||
* Make use of the full width in plain textarea mode.
|
||||
|
||||
* Added Chinese translation
|
||||
|
||||
* Added support for Django 1.2
|
||||
|
||||
* Updated French translation
|
||||
|
||||
* Added ``DBTEMPLATES_USE_REVERSION`` setting to be able to explicitely enable
|
||||
reversion support. (Default: ``False``)
|
||||
|
||||
.. _CodeMirror: http://marijn.haverbeke.nl/codemirror/
|
||||
.. _work: https://gist.github.com/368758/86bcafe53c438e2e2a0e3442c3b30f2c6011fbba
|
||||
.. _`Nic Pottier`: http://github.com/nicpottier
|
||||
|
||||
v0.6.1 (2009-10-19)
|
||||
-------------------
|
||||
|
||||
* Fixed issue with default site of a template, added ability to disable
|
||||
default site (``DBTEMPLATES_ADD_DEFAULT_SITE``).
|
||||
|
||||
v0.6.0 (2009-10-09)
|
||||
-------------------
|
||||
|
||||
* Updated and added locales (Danish, Brazilian Portuguese)
|
||||
|
||||
* Fixes an ambiguity problem with the cache invalidation
|
||||
|
||||
* Added ``invalidate_cache`` and ``repopulate_cache`` admin actions
|
||||
|
||||
* Added Sphinx documentation
|
||||
|
||||
v0.5.7
|
||||
------
|
||||
|
||||
* Updates to the docs
|
||||
|
||||
* switch back to Bitbucket
|
||||
|
||||
* fixed tests
|
||||
|
||||
* Added Italian translation
|
||||
|
||||
* list of sites the template is used on
|
||||
|
||||
* fixed bug in ``create_error_template`` command.
|
||||
|
||||
v0.5.4
|
||||
------
|
||||
|
||||
* Made loader and cache backends site-aware.
|
||||
|
||||
* The filesystem cache backend now saves the files under
|
||||
``<dir>/<site_domain>/<file_name>``.
|
||||
|
||||
* The Django cache backend the Site id in the cache key
|
||||
|
||||
* Template is now saved explicitly to backend if not existent in cache
|
||||
(e.g. if deleted manually or invalidated).
|
||||
|
||||
v0.5.3
|
||||
------
|
||||
|
||||
* Removed automatic creation of 404.html and 50v0.html templates and added a
|
||||
new management command for those cases called ``create_error_templates``
|
||||
|
||||
* Also reverted move to Bitbucket
|
||||
|
||||
v0.5.2
|
||||
------
|
||||
|
||||
* Fixed a problem with ``django.contrib.sites`` when its table hasn't been
|
||||
populated yet on initialization of dbtemplates. Thanks for the report,
|
||||
Kevin Fricovsky
|
||||
|
||||
* Added an example Django project and docs for it
|
||||
|
||||
v0.5.1
|
||||
------
|
||||
|
||||
* Removed unneeded code that registered the model with reversion.
|
||||
|
||||
* Updated docs a bit.
|
||||
|
||||
* Moved codebase to Bitbucket.
|
||||
|
||||
* Removed legacy ``sync_templates.py`` script, use ``django-admin.py
|
||||
sync_templates`` from now on.
|
||||
|
||||
v0.5.0
|
||||
------
|
||||
|
||||
* Added support for `django-reversion`_
|
||||
|
||||
* added feature that populates the content field automatically when left
|
||||
empty by using Django's other template loaders
|
||||
|
||||
* added caching backend system with two default backends:
|
||||
|
||||
* ``FileSystemBackend``
|
||||
* ``DjangoCacheBackend``
|
||||
|
||||
More about it in the `blog post`_ and in the docs.
|
||||
|
||||
.. _django-reversion: http://code.google.com/p/django-reversion/
|
||||
.. _blog post: http://jannisleidel.com/2008/11/updates-to-django-dbtemplates-and-half-assed-promise/
|
||||
|
||||
v0.4.7
|
||||
------
|
||||
|
||||
* Minor bugfix
|
||||
|
||||
v0.4.6
|
||||
------
|
||||
|
||||
* Minor doc change and PyPI support
|
||||
|
||||
v0.4.5
|
||||
------
|
||||
|
||||
* fixed the --force option of the sync_templates command
|
||||
|
||||
v0.4.4
|
||||
------
|
||||
|
||||
* fixed error in custom model save() after changes in Django `r8670`_.
|
||||
|
||||
.. _r8670: http://code.djangoproject.com/changeset/8670
|
||||
|
||||
v0.4.3
|
||||
------
|
||||
|
||||
* removed oldforms code
|
||||
|
||||
v0.4.2
|
||||
------
|
||||
|
||||
* added Hebrew translation (by mkriheli)
|
||||
|
||||
v0.4.1
|
||||
------
|
||||
|
||||
* added French (by Roland Frederic) and German locale
|
||||
|
||||
v0.4.0
|
||||
------
|
||||
|
||||
* adds better support for newforms-admin
|
||||
|
||||
* don't forget to load the dbtemplates.admin, e.g. by using
|
||||
django.contrib.admin.autodiscover() in you urls.py
|
||||
|
||||
v0.3.1
|
||||
------
|
||||
|
||||
* adds a new management command *sync_templates* for bidirectional syncing
|
||||
between filesystem and database (backwards-compatible) and
|
||||
FilesystemCaching (thanks, Arne Brodowski!)
|
||||
|
||||
v0.2.5
|
||||
------
|
||||
|
||||
* adds support for newforms-admin
|
||||
|
||||
Support
|
||||
=======
|
||||
|
||||
Please leave your questions and messages on the designated site:
|
||||
|
||||
http://github.com/jazzband/django-dbtemplates/issues/
|
||||
28
docs/conf.py
28
docs/conf.py
|
|
@ -1,3 +1,4 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# django-dbtemplates documentation build configuration file, created by
|
||||
# sphinx-quickstart on Fri Oct 9 14:52:11 2009.
|
||||
|
|
@ -15,7 +16,7 @@ import sys, os
|
|||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
sys.path.append(os.path.abspath('.'))
|
||||
#sys.path.append(os.path.abspath('.'))
|
||||
|
||||
# -- General configuration -----------------------------------------------------
|
||||
|
||||
|
|
@ -36,22 +37,17 @@ source_suffix = '.txt'
|
|||
master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = 'django-dbtemplates'
|
||||
copyright = '2007-2019, Jannis Leidel and contributors'
|
||||
project = u'django-dbtemplates'
|
||||
copyright = u'2010, Jannis Leidel'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
try:
|
||||
from dbtemplates import __version__
|
||||
# The short X.Y version.
|
||||
version = '.'.join(__version__.split('.')[:2])
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = __version__
|
||||
except ImportError:
|
||||
version = release = 'dev'
|
||||
version = '0.7.2'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '0.7.2'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
|
@ -95,7 +91,7 @@ pygments_style = 'sphinx'
|
|||
|
||||
# The theme to use for HTML and HTML Help pages. Major themes that come with
|
||||
# Sphinx are currently 'default' and 'sphinxdoc'.
|
||||
html_theme = 'default'
|
||||
html_theme = 'nature'
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
|
|
@ -103,7 +99,7 @@ html_theme = 'default'
|
|||
#html_theme_options = {}
|
||||
|
||||
# Add any paths that contain custom themes here, relative to this directory.
|
||||
# html_theme_path = ['_theme']
|
||||
html_theme_path = ['_theme']
|
||||
|
||||
# The name for this set of Sphinx documents. If None, it defaults to
|
||||
# "<project> v<release> documentation".
|
||||
|
|
@ -124,7 +120,7 @@ html_short_title = "django-dbtemplates"
|
|||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
# html_static_path = ['_static']
|
||||
html_static_path = ['_static']
|
||||
|
||||
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
||||
# using the given strftime format.
|
||||
|
|
@ -176,8 +172,8 @@ htmlhelp_basename = 'django-dbtemplatesdoc'
|
|||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title, author, documentclass [howto/manual]).
|
||||
latex_documents = [
|
||||
('index', 'django-dbtemplates.tex', 'django-dbtemplates Documentation',
|
||||
'Jannis Leidel and contributors', 'manual'),
|
||||
('index', 'django-dbtemplates.tex', u'django-dbtemplates Documentation',
|
||||
u'Jannis Leidel', 'manual'),
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
|
|
|
|||
|
|
@ -1,19 +1,10 @@
|
|||
django-dbtemplates
|
||||
==================
|
||||
|
||||
``dbtemplates`` is a Django app that consists of two parts:
|
||||
|
||||
1. It allows you to store templates in your database
|
||||
2. It provides `template loader`_ that enables Django to load the
|
||||
templates from the database
|
||||
|
||||
It also features optional support for :ref:`versioned storage <versioned>`
|
||||
and :ref:`django-admin command <commands>`, integrates with Django's
|
||||
:ref:`caching system <caching>` and the :ref:`admin actions <admin_actions>`.
|
||||
|
||||
Please see https://django-dbtemplates.readthedocs.io/ for more details.
|
||||
|
||||
The source code and issue tracker can be found on Github: https://github.com/jazzband/django-dbtemplates
|
||||
``dbtemplates`` is a Django app that comes with to parts: It allows you to
|
||||
create templates that are saved in your database, and it provides a so called
|
||||
`template loader`_, a function that enables Django to find the templates you
|
||||
created in the database.
|
||||
|
||||
.. _template loader: http://docs.djangoproject.com/en/dev/ref/templates/api/#loading-templates
|
||||
|
||||
|
|
@ -23,6 +14,3 @@ Contents:
|
|||
:maxdepth: 2
|
||||
|
||||
overview
|
||||
advanced
|
||||
settings
|
||||
changelog
|
||||
170
docs/make.bat
170
docs/make.bat
|
|
@ -1,170 +0,0 @@
|
|||
@ECHO OFF
|
||||
|
||||
REM Command file for Sphinx documentation
|
||||
|
||||
if "%SPHINXBUILD%" == "" (
|
||||
set SPHINXBUILD=sphinx-build
|
||||
)
|
||||
set BUILDDIR=_build
|
||||
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
|
||||
if NOT "%PAPER%" == "" (
|
||||
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
|
||||
)
|
||||
|
||||
if "%1" == "" goto help
|
||||
|
||||
if "%1" == "help" (
|
||||
:help
|
||||
echo.Please use `make ^<target^>` where ^<target^> is one of
|
||||
echo. html to make standalone HTML files
|
||||
echo. dirhtml to make HTML files named index.html in directories
|
||||
echo. singlehtml to make a single large HTML file
|
||||
echo. pickle to make pickle files
|
||||
echo. json to make JSON files
|
||||
echo. htmlhelp to make HTML files and a HTML help project
|
||||
echo. qthelp to make HTML files and a qthelp project
|
||||
echo. devhelp to make HTML files and a Devhelp project
|
||||
echo. epub to make an epub
|
||||
echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
|
||||
echo. text to make text files
|
||||
echo. man to make manual pages
|
||||
echo. changes to make an overview over all changed/added/deprecated items
|
||||
echo. linkcheck to check all external links for integrity
|
||||
echo. doctest to run all doctests embedded in the documentation if enabled
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "clean" (
|
||||
for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
|
||||
del /q /s %BUILDDIR%\*
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "html" (
|
||||
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The HTML pages are in %BUILDDIR%/html.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "dirhtml" (
|
||||
%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "singlehtml" (
|
||||
%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "pickle" (
|
||||
%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; now you can process the pickle files.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "json" (
|
||||
%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; now you can process the JSON files.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "htmlhelp" (
|
||||
%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; now you can run HTML Help Workshop with the ^
|
||||
.hhp project file in %BUILDDIR%/htmlhelp.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "qthelp" (
|
||||
%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; now you can run "qcollectiongenerator" with the ^
|
||||
.qhcp project file in %BUILDDIR%/qthelp, like this:
|
||||
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\asd.qhcp
|
||||
echo.To view the help file:
|
||||
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\asd.ghc
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "devhelp" (
|
||||
%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "epub" (
|
||||
%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The epub file is in %BUILDDIR%/epub.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "latex" (
|
||||
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "text" (
|
||||
%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The text files are in %BUILDDIR%/text.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "man" (
|
||||
%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The manual pages are in %BUILDDIR%/man.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "changes" (
|
||||
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.The overview file is in %BUILDDIR%/changes.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "linkcheck" (
|
||||
%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Link check complete; look for any errors in the above output ^
|
||||
or in %BUILDDIR%/linkcheck/output.txt.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "doctest" (
|
||||
%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Testing of doctests in the sources finished, look at the ^
|
||||
results in %BUILDDIR%/doctest/output.txt.
|
||||
goto end
|
||||
)
|
||||
|
||||
:end
|
||||
|
|
@ -1,9 +1,28 @@
|
|||
===================================
|
||||
Database template loader for Django
|
||||
===================================
|
||||
|
||||
``dbtemplates`` is a Django app that comes with to parts: It allows you to
|
||||
create templates that are saved in your database, and it provides a so called
|
||||
`template loader`_, a function that enables Django to find the templates you
|
||||
created in the database.
|
||||
|
||||
It also includes a extensible caching mechanism and supports version control
|
||||
of the templates saved in the database.
|
||||
|
||||
.. _template loader: http://docs.djangoproject.com/en/dev/ref/templates/api/#loading-templates
|
||||
|
||||
.. contents:: Table of Contents
|
||||
:backlinks: none
|
||||
|
||||
Setup
|
||||
=====
|
||||
|
||||
1. Get the source from the `Git repository`_ or install it from the
|
||||
Python Package Index by running ``pip install django-dbtemplates``.
|
||||
2. Edit the settings.py of your Django site:
|
||||
1. Get the source from the `Mercurial repository`_ or install it from the
|
||||
Python Package Index by running ``easy_install django-dbtemplates`` or
|
||||
``pip django-dbtemplates``.
|
||||
2. Follow the instructions in the INSTALL file
|
||||
3. Edit the settings.py of your Django site:
|
||||
|
||||
* Add ``dbtemplates`` to the ``INSTALLED_APPS`` setting
|
||||
|
||||
|
|
@ -23,54 +42,28 @@ Setup
|
|||
'dbtemplates',
|
||||
)
|
||||
|
||||
* Add ``dbtemplates.loader.Loader`` to the ``TEMPLATES.OPTIONS.loaders`` list
|
||||
in the settings.py of your Django project.
|
||||
* Add ``dbtemplates.loader.load_template_source`` to the
|
||||
``TEMPLATE_LOADERS`` list in the settings.py of your Django project
|
||||
|
||||
It should look something like this::
|
||||
|
||||
TEMPLATES = [
|
||||
{
|
||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||
'DIRS': [ # your template dirs here
|
||||
],
|
||||
'APP_DIRS': False,
|
||||
'OPTIONS': {
|
||||
'context_processors': [
|
||||
'django.contrib.auth.context_processors.auth',
|
||||
'django.template.context_processors.debug',
|
||||
'django.template.context_processors.i18n',
|
||||
'django.template.context_processors.media',
|
||||
'django.template.context_processors.static',
|
||||
'django.template.context_processors.tz',
|
||||
'django.contrib.messages.context_processors.messages',
|
||||
'django.template.context_processors.request',
|
||||
],
|
||||
'loaders': [
|
||||
'django.template.loaders.filesystem.Loader',
|
||||
'django.template.loaders.app_directories.Loader',
|
||||
'dbtemplates.loader.Loader',
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
TEMPLATE_LOADERS = (
|
||||
'django.template.loaders.filesystem.load_template_source',
|
||||
'django.template.loaders.app_directories.load_template_source',
|
||||
'dbtemplates.loader.load_template_source',
|
||||
)
|
||||
|
||||
The order of ``TEMPLATES.OPTIONS.loaders`` is important. In the former
|
||||
example, templates from the database will be used as a fallback (ie. when
|
||||
the template does not exists in other locations). If you want the template
|
||||
from the database to be used to override templates in other locations,
|
||||
put ``dbtemplates.loader.Loader`` at the beginning of ``loaders``.
|
||||
4. Sync your database ``python manage.py syncdb``
|
||||
5. Restart your Django server
|
||||
|
||||
3. Sync your database ``python manage.py migrate``
|
||||
4. Restart your Django server
|
||||
|
||||
.. _Git repository: https://github.com/jazzband/django-dbtemplates/
|
||||
.. _Mercurial repository: http://bitbucket.org/jezdez/django-dbtemplates/
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
Creating database templates is pretty simple: Just open the admin interface
|
||||
of your Django-based site in your browser and click on "Templates" in the
|
||||
"Database templates" section.
|
||||
"Dbtemplates" section.
|
||||
|
||||
There you only need to fill in the ``name`` field with the identifier, Django
|
||||
is supposed to use while searching for templates, e.g.
|
||||
|
|
@ -84,3 +77,409 @@ other template loaders. For example, if you have a template called
|
|||
contents in the database, you just need to leave the content field empty to
|
||||
automatically populate it. That's especially useful if you don't want to
|
||||
copy and paste its content manually to the textarea.
|
||||
|
||||
Example
|
||||
=======
|
||||
|
||||
``dbtemplates`` comes with an example Django project that let's you try it
|
||||
out. The example uses Django's own `flatpages app`_ to enable you to create
|
||||
a simple page using ``dbtemplates``. Flat pages are a perfect fit to
|
||||
dbtemplates since they come prepackaged and are simple to use.
|
||||
|
||||
Here is how it works:
|
||||
|
||||
1. Open your command line and change to the ``example`` directory in the
|
||||
directory with the extracted source distribution.
|
||||
2. Run ``python manage.py syncdb`` and follow the instructions.
|
||||
3. Run ``python manage.py runserver`` and open your favorite browser with the
|
||||
address http://127.0.0.1:8000/admin/.
|
||||
4. Next add a new `Template` object in the ``dbtemplates`` section and use
|
||||
``flatpages/default.html`` as the value for the ``name`` field. For the
|
||||
``content`` field use this example::
|
||||
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/REC-html40/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>{{ flatpage.title }}</title>
|
||||
</head>
|
||||
<body>
|
||||
{{ flatpage.content }}
|
||||
</body>
|
||||
</html>
|
||||
|
||||
5. Return to the home screen of the admin interface and add a new flat page.
|
||||
Use ``/`` (yep, just a forward slash) and whatever ``title`` and
|
||||
``content`` you prefer. Please make sure you select the default site
|
||||
``example.com`` before you save the flat page.
|
||||
6. Visit http://127.0.0.1:8000/ and see the flat page you just created
|
||||
rendered with the ``flatpages/default.html`` template provided by
|
||||
``dbtemplates``.
|
||||
|
||||
.. _flatpages app: http://docs.djangoproject.com/en/dev/ref/contrib/flatpages/
|
||||
|
||||
Settings
|
||||
========
|
||||
|
||||
* ``DBTEMPLATES_ADD_DEFAULT_SITE``
|
||||
|
||||
``dbtemplates`` adds the current site (``settings.SITE_ID``) to the database
|
||||
template when it is created by default. You can disable this feature by
|
||||
setting ``DBTEMPLATES_ADD_DEFAULT_SITE`` to ``False``.
|
||||
|
||||
* ``DBTEMPLATES_CACHE_BACKEND``
|
||||
|
||||
The dotted Python path to the cache backend class. See `Caching`_ for
|
||||
details.
|
||||
|
||||
* ``DBTEMPLATES_CACHE_DIR``
|
||||
|
||||
A directory path that is used by the cache ``FileSystemBackend`` to store
|
||||
the cached templates. See `Caching`_ for details.
|
||||
|
||||
* ``DBTEMPLATES_USE_CODEMIRROR``
|
||||
|
||||
A boolean, if enabled triggers the use of the CodeMirror based editor.
|
||||
Set to ``False`` by default.
|
||||
|
||||
* ``DBTEMPLATES_USE_REVERSION``
|
||||
|
||||
A boolean, if enabled triggers the use of ``django-reversion``.
|
||||
|
||||
* ``DBTEMPLATES_MEDIA_PREFIX``
|
||||
|
||||
The URL prefix for ``dbtemplates``' media -- CSS and JavaScript used by
|
||||
the CodeMirror based editor. Make sure to use a trailing
|
||||
slash, and to have this be different from the ``MEDIA_URL`` setting
|
||||
(since the same URL cannot be mapped onto two different sets of
|
||||
files).
|
||||
|
||||
Caching
|
||||
=======
|
||||
|
||||
Using the default caching
|
||||
-------------------------
|
||||
|
||||
Dbtemplates comes with different backends for caching that are automatically
|
||||
created, updated and deleted when templates are saved in the database by
|
||||
using Django's signal framework.
|
||||
|
||||
To enable one of them you need to specify a setting called
|
||||
``DBTEMPLATES_CACHE_BACKEND`` to one of the following values:
|
||||
|
||||
* ``dbtemplates.cache.FileSystemBackend`` -- File system caching
|
||||
|
||||
The ``FileSystemBackend`` is a simple way to store the templates you have
|
||||
in the database on the filesystem. That's especially useful if you don't
|
||||
use a full caching framework like Django is providing.
|
||||
|
||||
To use this backend you need additionally create a setting
|
||||
``DBTEMPLATES_CACHE_DIR`` that contains the full file system path to the
|
||||
directory where ``dbtemplates`` should create the cache files in.
|
||||
|
||||
* ``dbtemplates.cache.DjangoCacheBackend`` -- Django cache
|
||||
|
||||
The ``DjangoCacheBackend`` is a thin wrapper around Django's caching
|
||||
framework that enables you to use advanced caching solutions like
|
||||
memcached or database caching. Please see the `cache documentation`_ if
|
||||
you want to know more about it.
|
||||
|
||||
.. _cache documentation: http://docs.djangoproject.com/en/dev/topics/cache/#setting-up-the-cache
|
||||
|
||||
Writing your own caching backends
|
||||
---------------------------------
|
||||
|
||||
Writing your own cache backends is perfectly easy since ``dbtemplates``
|
||||
includes a easy-to-use base class in ``dbtemplates.cache.BaseCacheBackend``.
|
||||
|
||||
Just subclass that base backend somewhere in your own code and provide the
|
||||
follwing three reuqired methods:
|
||||
|
||||
* ``load``
|
||||
|
||||
Loads a template from the cache with the given name and returns its
|
||||
contents. Return None if nothing found.
|
||||
|
||||
Arguments:
|
||||
|
||||
* ``name`` - name of the template
|
||||
|
||||
* ``save``
|
||||
|
||||
Saves the passed template contents with the passed name in the cache.
|
||||
|
||||
Arguments:
|
||||
|
||||
* ``name`` - name of the template
|
||||
* ``content`` - contents of the template
|
||||
|
||||
* ``remove``
|
||||
|
||||
Removes the template with the passed name from the cache.
|
||||
|
||||
Arguments:
|
||||
|
||||
* ``name`` - name of the template
|
||||
|
||||
Please see also the `source of the default backends`_ to see how it works.
|
||||
|
||||
.. _source of the default backends: http://bitbucket.org/jezdez/django-dbtemplates/src/tip/dbtemplates/cache.py
|
||||
|
||||
Versionizing your templates
|
||||
===========================
|
||||
|
||||
``dbtemplates`` comes prepared to use the third party Django app
|
||||
`django-reversion`_, that once installed besides ``dbtemplates`` allows you
|
||||
to jump back to old versions of your templates. It automatically saves every
|
||||
state when you save the template in your database and provides an easy to use
|
||||
interface.
|
||||
|
||||
Please refer to `django-reversion's documentation`_ for more information
|
||||
about how it works. ``dbtemplates`` uses ``django-reversion`` if the
|
||||
``DBTEMPLATES_USE_REVERSION`` setting is ``True``. Just visit the
|
||||
"History" section of each template instance and browse its history.
|
||||
|
||||
Short installation howto
|
||||
------------------------
|
||||
|
||||
1. Get the source from the `django-reversion`_ project site and put it
|
||||
somewhere on your `PYTHONPATH`.
|
||||
2. Add ``reversion`` to the ``INSTALLED_APPS`` setting of your Django project
|
||||
3. Sync your database with ``python manage.py syncdb``
|
||||
|
||||
.. _django-reversion: http://code.google.com/p/django-reversion/
|
||||
.. _django-reversion's documentation: http://code.google.com/p/django-reversion/wiki/GettingStarted
|
||||
|
||||
Management commands
|
||||
===================
|
||||
|
||||
``dbtemplates`` comes with two `Django management commands`_ to be used with
|
||||
``django-admin.py`` or ``manage.py``:
|
||||
|
||||
* ``sync_templates``
|
||||
|
||||
Enables you to sync your already existing file systems templates with the
|
||||
database. It will guide you through the whole process.
|
||||
|
||||
* ``create_error_templates``
|
||||
|
||||
Tries to add the two templates ``404.html`` and ``500.html`` that are used
|
||||
by Django when a error occurs.
|
||||
|
||||
.. _Django management commands: http://docs.djangoproject.com/en/dev/ref/django-admin/
|
||||
|
||||
Admin actions
|
||||
=============
|
||||
|
||||
``dbtemplates`` provides two `admin actions`_ to be used with Django>=1.1.
|
||||
|
||||
* ``invalidate_cache``
|
||||
|
||||
Invalidates the cache of the selected templates by calling the appropriate
|
||||
cache backend methods.
|
||||
|
||||
* ``repopulate_cache``
|
||||
|
||||
Repopulates the cache with selected templates by invalidating it first and
|
||||
filling then after that.
|
||||
|
||||
.. _admin actions: http://docs.djangoproject.com/en/1.1/ref/contrib/admin/actions/#ref-contrib-admin-actions
|
||||
|
||||
Changelog
|
||||
=========
|
||||
|
||||
0.7.2 (09-04-10)
|
||||
----------------
|
||||
|
||||
* Moved to Github again. Sigh.
|
||||
|
||||
0.7.1 (07-07-10)
|
||||
----------------
|
||||
|
||||
* Fixed problem with the CodeMirror textarea, which wasn't completely
|
||||
disabled before.
|
||||
|
||||
* Fixed problem with the ``DBTEMPLATES_MEDIA_PREFIX`` setting, which defaults
|
||||
now to ``os.path.join(settings.MEDIA_ROOT, 'dbtemplates')`` now.
|
||||
|
||||
In other words, if you don't specify a ``DBTEMPLATES_MEDIA_PREFIX`` setting
|
||||
and have the CodeMirror textarea enabled, dbtemplates will look in a
|
||||
subdirectory of your site's ``MEDIA_ROOT`` for the CodeMirror media files.
|
||||
|
||||
0.7.0 (06-24-10)
|
||||
----------------
|
||||
|
||||
* Added CodeMirror_-based syntax highlighting textarea, based on the amaxing
|
||||
work_ by `Nic Pottier`_. Set the ``DBTEMPLATES_USE_CODEMIRROR`` setting
|
||||
to ``True`` to enable it.
|
||||
|
||||
* Make use of the full width in plain textarea mode.
|
||||
|
||||
* Added Chinese translation
|
||||
|
||||
* Added support for Django 1.2
|
||||
|
||||
* Updated French translation
|
||||
|
||||
* Added ``DBTEMPLATES_USE_REVERSION`` setting to be able to explicitely enable
|
||||
reversion support. (Default: ``False``)
|
||||
|
||||
.. _CodeMirror: http://marijn.haverbeke.nl/codemirror/
|
||||
.. _work: https://gist.github.com/368758/86bcafe53c438e2e2a0e3442c3b30f2c6011fbba
|
||||
.. _`Nic Pottier`: http://github.com/nicpottier
|
||||
|
||||
0.6.1 (10-19-09):
|
||||
-----------------
|
||||
|
||||
* Fixed issue with default site of a template, added ability to disable
|
||||
default site (``DBTEMPLATES_ADD_DEFAULT_SITE``).
|
||||
|
||||
0.6.0 (10-09-09):
|
||||
-----------------
|
||||
|
||||
* Updated and added locales (Danish, Brazilian Portuguese)
|
||||
|
||||
* Fixes an ambiguity problem with the cache invalidation
|
||||
|
||||
* Added ``invalidate_cache`` and ``repopulate_cache`` admin actions
|
||||
|
||||
* Added Sphinx documentation
|
||||
|
||||
0.5.7
|
||||
-----
|
||||
|
||||
* Updates to the docs
|
||||
|
||||
* switch back to Bitbucket
|
||||
|
||||
* fixed tests
|
||||
|
||||
* Added Italian translation
|
||||
|
||||
* list of sites the template is used on
|
||||
|
||||
* fixed bug in ``create_error_template`` command.
|
||||
|
||||
0.5.4
|
||||
-----
|
||||
|
||||
* Made loader and cache backends site-aware.
|
||||
|
||||
* The filesystem cache backend now saves the files under
|
||||
``<dir>/<site_domain>/<file_name>``.
|
||||
|
||||
* The Django cache backend the Site id in the cache key
|
||||
|
||||
* Template is now saved explicitly to backend if not existent in cache
|
||||
(e.g. if deleted manually or invalidated).
|
||||
|
||||
0.5.3
|
||||
-----
|
||||
|
||||
* Removed automatic creation of 404.html and 500.html templates and added a
|
||||
new management command for those cases called ``create_error_templates``
|
||||
|
||||
* Also reverted move to Bitbucket
|
||||
|
||||
0.5.2
|
||||
-----
|
||||
|
||||
* Fixed a problem with ``django.contrib.sites`` when its table hasn't been
|
||||
populated yet on initialization of dbtemplates. Thanks for the report,
|
||||
Kevin Fricovsky
|
||||
|
||||
* Added an example Django project and docs for it
|
||||
|
||||
0.5.1
|
||||
-----
|
||||
|
||||
* Removed unneeded code that registered the model with reversion.
|
||||
|
||||
* Updated docs a bit.
|
||||
|
||||
* Moved codebase to Bitbucket.
|
||||
|
||||
* Removed legacy ``sync_templates.py`` script, use ``django-admin.py
|
||||
sync_templates`` from now on.
|
||||
|
||||
0.5.0
|
||||
-----
|
||||
|
||||
* Added support for `django-reversion`_
|
||||
|
||||
* added feature that populates the content field automatically when left
|
||||
empty by using Django's other template loaders
|
||||
|
||||
* added caching backend system with two default backends:
|
||||
|
||||
* ``FileSystemBackend``
|
||||
* ``DjangoCacheBackend``
|
||||
|
||||
More about it in the `blog post`_ and in the docs.
|
||||
|
||||
.. _django-reversion: http://code.google.com/p/django-reversion/
|
||||
.. _blog post: http://jannisleidel.com/2008/11/updates-to-django-dbtemplates-and-half-assed-promise/
|
||||
|
||||
0.4.7
|
||||
-----
|
||||
|
||||
* Minor bugfix
|
||||
|
||||
0.4.6
|
||||
-----
|
||||
|
||||
* Minor doc change and PyPI support
|
||||
|
||||
0.4.5
|
||||
-----
|
||||
|
||||
* fixed the --force option of the sync_templates command
|
||||
|
||||
0.4.4
|
||||
-----
|
||||
|
||||
* fixed error in custom model save() after changes in Django `r8670`_.
|
||||
|
||||
.. _r8670: http://code.djangoproject.com/changeset/8670
|
||||
|
||||
0.4.3
|
||||
-----
|
||||
|
||||
* removed oldforms code
|
||||
|
||||
0.4.2
|
||||
-----
|
||||
|
||||
* added Hebrew translation (by mkriheli)
|
||||
|
||||
0.4.1
|
||||
-----
|
||||
|
||||
* added French (by Roland Frederic) and German locale
|
||||
|
||||
0.4.0
|
||||
-----
|
||||
|
||||
* adds better support for newforms-admin
|
||||
|
||||
* don't forget to load the dbtemplates.admin, e.g. by using
|
||||
django.contrib.admin.autodiscover() in you urls.py
|
||||
|
||||
0.3.1
|
||||
-----
|
||||
|
||||
* adds a new management command *sync_templates* for bidirectional syncing
|
||||
between filesystem and database (backwards-compatible) and
|
||||
FilesystemCaching (thanks, Arne Brodowski!)
|
||||
|
||||
0.2.5
|
||||
-----
|
||||
|
||||
* adds support for newforms-admin
|
||||
|
||||
Support
|
||||
=======
|
||||
|
||||
Please leave your questions and messages on the designated site:
|
||||
|
||||
http://github.com/jezdez/django-dbtemplates/issues/
|
||||
|
|
|
|||
|
|
@ -1,65 +0,0 @@
|
|||
Settings
|
||||
========
|
||||
|
||||
``DBTEMPLATES_ADD_DEFAULT_SITE``
|
||||
--------------------------------
|
||||
|
||||
``dbtemplates`` adds the current site (``settings.SITE_ID``) to the database
|
||||
template when it is created by default. You can disable this feature by
|
||||
setting ``DBTEMPLATES_ADD_DEFAULT_SITE`` to ``False``.
|
||||
|
||||
``DBTEMPLATES_AUTO_POPULATE_CONTENT``
|
||||
-------------------------------------
|
||||
|
||||
``dbtemplates`` auto-populates the content of a newly created template with
|
||||
the content of a template with the same name the other template loader.
|
||||
To disable this feature set ``DBTEMPLATES_AUTO_POPULATE_CONTENT`` to
|
||||
``False``.
|
||||
|
||||
``DBTEMPLATES_CACHE_BACKEND``
|
||||
-----------------------------
|
||||
|
||||
The dotted Python path to the cache backend class. See
|
||||
:ref:`Caching <caching>` for details.
|
||||
|
||||
``DBTEMPLATES_USE_CODEMIRROR``
|
||||
------------------------------
|
||||
|
||||
A boolean, if enabled triggers the use of the CodeMirror based editor.
|
||||
Set to ``False`` by default.
|
||||
|
||||
``DBTEMPLATES_USE_TINYMCE``
|
||||
---------------------------
|
||||
|
||||
.. versionadded:: 1.3
|
||||
|
||||
A boolean, if enabled triggers the use of the TinyMCE based editor.
|
||||
Set to ``False`` by default.
|
||||
|
||||
``DBTEMPLATES_USE_REVERSION``
|
||||
-----------------------------
|
||||
|
||||
A boolean, if enabled triggers the use of ``django-reversion``.
|
||||
|
||||
``DBTEMPLATES_USE_REVERSION_COMPARE``
|
||||
-----------------------------
|
||||
|
||||
A boolean, if enabled triggers the use of ``django-reversion-compare``.
|
||||
|
||||
``DBTEMPLATES_MEDIA_PREFIX``
|
||||
----------------------------
|
||||
|
||||
The URL prefix for ``dbtemplates``' media -- CSS and JavaScript used by
|
||||
the CodeMirror based editor. Make sure to use a trailing
|
||||
slash, and to have this be different from the ``STATIC_URL`` setting
|
||||
(since the same URL cannot be mapped onto two different sets of
|
||||
files).
|
||||
|
||||
.. warning::
|
||||
Starting in version 1.0, ``dbtemplates`` uses the ``STATIC_URL`` setting,
|
||||
originally introduced by the django-staticfiles_ app. The app has since
|
||||
been added to Django itself and isn't needed if you use Django 1.3 or
|
||||
higher. Please refer to the `contrib docs`_ in that case.
|
||||
|
||||
.. _django-staticfiles: http://pypi.python.org/pypi/django-staticfiles
|
||||
.. _contrib docs: http://docs.djangoproject.com/en/dev/ref/staticfiles/
|
||||
15
example/manage.py
Executable file
15
example/manage.py
Executable file
|
|
@ -0,0 +1,15 @@
|
|||
#!/usr/bin/env python
|
||||
import os, sys
|
||||
from django.core.management import execute_manager
|
||||
|
||||
sys.path.insert(0, os.path.abspath('./..'))
|
||||
|
||||
try:
|
||||
import settings # Assumed to be in the same directory.
|
||||
except ImportError:
|
||||
import sys
|
||||
sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
execute_manager(settings)
|
||||
1
example/requirements.txt
Normal file
1
example/requirements.txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
django-staticfiles
|
||||
106
example/settings.py
Normal file
106
example/settings.py
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
# Django settings for example project.
|
||||
import os, posixpath
|
||||
|
||||
PROJECT_ROOT = os.path.abspath(os.path.dirname(__file__))
|
||||
|
||||
DEBUG = True
|
||||
TEMPLATE_DEBUG = DEBUG
|
||||
|
||||
ADMINS = (
|
||||
# ('Your Name', 'your_email@domain.com'),
|
||||
)
|
||||
|
||||
MANAGERS = ADMINS
|
||||
|
||||
DATABASE_ENGINE = 'sqlite3' # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
|
||||
DATABASE_NAME = 'example.db' # Or path to database file if using sqlite3.
|
||||
DATABASE_USER = '' # Not used with sqlite3.
|
||||
DATABASE_PASSWORD = '' # Not used with sqlite3.
|
||||
DATABASE_HOST = '' # Set to empty string for localhost. Not used with sqlite3.
|
||||
DATABASE_PORT = '' # Set to empty string for default. Not used with sqlite3.
|
||||
|
||||
# Local time zone for this installation. Choices can be found here:
|
||||
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
|
||||
# although not all choices may be available on all operating systems.
|
||||
# If running in a Windows environment this must be set to the same as your
|
||||
# system time zone.
|
||||
TIME_ZONE = 'America/Chicago'
|
||||
|
||||
# Language code for this installation. All choices can be found here:
|
||||
# http://www.i18nguy.com/unicode/language-identifiers.html
|
||||
LANGUAGE_CODE = 'en-us'
|
||||
|
||||
SITE_ID = 1
|
||||
|
||||
# If you set this to False, Django will make some optimizations so as not
|
||||
# to load the internationalization machinery.
|
||||
USE_I18N = True
|
||||
|
||||
# Absolute path to the directory that holds media.
|
||||
# Example: "/home/media/media.lawrence.com/"
|
||||
MEDIA_ROOT = os.path.join(PROJECT_ROOT, "site_media", "media")
|
||||
|
||||
# URL that handles the media served from MEDIA_ROOT. Make sure to use a
|
||||
# trailing slash if there is a path component (optional in other cases).
|
||||
# Examples: "http://media.lawrence.com", "http://example.com/media/"
|
||||
MEDIA_URL = "/site_media/media/"
|
||||
|
||||
# Absolute path to the directory that holds static files like app media.
|
||||
# Example: "/home/media/media.lawrence.com/apps/"
|
||||
STATIC_ROOT = os.path.join(PROJECT_ROOT, "site_media", "static")
|
||||
|
||||
# URL that handles the static files like app media.
|
||||
# Example: "http://media.lawrence.com"
|
||||
STATIC_URL = "/site_media/static/"
|
||||
|
||||
# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a
|
||||
# trailing slash.
|
||||
# Examples: "http://foo.com/media/", "/media/".
|
||||
ADMIN_MEDIA_PREFIX = posixpath.join(STATIC_URL, "admin/")
|
||||
|
||||
# Make this unique, and don't share it with anybody.
|
||||
SECRET_KEY = 'e-%(1e1f8ar2v)_8d!%-75a2ag(w(ht*l%n-wts5$li!5=97)8'
|
||||
|
||||
# List of callables that know how to import templates from various sources.
|
||||
TEMPLATE_LOADERS = (
|
||||
'django.template.loaders.filesystem.load_template_source',
|
||||
'django.template.loaders.app_directories.load_template_source',
|
||||
'django.template.loaders.eggs.load_template_source',
|
||||
'dbtemplates.loader.load_template_source',
|
||||
)
|
||||
|
||||
MIDDLEWARE_CLASSES = (
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware',
|
||||
)
|
||||
|
||||
ROOT_URLCONF = 'example.urls'
|
||||
|
||||
TEMPLATE_DIRS = (
|
||||
# Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
|
||||
# Always use forward slashes, even on Windows.
|
||||
# Don't forget to use absolute paths, not relative paths.
|
||||
)
|
||||
|
||||
INSTALLED_APPS = (
|
||||
'django.contrib.auth',
|
||||
'django.contrib.contenttypes',
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.sites',
|
||||
'django.contrib.admin',
|
||||
'django.contrib.flatpages',
|
||||
'dbtemplates',
|
||||
'staticfiles',
|
||||
#'reversion',
|
||||
)
|
||||
|
||||
# Uncomment the following two settings to use the file system cache backend.
|
||||
# It will cache in the directory "cache" inside the example project directory.
|
||||
#DBTEMPLATES_CACHE_BACKEND = "dbtemplates.cache.FileSystemBackend"
|
||||
#DBTEMPLATES_CACHE_DIR = "cache"
|
||||
|
||||
DBTEMPLATES_MEDIA_PREFIX = posixpath.join(STATIC_URL, "dbtemplates/")
|
||||
DBTEMPLATES_USE_CODEMIRROR = True
|
||||
|
||||
24
example/urls.py
Normal file
24
example/urls.py
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
from django.conf import settings
|
||||
from django.conf.urls.defaults import patterns, include
|
||||
|
||||
# Uncomment the next two lines to enable the admin:
|
||||
from django.contrib import admin
|
||||
admin.autodiscover()
|
||||
|
||||
urlpatterns = patterns('',
|
||||
# Example:
|
||||
# (r'^example/', include('example.foo.urls')),
|
||||
|
||||
# Uncomment the admin/doc line below and add 'django.contrib.admindocs'
|
||||
# to INSTALLED_APPS to enable admin documentation:
|
||||
# (r'^admin/doc/', include('django.contrib.admindocs.urls')),
|
||||
|
||||
# Uncomment the next line to enable the admin:
|
||||
(r'^admin/(.*)', admin.site.root),
|
||||
)
|
||||
|
||||
# the following is used to serve up local media files like images
|
||||
if settings.DEBUG:
|
||||
urlpatterns += patterns("",
|
||||
(r"", include("staticfiles.urls")),
|
||||
)
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
[build-system]
|
||||
requires = [
|
||||
"setuptools>=61.2",
|
||||
"setuptools_scm",
|
||||
]
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "django-dbtemplates"
|
||||
authors = [{name = "Jannis Leidel", email = "jannis@leidel.info"}]
|
||||
description = "Template loader for templates stored in the database"
|
||||
readme = "README.rst"
|
||||
classifiers = [
|
||||
"Development Status :: 5 - Production/Stable",
|
||||
"Environment :: Web Environment",
|
||||
"Intended Audience :: Developers",
|
||||
"License :: OSI Approved :: BSD License",
|
||||
"Operating System :: OS Independent",
|
||||
"Programming Language :: Python",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3 :: Only",
|
||||
"Programming Language :: Python :: 3.8",
|
||||
"Programming Language :: Python :: 3.9",
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Programming Language :: Python :: 3.13",
|
||||
"Framework :: Django",
|
||||
]
|
||||
requires-python = ">=3.8"
|
||||
dependencies = ["django-appconf >= 0.4"]
|
||||
dynamic = ["version"]
|
||||
|
||||
[project.urls]
|
||||
Documentation = "https://django-dbtemplates.readthedocs.io/"
|
||||
Changelog = "https://django-dbtemplates.readthedocs.io/en/latest/changelog.html"
|
||||
Source = "https://github.com/jazzband/django-dbtemplates"
|
||||
|
||||
[tool.setuptools]
|
||||
zip-safe = false
|
||||
include-package-data = false
|
||||
|
||||
[tool.setuptools.packages]
|
||||
find = {namespaces = false}
|
||||
|
||||
[tool.setuptools.package-data]
|
||||
dbtemplates = [
|
||||
"locale/*/LC_MESSAGES/*",
|
||||
"static/dbtemplates/css/*.css",
|
||||
"static/dbtemplates/js/*.js",
|
||||
]
|
||||
|
|
@ -1 +0,0 @@
|
|||
django
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
flake8
|
||||
coverage
|
||||
13
setup.cfg
Normal file
13
setup.cfg
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
[egg_info]
|
||||
#tag_build = a1
|
||||
|
||||
[build_sphinx]
|
||||
source-dir = docs/
|
||||
build-dir = docs/_build
|
||||
all_files = 1
|
||||
|
||||
[upload_docs]
|
||||
upload-dir = docs/_build/html
|
||||
|
||||
[upload_sphinx]
|
||||
upload-dir = docs/_build/html
|
||||
29
setup.py
Normal file
29
setup.py
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
from setuptools import setup, find_packages
|
||||
|
||||
setup(
|
||||
name='django-dbtemplates',
|
||||
version=__import__('dbtemplates').__version__,
|
||||
description='Template loader for database stored templates with extensible cache backend',
|
||||
long_description=open('docs/overview.txt').read(),
|
||||
author='Jannis Leidel',
|
||||
author_email='jannis@leidel.info',
|
||||
url='http://packages.python.org/django-dbtemplates/',
|
||||
packages=find_packages(exclude=['example']),
|
||||
zip_safe=False,
|
||||
package_data = {
|
||||
'dbtemplates': [
|
||||
'locale/*/LC_MESSAGES/*',
|
||||
'media/dbtemplates/css/*.css',
|
||||
'media/dbtemplates/js/*.js',
|
||||
],
|
||||
},
|
||||
classifiers=[
|
||||
'Development Status :: 4 - Beta',
|
||||
'Environment :: Web Environment',
|
||||
'Intended Audience :: Developers',
|
||||
'License :: OSI Approved :: BSD License',
|
||||
'Operating System :: OS Independent',
|
||||
'Programming Language :: Python',
|
||||
'Framework :: Django',
|
||||
]
|
||||
)
|
||||
61
tox.ini
61
tox.ini
|
|
@ -1,61 +0,0 @@
|
|||
[tox]
|
||||
minversion = 4.0
|
||||
envlist =
|
||||
flake8
|
||||
py3{8,9,10,11,12}-dj42
|
||||
py3{10,11,12}-dj{50}
|
||||
py3{10,11,12,13}-dj{51,52}
|
||||
py3{12,13}-dj{main}
|
||||
coverage
|
||||
|
||||
[gh-actions]
|
||||
python =
|
||||
3.8: py38
|
||||
3.9: py39
|
||||
3.10: py310
|
||||
3.10: py310, flake8
|
||||
3.11: py311
|
||||
3.12: py312
|
||||
3.13: py313
|
||||
|
||||
[testenv]
|
||||
skipsdist = true
|
||||
package = editable
|
||||
basepython =
|
||||
py38: python3.8
|
||||
py39: python3.9
|
||||
py310: python3.10
|
||||
py311: python3.11
|
||||
py312: python3.12
|
||||
py313: python3.13
|
||||
setenv =
|
||||
DJANGO_SETTINGS_MODULE = dbtemplates.test_settings
|
||||
deps =
|
||||
-r requirements/tests.txt
|
||||
dj42: Django>=4.2,<4.3
|
||||
dj50: Django>=5.0,<5.1
|
||||
dj51: Django>=5.1,<5.2
|
||||
dj52: Django>=5.2,<5.3
|
||||
djmain: https://github.com/django/django/archive/main.tar.gz#egg=django
|
||||
|
||||
commands =
|
||||
python --version
|
||||
python -c "import django ; print(django.VERSION)"
|
||||
coverage run --branch --parallel-mode {envbindir}/django-admin test -v2 {posargs:dbtemplates}
|
||||
|
||||
[testenv:coverage]
|
||||
basepython = python3.10
|
||||
deps = coverage
|
||||
commands =
|
||||
coverage combine
|
||||
coverage report
|
||||
coverage xml
|
||||
|
||||
[testenv:flake8]
|
||||
basepython = python3.10
|
||||
commands = flake8 dbtemplates
|
||||
deps = flake8
|
||||
|
||||
[flake8]
|
||||
exclude=.tox
|
||||
ignore=E501,E127,E128,E124
|
||||
Loading…
Reference in a new issue