Compare commits

...

252 commits
1.2 ... master

Author SHA1 Message Date
Thomas Güttler
10e7de2eda
Fix cache invalidation (#131) 2025-06-17 16:38:05 -07:00
Viktor Kálmán
930ce5c65c
add project urls (#156) 2025-06-09 11:47:43 -07:00
blag
8e284b54d8
Revert "Split out an AbstractTemplate model for easier reuse" (#154)
This reverts commit 46be8fc748.
2025-05-29 23:31:49 +02:00
blag
05f1ee1193
Split out an AbstractTemplate model for easier reuse (#150) 2025-05-26 22:09:25 +02:00
blag
303bd0cabe
Add missing migration for creation_date and last_changed changes (#151) 2025-05-26 22:08:21 +02:00
Łukasz Chojnacki
64d112cc4f
Add explicit id field to avoid creating migration with DEFAULT_AUTO_FIELD set to BigAutoField (#142)
Co-authored-by: blag <blag@users.noreply.github.com>
2025-05-26 20:13:03 +02:00
blag
7f1c6701c1
Properly add Django 5.2 and tweak coverage collection (#148) 2025-05-26 20:12:55 +02:00
blag
873c90b777
Convert setup.py and setup.cfg to pyproject.toml (#149) 2025-05-26 20:12:37 +02:00
Thomas Güttler
e64a457281
There is no INSTALL file. (#128)
removed "Follow the instructions in the INSTALL file", since there is no INSTALL file.

Co-authored-by: blag <blag@users.noreply.github.com>
2025-05-26 20:00:16 +02:00
blag
a7f4e0bbe8
Make creation_date and last_updated fields readonly in admin (#144) 2025-05-26 19:59:50 +02:00
blag
218b28b7aa
Let Django handle creation_date and last_changed (#145) 2025-05-26 19:59:18 +02:00
blag
602717af95
Add default_auto_field to AppConfig (#146) 2025-05-26 19:53:42 +02:00
Jannis Leidel
8769e29057
Use correct release branch of pypa/publish action. (#138) 2025-05-20 21:40:09 +02:00
Viktor Kálmán
ac740e06f3
Support for Python 3.12 and up (#143)
* support for Python 3.12 and up

* removed unused deprecated ugettext imports

* fix django main being Python 3.12+

* missed some copypaste
2025-02-16 21:08:16 +01:00
Jannis Leidel
233a401e75
Fix docs rendering (#127)
* Create .readthedocs.yaml

* Add docs requirements
2022-08-29 12:09:54 +02:00
Michał Pasternak
13bacacef8
Merge pull request #126 from mpasternak/master
Django 4.x
2022-08-11 07:28:21 +02:00
Michał Pasternak
fa72b2771b Flake8 2022-08-10 22:32:23 +02:00
Michał Pasternak
fac9f6a807 Mention dropping Django below 3.2 2022-08-10 22:29:46 +02:00
Michał Pasternak
f53244ce54 Merge branch 'master' of github.com:mpasternak/django-dbtemplates-iplweb 2022-08-10 22:29:10 +02:00
Michał Pasternak
6ca53981d3 Test all the supported versions 2022-08-10 22:28:36 +02:00
Michał Pasternak
45e216b8ac Remove compatibility wrapper 2022-08-10 22:28:21 +02:00
Michał Pasternak
5a363dbe34
Update setup.py
Co-authored-by: Hugo van Kemenade <hugovk@users.noreply.github.com>
2022-08-10 10:47:46 +02:00
Michał Pasternak
2c8dc82721
Update tox.ini
Co-authored-by: Hugo van Kemenade <hugovk@users.noreply.github.com>
2022-08-09 17:50:42 +02:00
Michał Pasternak
98bc9921b0 Remove trailing whitespace 2022-08-09 17:41:44 +02:00
Michał Pasternak
b6b0bf48ba Django 4.0 i18n fixes 2022-08-09 17:38:47 +02:00
Michał Pasternak
36fbb80fc0 Update to Django 4.0 i18n style 2022-08-09 17:38:39 +02:00
Michał Pasternak
e08a8d3950 Document changes in 4.0 (unreleased) 2022-08-09 17:35:13 +02:00
Michał Pasternak
6dd23d2325 Proper links to CI badge 2022-08-09 17:34:29 +02:00
Michał Pasternak
a68caedc2d Revert unintentional typo 2022-08-09 17:34:14 +02:00
Michał Pasternak
2b5034951f Remove unsupported Django versions 2022-08-09 17:34:06 +02:00
Michał Pasternak
b138cafcfa Passing flake8 2022-08-08 00:49:40 +02:00
Michał Pasternak
f98fb8ca24 Min. supported Python version 2022-08-08 00:40:17 +02:00
Michał Pasternak
2e3f009426
Merge branch 'master' into master 2022-08-08 00:36:05 +02:00
Michał Pasternak
8e8b76fc0a
Merge pull request #125 from jazzband/add-3.10
Add support for Python 3.10
2022-08-08 00:25:12 +02:00
Jazzband Bot
49dd3be520
Jazzband: Created local 'CODE_OF_CONDUCT.md' from remote 'CODE_OF_CONDUCT.md' (#120) 2022-08-05 14:12:18 +02:00
Hugo van Kemenade
74ee8a2fe3 Add pre-commit config 2022-06-15 16:02:33 +03:00
Michał Pasternak
1a20742b71 Fix flake8 target on GitHub 2022-06-15 14:58:13 +02:00
Hugo van Kemenade
9455b36281 Upgrade to f-strings with 'flynt .' 2022-06-15 15:54:51 +03:00
Hugo van Kemenade
165ffd0b15 Test Python 3.11 beta 2022-06-15 15:54:51 +03:00
Hugo van Kemenade
a3054c7724 Fix Flake8 2022-06-15 15:47:52 +03:00
Hugo van Kemenade
e5e4e55d22 Upgrade Python syntax with pyupgrade --py37-plus 2022-06-15 15:47:52 +03:00
Hugo van Kemenade
9a27f4938c Drop support for EOL Python 3.6 2022-06-15 15:47:52 +03:00
Michał Pasternak
013057425f Min. Python version 2022-06-15 14:43:43 +02:00
Michał Pasternak
7ffc0fa33f Don't build unversal wheel 2022-06-15 14:43:32 +02:00
Michał Pasternak
de4babcad4 Describe changes 2022-06-15 14:39:44 +02:00
Hugo van Kemenade
6b18f19ffd Add support for Python 3.10 2022-06-15 15:39:30 +03:00
Michał Pasternak
5281b74ea7 Don't change basepython for flake8 2022-06-15 14:31:46 +02:00
Michał Pasternak
9dbdb95227 Rename for PyPI release 2022-06-15 14:29:06 +02:00
Michał Pasternak
e1e11c42cb Django 4.x fixes 2022-06-15 14:25:32 +02:00
Michał Pasternak
9f664ea43c Django 4.x fix 2022-06-15 14:22:48 +02:00
Michał Pasternak
e477561810 Proper image path 2022-06-15 14:22:42 +02:00
Michał Pasternak
2d622ee28c Python 3.10 2022-06-15 14:22:32 +02:00
Michał Pasternak
8901551893 Merge branch 'master' of github.com:mpasternak/django-dbtemplates-iplweb 2022-06-15 14:22:06 +02:00
Michał Pasternak
9e4a6f7c78 Django 4.x 2022-06-15 14:20:06 +02:00
Michał Pasternak
9486f0c78b
Merge pull request #118 from wamberg/cache-compat-#116
Django 3.2 compatibility
2022-06-15 12:17:42 +02:00
Nikolaus Schlemm
376f33916f focus on currently supported releases of python and django 2022-02-08 09:20:18 -05:00
Bill Amberg
8cd8a17bc1 Use strings explicitly for template directories 2022-02-08 09:15:46 -05:00
Bill Amberg
f45cd228f9 Get cache for Django>=3.2 2022-02-08 09:15:46 -05:00
Bill Amberg
24b5f469a2 Add failing test environment for Django==3.2 2022-02-08 09:15:33 -05:00
Giovanni B
2b747bc4af
Fixes #113 (#115)
* Fixes #113

* Update tox.ini

Co-authored-by: Jannis Leidel <jannis@leidel.info>

Co-authored-by: Jannis Leidel <jannis@leidel.info>
2021-10-21 17:35:56 +02:00
Jannis Leidel
ac86ca5ec9
Rename Django's dev branch to main. (#114)
More information: https://groups.google.com/g/django-developers/c/tctDuKUGosc/
Refs: https://github.com/django/django/pull/14048
2021-03-09 13:34:27 +01:00
Jannis Leidel
012fe061a8
Migrate to GitHub Actions. (#112)
* Add GitHub Actions test workflow.

* Update version map.

* Fix flake8

* Write coverage file.

* Fix typo.

* Add release workflow.

* Removed Travis cruft and updated other files.

* Update trove classifiers.

* Black setup.

* Remove unneeded twine check.

* Extend changelog.

* Fix six issue.

* Update tox.ini

Co-authored-by: Hugo van Kemenade <hugovk@users.noreply.github.com>

* Add 3.9.

* Add base python

Co-authored-by: Hugo van Kemenade <hugovk@users.noreply.github.com>
2020-12-09 09:55:35 +01:00
Kaustubh Bhalerao
68ac54a72b
Django 3.0.4 (#107)
Co-authored-by: Kaustubh Bhalerao <bhalerao@soildiagnostics.com>
2020-06-15 14:17:18 +07:00
Nikolaus Schlemm
7ea4655b57 integrate with django-reversion-compare to offer a history compare view in admin 2020-06-15 13:08:47 +07:00
John Vandenberg
1d53b25cc2
Merge pull request #102 from nschlemm/nschlemm-patch-help_text 2020-05-06 00:31:10 +07:00
John Vandenberg
81ba1364f8
Merge pull request #103 from nschlemm/update-tox 2020-05-05 20:47:13 +07:00
John Vandenberg
ae97ad7e24
Merge pull request #100 from nschlemm/nschlemm-patch-raw_input 2020-05-05 20:36:54 +07:00
John Vandenberg
5c6c35bf3d
Merge pull request #98 from nschlemm/patch-2 2020-05-05 20:35:41 +07:00
Nikolaus Schlemm
50f02a50bc added django 2.2, dropped django 2.0 and python 3.4
keeping in sync with https://www.djangoproject.com/download/#supported-versions
2019-06-19 13:37:44 +02:00
Nikolaus Schlemm
230157640c let's keep flake8 silent until we can throw this backwards-compatibility hack out completely 2019-06-19 12:50:02 +02:00
Nikolaus Schlemm
f443f29047
Fixes #101 by expanding the help text default value 2019-06-19 12:34:03 +02:00
Nikolaus Schlemm
79d1d3986f
Fixes #99 by replacing raw_input with input
added (propably obsolete) backwards compatability as django already threw out six
2019-06-19 12:15:59 +02:00
Nikolaus Schlemm
73a33361d3
Fixes #82 TypeError: can only concatenate list (not "tuple") to list 2019-01-28 02:07:52 +01:00
Jannis Leidel
a04933e5ce
Fix changelog date. 2019-01-27 22:54:59 +01:00
Jannis Leidel
78ca3f48dd
Bump version to 3.0. 2019-01-27 22:26:41 +01:00
Jannis Leidel
727746add1
12 years! 2019-01-27 22:26:28 +01:00
Jannis Leidel
07d62d8d26
Updated changelog. 2019-01-27 22:25:42 +01:00
Jannis Leidel
4ece48c7b2
Remove Python 3.4 from Django 2.1 tests since it’s not supported. 2019-01-27 22:24:20 +01:00
Jannis Leidel
966b68ee5c
Added some Python versions to trove classifiers. 2019-01-27 22:23:54 +01:00
Jannis Leidel
039f6f419f
Build universal wheel files. 2019-01-27 22:08:06 +01:00
Jannis Leidel
24c8d2005a
Use twine instead of readme_renderer for readme check. 2019-01-27 22:07:58 +01:00
Jannis Leidel
df358a53dd
Merge pull request #88 from m-vdb/mvdb/fix-migration
Fix bytes string migration (python3)
2019-01-27 22:02:31 +01:00
Jannis Leidel
f5b9e36fc7
Merge pull request #89 from m-vdb/mvdb/fix-str-representation
Fix Template string representation for python3
2019-01-27 21:58:28 +01:00
Jannis Leidel
16afa49831
Use django.utils.six instead of six directly. 2019-01-27 21:54:57 +01:00
Jannis Leidel
cef1ec49c0
Merge pull request #97 from nschlemm/patch-1
Fix flake8 W504 line break after binary operator
2019-01-27 21:46:24 +01:00
Jannis Leidel
745e64f3e0
Re-enable project releases via Jazzband.co. Fix #95. 2019-01-27 21:43:29 +01:00
Nikolaus Schlemm
28bde8c32d
Fix flake8 W504 line break after binary operator
and thereby hopefully allow for closing https://github.com/jazzband/django-dbtemplates/issues/95 ?
2019-01-26 01:18:32 +01:00
Waldecir Santos
16a80d4635
fix PyPi upload 2018-10-01 20:14:42 +01:00
Waldecir Santos
6522a39250
added server tag to deploy 2018-10-01 19:45:48 +01:00
Waldecir Santos
149a16e308
bump version 2018-10-01 18:53:22 +01:00
Waldecir Santos
92e0e1ca0c
Merge pull request #87 from eprikazc/master
Add support for Django2.0, drop 1.8
2018-10-01 18:52:35 +01:00
Eugene Prikazchikov
c2009596ef Add workaround to make Python3.7 in Travis work properly 2018-10-01 11:20:33 +03:00
Eugene Prikazchikov
9cce7cd03b Update tox.ini to support Python3.7 2018-10-01 10:59:47 +03:00
Eugene Prikazchikov
34e34b7259 Add renderer parameter to CodeMirrorTextArea.render
According to django2.1
2018-09-13 23:37:41 +03:00
m-vdb
db5e4ec4b6 fix Template string representation for python3 2018-02-12 20:12:38 +01:00
m-vdb
3ba01f425c remove byte string from migration file 2018-02-12 20:02:23 +01:00
Jannis Leidel
77d8fc4e33
Merge pull request #83 from paulgueltekin/master
fixed method call with named argument
2017-12-09 23:49:08 +01:00
Jannis Leidel
3939947a0e
Merge pull request #86 from kammato/russian_locale_fix
Recompiled russian locale correctly
2017-12-09 23:46:11 +01:00
Eugene Prikazchikov
1c80410a5b Update get_template_source utility function to use up-to-date template API 2017-12-09 21:38:42 +03:00
Eugene Prikazchikov
18afb50582 Remove django 1.8 from tox.ini 2017-12-09 20:43:44 +03:00
Eugene Prikazchikov
e3318658a5 Update Loader class to up-to-date template loader API
load_template_sources is deprecated in Django 1.9 ad removed in Django2.0
see https://docs.djangoproject.com/en/1.9/releases/1.9/#template-loader-apis-have-changed
2017-12-09 20:40:57 +03:00
Jannis Leidel
3ee69a58ce
Drop testing pypy. 2017-11-22 15:47:11 +01:00
Jannis Leidel
9a84b1af86
Fix test matrix. 2017-11-22 15:43:19 +01:00
Jannis Leidel
bc206765fa
Appease flake8. 2017-11-22 11:01:02 +01:00
Khamid Tomov
8176a137dd Recompiled russian locale correctly 2017-05-18 18:00:03 +03:00
Paul Gueltekin
1c9467fa37 fixed method call with named argument 2017-01-17 16:51:06 +01:00
Jannis Leidel
49fc6c47ff Fix condition for auto-release 2016-09-20 12:55:46 +02:00
Jannis Leidel
d3221c3acd Update docs 2016-09-20 12:44:29 +02:00
Jannis Leidel
70fb31c190 Add Django appconfig for overriding the name in the admin 2016-09-20 12:41:44 +02:00
Jannis Leidel
6fbde482af Some packaging fixes as usual 2016-09-20 12:32:59 +02:00
Matthias K
62ba054698 Merge pull request #81 from jazzband/python3
Port to Python 3 and get rid of legacy code
2016-09-20 12:28:16 +02:00
Jannis Leidel
e4acf6e754 Use saner test assertion 2016-09-20 12:02:03 +02:00
Jannis Leidel
3d5d70db41 More Py3 fixes 2016-09-20 11:46:13 +02:00
Jannis Leidel
8c1e33de72 Use io instead of codecs 2016-09-20 11:34:28 +02:00
Jannis Leidel
44c040523a Remove last version switch 2016-09-20 11:34:15 +02:00
Jannis Leidel
39c8420511 Fix a codec issue in Py3 2016-09-20 11:20:34 +02:00
Jannis Leidel
7454e109ea Update docs 2016-09-20 10:57:49 +02:00
Jannis Leidel
d7ecd93cce Port to Python 3 and removed legacy code 2016-09-20 10:34:59 +02:00
Jannis Leidel
1e2a4f0dff Remove old example project 2016-09-20 10:33:24 +02:00
Jannis Leidel
f0cfdfa9ce Use better version checks, fix #78 2016-09-20 10:33:24 +02:00
Matthias K
279fba2635 Do not install flake8>=3 as this project still seems to support Python 2.6 2016-09-20 10:14:23 +02:00
Matthias K
cd2a06ea51 Merge pull request #76 from adamchainz/readthedocs.io
Convert readthedocs links for their .org -> .io migration for hosted projects
2016-09-20 10:12:53 +02:00
Matthias K
892bc8b0aa Merge pull request #74 from thedrow/patch-1
Added django 1.9 to the build
2016-09-20 10:11:48 +02:00
Adam Chainz
2427759736 Convert readthedocs links for their .org -> .io migration for hosted projects
As per [their blog post of the 27th April](https://blog.readthedocs.com/securing-subdomains/) ‘Securing subdomains’:

> Starting today, Read the Docs will start hosting projects from subdomains on the domain readthedocs.io, instead of on readthedocs.org. This change addresses some security concerns around site cookies while hosting user generated data on the same domain as our dashboard.

Test Plan: Manually visited all the links I’ve modified.
2016-06-11 10:53:29 +01:00
Omer Katz
f1fb4577cc Exclude migrations. 2016-04-01 15:42:47 +03:00
Omer Katz
9c297392dc Added django 1.9 to the build
Also, added caching and bumped the latest django 1.8.x version.
2016-04-01 15:38:12 +03:00
Michael Kutý
7619f9fb71 Merge pull request #72 from jazzband/hotfix/django_import
Use native importlib istead of Django version.
2016-01-07 16:48:43 +01:00
Michael Kutý
d1b83e1145 Install importlib backport in python 2.6. 2016-01-03 00:10:42 +01:00
Michael Kutý
ca8841ce9c Use native importlib. 2016-01-03 00:01:45 +01:00
Jannis Leidel
a3334a05ec Moved to Jazzband. 2015-12-17 10:44:42 +01:00
Jannis Leidel
483db6616a Merge remote-tracking branch 'origin/develop-1.4' 2015-12-17 10:38:40 +01:00
Jannis Leidel
0b4cec538e Merge branch 'develop' 2015-12-17 10:38:29 +01:00
Michael Kutý
6815ce6c6c Merge pull request #69 from glader/develop-1.4
Fix localization
2015-10-16 14:10:34 +02:00
Mikhail Polykovskij
2c7afb6a1a Fix localization 2015-10-16 17:05:42 +05:00
Michael Kutý
676a410517 Merge pull request #68 from michaelkuty/develop
fix get cache deprecated
2015-09-17 21:18:21 +02:00
Michael Kutý
9648555473 fix RemovedInDjango19Warning: 'get_cache' is deprecated in favor of 'caches'. 2015-09-17 21:15:10 +02:00
Michael Kutý
b6912fc339 Merge pull request #67 from philippeowagner/develop-1.4
Docs update for  ``TEMPLATES.OPTIONS.loaders`` config. Fixes #65
2015-09-17 12:23:01 +02:00
Philippe O. Wagner
308d03ba98 Docs update for `TEMPLATES.OPTIONS.loaders` config.
Works for Django 1.8+
2015-09-17 12:12:20 +02:00
Michael Kutý
b9b2ac5885 Merge pull request #66 from barseghyanartur/develop
python 3 fix
2015-09-17 11:28:54 +02:00
Michael Kutý
db74e84604 Merge pull request #1 from jezdez/develop-1.4
Develop 1.4
2015-08-25 10:49:50 +02:00
Michael Kutý
35a57bbcb1 drop support for django < 1.3.7 2015-08-19 14:56:00 +02:00
Michael Kutý
c8a048352e Fix some Python 3 issues - thanks @vikingco 2015-08-19 11:42:39 +02:00
Artur Barseghyan
bb9199b0be python 3 fix 2015-08-18 16:29:14 +02:00
Michael Kutý
fbc2891c41 Merge pull request #64 from barseghyanartur/develop
fix setup for python 3
2015-08-18 15:59:42 +02:00
Artur Barseghyan
59c65c56ab fix setup for python 3 2015-08-18 14:15:26 +02:00
Michael Kutý
6dd19d3a17 Merge pull request #62 from michaelkuty/develop
use managers for django 1.8+
2015-07-23 15:43:58 +02:00
Michael Kutý
c55e2220b3 use managers for django 1.8+ 2015-07-23 15:42:07 +02:00
Michael Kutý
70da2e6a48 use migrations generated from django 1.7 2015-07-15 00:08:45 +02:00
Michael Kutý
04c2d12dbd added django migrations and south moved to own directory 2015-07-14 23:30:53 +02:00
Michael Kutý
42590af744 fixed (fields.W340) null has no effect on ManyToManyField and import sorting 2015-07-06 22:16:43 +02:00
Michael Kutý
464425b236 fix settings runtime patching which cause fails because if we set correct template dirs is not there test dirs 2015-06-16 00:07:27 +02:00
Michael Kutý
926a3215eb cleanup yaml 2015-06-15 23:19:22 +02:00
Michael Kutý
acdf9dc8e5 properly exclude python 2.6 from new djangos 2015-06-15 23:15:27 +02:00
Michael Kutý
201077e11b properly collect template dirs for all available template engines in dj 1.8 and prettify readme 2015-06-15 23:10:41 +02:00
Michael Kutý
99ed8b2ce3 fix app dirs on django 1.8 2015-06-15 22:44:44 +02:00
Michael Kutý
edbb5e1ef0 exclude python 2.6 from Dj 1.7 and 1.8 where was dropped support for this version 2015-06-15 22:39:17 +02:00
Michael Kutý
51b62d9a62 omg fix pep8 passing 2015-06-15 21:17:18 +02:00
Michael Kutý
c9569a81db update readme and added notice about compatibility, bump version and changelog 2015-06-15 21:03:09 +02:00
Michael Kutý
b47af2e1ff added middleware classes 2015-06-15 20:36:24 +02:00
Michael Kutý
16fe97575c pep8 cleanup and fix test runner for new django 2015-06-15 20:20:02 +02:00
Michael Kutý
0e97716488 ModelForm now requires either fields or exclude - mentoined in #52 thanks @volksman 2015-06-15 16:54:21 +02:00
Michael Kutý
b03803010d Merge pull request #59 from eculver/develop
Support for using redactorjs for editing templates.
2015-06-15 16:48:43 +02:00
Michael Kutý
078d556390 fix flake8 2015-06-15 16:44:34 +02:00
Michael Kutý
658aca88dc bump version 2015-06-15 16:35:15 +02:00
Michael Kutý
984f83c0a8 update dj versions 2015-04-28 11:19:19 +02:00
Michael Kutý
685c77e718 proper solution 2015-04-28 11:16:06 +02:00
Michael Kutý
15c4a5930b fix loader for django 1.8 2015-04-28 01:03:45 +02:00
Michael Kutý
50a877a7d5 fix name 2015-04-28 01:00:24 +02:00
Michael Kutý
c2d49e1d71 hot-fixed populating template djagno 1.8+ 2015-04-27 23:40:42 +02:00
Kevin Mooney
5d3a392e4c Deleted utils.py 2015-04-03 16:37:59 +00:00
Jannis Leidel
b371cc6518 Merge pull request #53 from kangfend/fix-modelform
Include fields to class Meta
2014-10-29 13:26:19 +01:00
Sutrisno Efendi
4352fb639e Include fields to class Meta 2014-09-23 15:19:16 +07:00
Jannis Leidel
1372f43992 Merge pull request #45 from jnns/develop
Fix link to django-reversion doc.
2013-11-06 05:52:56 -08:00
Jannis
bfd7186db0 Fix URL to django-reversion doc.
Fix URL of django-reversion's documentation. Apparently, django-reversion uses Readthedocs instead of GitHub's wiki now.
2013-11-06 14:35:34 +01:00
Jannis Leidel
91d5e137f1 Merge pull request #42 from szelga/feature_rulocale
add Russian locale
2013-07-30 01:59:23 -07:00
Wasil W Sergejczyk
12ffd84380 add Russian locale 2013-07-30 14:35:07 +06:00
Jannis Leidel
f668370eee Drop support for Python 2.5. 2013-04-04 11:41:38 +02:00
Jannis Leidel
b051161aea Test on Django 1.5.X, too. 2013-04-04 11:34:18 +02:00
Jannis Leidel
4b024de965 Minor cosmetic changes to please flake8. 2013-04-04 11:33:00 +02:00
Evan Culver
2fc79eda7a Support for using redactorjs for editing templates. 2012-09-05 16:47:34 -04:00
Jannis Leidel
d2f595ce82 Moved to django-discover-runner. 2012-05-23 23:50:32 +02:00
Jannis Leidel
f7378df802 Use __isnull for querying a non-site specific template. Refs #33. 2012-05-19 21:40:47 +02:00
Jannis Leidel
1c520b0fad Re-enabled 2.5 now that flake8 works on it again. 2012-05-19 19:24:17 +02:00
Jannis Leidel
c36d649e4d Disabled Python 2.5 again as flake8 doesn't support it at the moment :( 2012-05-19 13:27:09 +02:00
Jannis Leidel
6d356db2ef Trying 2.5 2012-05-19 13:10:03 +02:00
Jannis Leidel
0672fa42bf Set env vars before installing and use crate. 2012-05-19 13:08:02 +02:00
Jannis Leidel
7802fbe328 Merge branch 'release/1.3' into develop 2012-05-07 23:53:19 +02:00
Jannis Leidel
327384645c Merge branch 'release/1.3' 2012-05-07 23:53:05 +02:00
Jannis Leidel
8844180d6c Bumped version to 1.3. 2012-05-07 23:52:59 +02:00
Jannis Leidel
25d9283758 Use version from __version__. 2012-05-07 23:52:50 +02:00
Jannis Leidel
ca9d2fc468 Removed old hg tags. 2012-05-07 23:50:01 +02:00
Jannis Leidel
c59de762f9 Correct version. 2012-05-07 23:48:21 +02:00
Jannis Leidel
ee29bbe46e Updated settings docs. 2012-05-07 23:48:07 +02:00
Jannis Leidel
4c3c459e82 Updated changelog. 2012-05-07 23:47:30 +02:00
Jannis Leidel
60215fe947 Updated AUTHORS file. 2012-05-07 23:47:15 +02:00
Jannis Leidel
a1cec65e29 Removed INSTALL file from manifest template. 2012-05-07 14:15:52 +02:00
Jannis Leidel
e7b6b8ce00 Ignore long lines, stupid. 2012-05-07 14:12:07 +02:00
Jannis Leidel
d018f826da Forgotten dirname for flake8. 2012-05-07 14:10:12 +02:00
Jannis Leidel
07fe3cc7ee Fixed typo. 2012-05-07 14:08:08 +02:00
Jannis Leidel
842e08cf2e Switched to using nose and django-nose for easy test running. 2012-05-07 14:06:54 +02:00
Jannis Leidel
2e430d5370 Minor code cleanup of the migrations. 2012-05-07 10:57:36 +02:00
Jannis Leidel
2f27327beb Handle timezone on 1.4 correctly. 2012-05-07 10:57:23 +02:00
Jannis Leidel
f1e680aa31 Added link to Travic build. 2012-05-07 10:54:26 +02:00
Jannis Leidel
0e43258b5b Added DATABASES setting to please Django 1.4. 2012-05-07 10:35:31 +02:00
Jannis Leidel
d926d6c934 Merge pull request #32 from selwin/develop
Fixed an issue where ``get_cache_key`` may produce invalid memcached keys
2012-05-07 01:32:40 -07:00
Jannis Leidel
f3fc408385 Get the database name from the routers and dropped support for 1.2.X. 2012-05-07 10:31:24 +02:00
Jannis Leidel
20aebf894d Limit the tests to dbtemplates. 2012-05-07 09:48:01 +02:00
Jannis Leidel
d3ccb0c42a Stop using a context manager when we don't need it really. 2012-05-07 09:04:31 +02:00
Jannis Leidel
222c7947d2 Added auth app to list of installed apps during tests. 2012-05-07 09:04:05 +02:00
Jannis Leidel
bea453548f Renamed test requirements file to correct name. 2012-05-07 08:58:36 +02:00
Jannis Leidel
abc2fe5cd2 Added a few more test requirements. 2012-05-07 08:57:45 +02:00
Jannis Leidel
87c5c46999 Further fiddling with the travis config. 2012-05-07 08:55:27 +02:00
Jannis Leidel
0ff18227f9 Hrm, setting the variable in the env block? 2012-05-07 08:43:48 +02:00
Jannis Leidel
20a5d9fc66 Forgot to set the DJANGO_SETTINGS_MODULE var. 2012-05-07 08:41:02 +02:00
Jannis Leidel
3c67628a63 Removed dependency on versiontools. 2012-05-07 08:36:01 +02:00
Jannis Leidel
45700c7e1c Moved CI to Travis. 2012-05-07 08:35:36 +02:00
Selwin Ong
bb4e7ce36f Fixed an issue where `get_cache_key` may produce invalid memcached
keys.
2012-05-06 20:52:17 +07:00
Jannis Leidel
33c1197ad1 Merge pull request #30 from bmihelac/fix-27-MultipleObjectsReturned
Fix 27 multiple objects returned
2012-03-30 06:31:55 -07:00
Jannis Leidel
45407e1624 Merge pull request #29 from bmihelac/fix-28-test-warnings
Fix for #28
2012-03-30 06:31:23 -07:00
Bojan Mihelac
3aa3132255 Fix for #28 2012-03-30 15:25:45 +02:00
Bojan Mihelac
29f08281d7 Fix #27.
dbtemplates tries to find template from database which is associated
with current site, and if that fails then template from database which
is not associated with any site.
2012-03-30 15:14:21 +02:00
Bojan Mihelac
f503013b0f Add failing tests for #27.
Raises MultipleObjectsReturned with sites
2012-03-30 15:11:57 +02:00
Jannis Leidel
832b000c49 Merge pull request #21 from markstahler/develop
django-tinymce support
2012-03-19 14:18:49 -07:00
Jannis Leidel
311875c68b Merge pull request #25 from gandalfar/test_no_dbloader
fix for tests when dbtemplates template loader is not in main settings
2012-03-19 14:17:59 -07:00
Jure Cuhalev
0cfd927938 fix for tests when dbtemplates template loader is not in main settings.py 2012-02-25 22:47:05 +01:00
Jannis Leidel
ad7b258308 Force an encoding when writing the content to the file. 2012-02-24 23:35:51 +01:00
Mark Stahler
68d4342df4 removed urls.py which is not required if django-tinymce is installed
properly. fixed new bug relating to codemirror introduced by tinymce
2012-01-18 08:33:13 -05:00
Mark Stahler
edaf6ea258 respect column widths 2012-01-17 22:11:08 -05:00
Mark Stahler
e866e52074 fixed tinyMce not appearing in admin area 2012-01-17 21:58:47 -05:00
Mark Stahler
02aaad635a Added TinyMCE support via django-tinymce 2012-01-17 21:22:22 -05:00
Jannis Leidel
b13ffbb248 Merge pull request #19 from bmihelac/patch-2
Fix typo in docs - ``dbtemplates.loader.Loader`` should be first in ``TEMPLATE_LOADERS``.
2012-01-09 10:11:18 -08:00
bmihelac
3e18bc9784 Update docs/overview.txt 2012-01-09 13:12:19 +01:00
bmihelac
cb3fe58a6e Fix typo in docs - `dbtemplates.loader.Loader should be first in TEMPLATE_LOADERS`. 2012-01-09 12:56:09 +01:00
Jannis Leidel
6a6229648e Merge pull request #18 from bmihelac/patch-1
Fix typo in docs.
2012-01-09 03:46:42 -08:00
bmihelac
5a6053fef0 Fix typo in docs. 2012-01-09 12:37:26 +01:00
Jannis Leidel
1c10468529 Fixed ignore files. 2012-01-09 00:01:31 +01:00
Jannis Leidel
4ae9392e08 Use django-jenkins for tests and prepare it for ci.enn.io. 2012-01-09 00:01:17 +01:00
Jannis Leidel
9cc07437ee Updated year. 2012-01-09 00:00:10 +01:00
Jannis Leidel
65684c1243 Use latest versiontools. 2012-01-08 23:59:52 +01:00
Jannis Leidel
fcca3742e0 Minor cleanup in docs. 2012-01-08 23:59:34 +01:00
Jannis Leidel
cc94071fc4 Merge branch 'release/1.2.1' into develop 2011-09-07 12:08:42 +02:00
Jannis Leidel
357954a83c Merge branch 'release/1.2.1' 2011-09-07 12:08:37 +02:00
Jannis Leidel
41842de12d Bumped version to 1.2.1. 2011-09-07 12:05:09 +02:00
Jannis Leidel
b6d5bfa226 Use better testrunner. 2011-09-06 15:00:30 +02:00
Jannis Leidel
1224ab4005 Added versiontools requirement to setup.py. 2011-09-06 12:31:56 +02:00
Jannis Leidel
d5be3e42d5 Use django-appconf. 2011-09-06 12:31:28 +02:00
Jannis Leidel
fcc9045829 Fixed changelog and added bugfix to it. 2011-09-05 11:02:55 +02:00
Jannis Leidel
e3c53f6b17 Merge pull request #16 from dfalk/develop
Use ugettext_lazy instead of gettext_lazy for verbose name.
2011-08-25 15:49:44 -07:00
dfalk
9e81e53099 using ugettext 2011-08-26 01:28:49 +04:00
Jannis Leidel
f53536fdcd Merge branch 'release/1.2' into develop 2011-08-15 13:24:56 +02:00
kmooney
9843cb8190 Merge branch 'master' into develop 2011-06-30 12:37:39 -05:00
kmooney
431813c9b1 Change to skip template loaders whose load method is not implemented. This happens with the Django cached template loader, in particular. 2011-06-30 12:26:50 -05:00
54 changed files with 1294 additions and 972 deletions

6
.coveragerc Normal file
View file

@ -0,0 +1,6 @@
[run]
source = dbtemplates
branch = 1
[report]
omit = *tests*,*/migrations/*,test_*

40
.github/workflows/release.yml vendored Normal file
View file

@ -0,0 +1,40 @@
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 Normal file
View file

@ -0,0 +1,48 @@
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 }}

8
.gitignore vendored
View file

@ -1,10 +1,14 @@
.*
!.gitignore
!.coveragerc
*.pyc
.*.swp
MANIFEST
build
dist
*.egg-info
example/example.db
docs/_build
.tox/
*.egg/
*.egg/
.coverage
coverage.xml

View file

@ -1,9 +0,0 @@
syntax: glob
*.pyc
.*.swp
MANIFEST
build
dist
django_dbtemplates.egg-info/
example/example.db
docs/_build

24
.hgtags
View file

@ -1,24 +0,0 @@
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

15
.pre-commit-config.yaml Normal file
View file

@ -0,0 +1,15 @@
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

25
.readthedocs.yaml Normal file
View file

@ -0,0 +1,25 @@
# .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

View file

@ -4,5 +4,4 @@ source_file = dbtemplates/locale/en/LC_MESSAGES/django.po
source_lang = en
[main]
host = https://www.transifex.net
host = https://www.transifex.com

View file

@ -5,10 +5,14 @@ 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

46
CODE_OF_CONDUCT.md Normal file
View file

@ -0,0 +1,46 @@
# 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/

3
CONTRIBUTING.md Normal file
View file

@ -0,0 +1,3 @@
[![Jazzband](https://jazzband.co/static/img/jazzband.svg)](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
View file

@ -1,17 +0,0 @@
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/

View file

@ -1,4 +1,4 @@
Copyright (c) 2007-2011, Jannis Leidel and contributors
Copyright (c) 2007-2019, Jannis Leidel and contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without

View file

@ -1,8 +1,4 @@
include INSTALL
include LICENSE
include AUTHORS
include README.rst
include MANIFEST.in
include LICENSE AUTHORS README.rst MANIFEST.in tox.ini .coveragerc CONTRIBUTING.md
recursive-include docs *.txt
recursive-include dbtemplates/locale *
recursive-include dbtemplates/static/dbtemplates *.css *.js

View file

@ -1,6 +1,17 @@
django-dbtemplates
==================
.. image:: https://jazzband.co/static/img/badge.svg
:alt: Jazzband
:target: https://jazzband.co/
.. image:: https://github.com/jazzband/django-dbtemplates/workflows/Test/badge.svg
:target: https://github.com/jazzband/django-dbtemplates/actions
.. image:: https://codecov.io/github/jazzband/django-dbtemplates/coverage.svg?branch=master
:alt: Codecov
:target: https://codecov.io/github/jazzband/django-dbtemplates?branch=master
``dbtemplates`` is a Django app that consists of two parts:
1. It allows you to store templates in your database
@ -10,10 +21,10 @@ django-dbtemplates
It also features optional support for versioned storage and django-admin
command, integrates with Django's caching system and the admin actions.
Please see http://django-dbtemplates.readthedocs.org/ for more details.
Please see https://django-dbtemplates.readthedocs.io/ for more details.
The source code and issue tracker can be found on Github:
https://github.com/jezdez/django-dbtemplates
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

View file

@ -1,16 +1,3 @@
VERSION = (1, 2, 0, "f", 0) # following PEP 386
DEV_N = None
import importlib.metadata
def get_version():
version = "%s.%s" % (VERSION[0], VERSION[1])
if VERSION[2]:
version = "%s.%s" % (version, VERSION[2])
if VERSION[3] != "f":
version = "%s%s%s" % (version, VERSION[3], VERSION[4])
if DEV_N:
version = "%s.dev%s" % (version, DEV_N)
return version
__version__ = get_version()
__version__ = importlib.metadata.version("django-dbtemplates")

View file

@ -1,23 +1,29 @@
import posixpath
from django import forms
from django.contrib import admin
from django.utils.translation import ungettext, ugettext_lazy as _
from django.core.exceptions import ImproperlyConfigured
from django.utils.translation import gettext_lazy as _
from django.utils.translation import ngettext
from django.utils.safestring import mark_safe
from dbtemplates.conf import settings
from dbtemplates.models import (Template,
remove_cached_template, add_template_to_cache)
from dbtemplates.models import Template, add_template_to_cache, remove_cached_template
from dbtemplates.utils.template import check_template_syntax
# Check if django-reversion is installed and use reversions' VersionAdmin
# as the base admin class if yes
if settings.DBTEMPLATES_USE_REVERSION:
# 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:
from reversion.admin import VersionAdmin as TemplateModelAdmin
else:
from django.contrib.admin import ModelAdmin as TemplateModelAdmin
from django.contrib.admin import ModelAdmin as TemplateModelAdmin # noqa
class CodeMirrorTextArea(forms.Textarea):
"""
A custom widget for the CodeMirror browser editor to be used with the
content field of the Template model.
@ -25,13 +31,14 @@ class CodeMirrorTextArea(forms.Textarea):
class Media:
css = dict(screen=[posixpath.join(
settings.DBTEMPLATES_MEDIA_PREFIX, 'css/editor.css')])
js = [posixpath.join(settings.DBTEMPLATES_MEDIA_PREFIX, 'js/codemirror.js')]
js = [posixpath.join(settings.DBTEMPLATES_MEDIA_PREFIX,
'js/codemirror.js')]
def render(self, name, value, attrs=None):
def render(self, name, value, attrs=None, renderer=None):
result = []
result.append(
super(CodeMirrorTextArea, self).render(name, value, attrs))
result.append(u"""
super().render(name, value, attrs))
result.append("""
<script type="text/javascript">
var editor = CodeMirror.fromTextArea('id_%(name)s', {
path: "%(media_prefix)sjs/",
@ -45,7 +52,8 @@ class CodeMirrorTextArea(forms.Textarea):
});
</script>
""" % dict(media_prefix=settings.DBTEMPLATES_MEDIA_PREFIX, name=name))
return mark_safe(u"".join(result))
return mark_safe("".join(result))
if settings.DBTEMPLATES_USE_CODEMIRROR:
TemplateContentTextArea = CodeMirrorTextArea
@ -54,26 +62,42 @@ else:
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.")
"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({'rows': '24'}),
widget=TemplateContentTextArea(attrs={'rows': '24'}),
help_text=content_help_text, 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'),
@ -98,7 +122,7 @@ class TemplateAdmin(TemplateModelAdmin):
for template in queryset:
remove_cached_template(template)
count = queryset.count()
message = ungettext(
message = ngettext(
"Cache of one template successfully invalidated.",
"Cache of %(count)d templates successfully invalidated.",
count)
@ -110,7 +134,7 @@ class TemplateAdmin(TemplateModelAdmin):
for template in queryset:
add_template_to_cache(template)
count = queryset.count()
message = ungettext(
message = ngettext(
"Cache successfully repopulated with one template.",
"Cache successfully repopulated with %(count)d templates.",
count)
@ -123,18 +147,19 @@ class TemplateAdmin(TemplateModelAdmin):
for template in queryset:
valid, error = check_template_syntax(template)
if not valid:
errors.append('%s: %s' % (template.name, error))
errors.append(f'{template.name}: {error}')
if errors:
count = len(errors)
message = ungettext(
message = ngettext(
"Template syntax check FAILED for %(names)s.",
"Template syntax check FAILED for %(count)d templates: %(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 = ungettext(
message = ngettext(
"Template syntax OK.",
"Template syntax OK for %(count)d templates.", count)
self.message_user(request, message % {'count': count})
@ -144,4 +169,5 @@ class TemplateAdmin(TemplateModelAdmin):
return ", ".join([site.name for site in template.sites.all()])
site_list.short_description = _('sites')
admin.site.register(Template, TemplateAdmin)

9
dbtemplates/apps.py Normal file
View file

@ -0,0 +1,9 @@
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'

View file

@ -1,13 +1,17 @@
import posixpath
from django.core.exceptions import ImproperlyConfigured
from django.conf import settings
from dbtemplates.utils.settings import AppSettings
from appconf import AppConf
class DbTemplatesSettings(AppSettings):
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
@ -15,29 +19,49 @@ class DbTemplatesSettings(AppSettings):
def configure_media_prefix(self, value):
if value is None:
base_url = getattr(self, "STATIC_URL", None)
base_url = getattr(settings, "STATIC_URL", None)
if base_url is None:
base_url = self.MEDIA_URL
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(self, "CACHES"):
if "dbtemplates" in self.CACHES:
if hasattr(settings, "CACHES"):
if "dbtemplates" in settings.CACHES:
return "dbtemplates"
else:
return "default"
if isinstance(value, basestring) and value.startswith("dbtemplates."):
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 self.INSTALLED_APPS:
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.")
"INSTALLED_APPS setting to make "
"use of it in dbtemplates.")
return value
settings = DbTemplatesSettings("DBTEMPLATES")
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

View file

@ -1,11 +1,11 @@
from django.contrib.sites.models import Site
from django.template import TemplateDoesNotExist
from django.db import router
from django.template import Origin, TemplateDoesNotExist
from django.template.loaders.base import Loader as BaseLoader
from dbtemplates.conf import settings
from dbtemplates.models import Template
from dbtemplates.utils.cache import (cache, get_cache_key,
set_and_return, get_cache_notfound_key)
from django.template.loader import BaseLoader
class Loader(BaseLoader):
@ -19,7 +19,25 @@ class Loader(BaseLoader):
"""
is_usable = True
def load_template_source(self, template_name, template_dirs=None):
def get_template_sources(self, template_name, template_dirs=None):
yield Origin(
name=template_name,
template_name=template_name,
loader=self,
)
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
@ -33,15 +51,13 @@ class Loader(BaseLoader):
# in the cache indicating that queries failed, with the current
# timestamp.
site = Site.objects.get_current()
display_name = 'dbtemplates:%s:%s:%s' % (settings.DATABASE_ENGINE,
template_name, site.domain)
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:
except Exception:
pass
# Not found in cache, move on.
@ -51,20 +67,19 @@ class Loader(BaseLoader):
notfound = cache.get(cache_notfound_key)
if notfound:
raise TemplateDoesNotExist(template_name)
except:
except Exception:
raise TemplateDoesNotExist(template_name)
# Not marked as not-found, move on...
try:
template = Template.objects.get(name__exact=template_name,
sites__in=[site.id])
return set_and_return(cache_key, template.content, display_name)
return self._load_and_store_template(template_name, cache_key,
site, sites__in=[site.id])
except (Template.MultipleObjectsReturned, Template.DoesNotExist):
try:
template = Template.objects.get(name__exact=template_name)
return set_and_return(cache_key, template.content, display_name)
except Template.DoesNotExist:
return self._load_and_store_template(template_name, cache_key,
site, sites__isnull=True)
except (Template.MultipleObjectsReturned, Template.DoesNotExist):
pass
# Mark as not-found in cache.

Binary file not shown.

View file

@ -0,0 +1,106 @@
# 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 "шаблоны"

View file

@ -1,20 +1,19 @@
from django.core.management.base import CommandError, NoArgsCommand
from django.core.management.base import CommandError, BaseCommand
from dbtemplates.models import Template
from dbtemplates.utils.template import check_template_syntax
class Command(NoArgsCommand):
class Command(BaseCommand):
help = "Ensures templates stored in the database don't have syntax errors."
def handle_noargs(self, **options):
def handle(self, **options):
errors = []
for template in Template.objects.all():
valid, error = check_template_syntax(template)
if not valid:
errors.append('%s: %s' % (template.name, error))
errors.append(f'{template.name}: {error}')
if errors:
raise CommandError(
'Some templates contained errors\n%s' % '\n'.join(errors))
# NOTE: printing instead of using self.stdout.write to maintain
# Django 1.2 compatibility
print('OK')
self.stdout.write('OK')

View file

@ -1,7 +1,5 @@
import sys
from optparse import make_option
from django.core.management.base import CommandError, NoArgsCommand
from django.core.management.base import CommandError, BaseCommand
from django.contrib.sites.models import Site
from dbtemplates.models import Template
@ -26,13 +24,15 @@ TEMPLATES = {
}
class Command(NoArgsCommand):
class Command(BaseCommand):
help = "Creates the default 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):
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):
force = options.get('force')
try:
site = Site.objects.get_current()
@ -43,7 +43,7 @@ class Command(NoArgsCommand):
verbosity = int(options.get('verbosity', 1))
for error_code in (404, 500):
template, created = Template.objects.get_or_create(
name="%s.html" % error_code)
name=f"{error_code}.html")
if created or (not created and force):
template.content = TEMPLATES.get(error_code, '')
template.save()

View file

@ -1,111 +1,153 @@
import os
import codecs
from optparse import make_option
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.conf import settings
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')
ALWAYS_ASK, FILES_TO_DATABASE, DATABASE_TO_FILES = ("0", "1", "2")
class Command(NoArgsCommand):
DIRS = []
for engine in _engine_list():
DIRS.extend(engine.dirs)
DIRS = tuple(DIRS)
app_template_dirs = get_app_template_dirs("templates")
class Command(BaseCommand):
help = "Syncs file system templates with the database bidirectionally."
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"),
make_option("-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"),
make_option("-a", "--app-first", action="store_true", dest="app_first",
default=False, help="look for templates in applications "
"directories before project templates"),
make_option("-d", "--delete", action="store_true", dest="delete",
default=False, help="Delete templates after syncing"))
def handle_noargs(self, **options):
extension = options.get('ext')
force = options.get('force')
overwrite = options.get('overwrite')
app_first = options.get('app_first')
delete = options.get('delete')
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")
if not extension.startswith("."):
extension = ".%s" % extension
extension = f".{extension}"
try:
site = Site.objects.get_current()
except:
raise CommandError("Please make sure to have the sites contrib "
"app installed and setup with a site object")
if not type(settings.TEMPLATE_DIRS) in (tuple, list):
raise CommandError("Please make sure settings.TEMPLATE_DIRS is a "
"list or tuple.")
except Exception:
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 + settings.TEMPLATE_DIRS
tpl_dirs = app_template_dirs + DIRS
else:
tpl_dirs = settings.TEMPLATE_DIRS + app_template_dirs
templatedirs = [d for d in tpl_dirs if os.path.isdir(d)]
tpl_dirs = DIRS + app_template_dirs
templatedirs = [str(d) for d in tpl_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(templatedir)[1]
if name.startswith('/'):
name = path.split(str(templatedir))[1]
if name.startswith("/"):
name = name[1:]
try:
t = Template.on_site.get(name__exact=name)
except Template.DoesNotExist:
if not force:
confirm = raw_input(
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'):
t = Template(name=name,
content=codecs.open(path, "r").read())
" (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())
t.save()
t.sites.add(site)
else:
while 1:
while True:
if overwrite == ALWAYS_ASK:
confirm = raw_input(
"\n%s exists in the database.\n"
"(1) Overwrite %s with '%s'\n"
"(2) Overwrite '%s' with %s\n"
_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: "
% (t.__repr__(),
t.__repr__(), path,
path, t.__repr__()))
% {"template": t.__repr__(), "path": path}
)
confirm = input(_i)
else:
confirm = overwrite
if confirm in ('', FILES_TO_DATABASE, DATABASE_TO_FILES):
if confirm in (
"",
FILES_TO_DATABASE,
DATABASE_TO_FILES,
):
if confirm == FILES_TO_DATABASE:
t.content = codecs.open(path, 'r').read()
t.save()
t.sites.add(site)
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(
u"Couldn't delete %s" % path)
f"Couldn't delete {path}"
)
elif confirm == DATABASE_TO_FILES:
try:
f = codecs.open(path, 'w')
with open(path, "w", encoding="utf-8") as f: # noqa
f.write(t.content)
finally:
f.close()
if delete:
t.delete()
break

View file

@ -1,57 +1,73 @@
# encoding: utf-8
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding model 'Template'
db.create_table('django_template', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('name', self.gf('django.db.models.fields.CharField')(unique=True, max_length=100)),
('content', self.gf('django.db.models.fields.TextField')(blank=True)),
('creation_date', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)),
('last_changed', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)),
))
db.send_create_signal('dbtemplates', ['Template'])
# Adding M2M table for field sites on 'Template'
db.create_table('django_template_sites', (
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
('template', models.ForeignKey(orm['dbtemplates.template'], null=False)),
('site', models.ForeignKey(orm['sites.site'], null=False))
))
db.create_unique('django_template_sites', ['template_id', 'site_id'])
import django
import django.utils.timezone
from django.db import migrations, models
def backwards(self, orm):
# Deleting model 'Template'
db.delete_table('django_template')
class Migration(migrations.Migration):
# Removing M2M table for field sites on 'Template'
db.delete_table('django_template_sites')
dependencies = [
("sites", "0001_initial"),
]
models = {
'dbtemplates.template': {
'Meta': {'ordering': "('name',)", 'object_name': 'Template', 'db_table': "'django_template'"},
'content': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'creation_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'last_changed': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
'sites': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['sites.Site']", 'symmetrical': 'False'})
},
'sites.site': {
'Meta': {'ordering': "('domain',)", 'object_name': 'Site', 'db_table': "'django_site'"},
'domain': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
}
}
complete_apps = ['dbtemplates']
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
],
),
]

View file

@ -0,0 +1,23 @@
# 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'),
),
]

View file

@ -1,39 +0,0 @@
# encoding: utf-8
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Removing unique constraint on 'Template', fields ['name']
db.delete_unique('django_template', ['name'])
def backwards(self, orm):
# Adding unique constraint on 'Template', fields ['name']
db.create_unique('django_template', ['name'])
models = {
'dbtemplates.template': {
'Meta': {'ordering': "('name',)", 'object_name': 'Template', 'db_table': "'django_template'"},
'content': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'creation_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'last_changed': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'sites': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['sites.Site']", 'symmetrical': 'False'})
},
'sites.site': {
'Meta': {'ordering': "('domain',)", 'object_name': 'Site', 'db_table': "'django_site'"},
'domain': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
}
}
complete_apps = ['dbtemplates']

View file

@ -1,33 +1,32 @@
# -*- coding: utf-8 -*-
from datetime import datetime
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
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.contrib.sites.models import Site
from django.contrib.sites.managers import CurrentSiteManager
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
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,
help_text=_("Example: 'flatpages/default.html'"))
content = models.TextField(_('content'), blank=True)
sites = models.ManyToManyField(Site, verbose_name=_('sites'),
blank=True, null=True)
creation_date = models.DateTimeField(_('creation date'),
default=datetime.now)
last_changed = models.DateTimeField(_('last changed'),
default=datetime.now)
blank=True)
creation_date = models.DateTimeField(_('creation date'), auto_now_add=True)
last_changed = models.DateTimeField(_('last changed'), auto_now=True)
objects = models.Manager()
on_site = CurrentSiteManager('sites')
@ -38,7 +37,7 @@ class Template(models.Model):
verbose_name_plural = _('templates')
ordering = ('name',)
def __unicode__(self):
def __str__(self):
return self.name
def populate(self, name=None):
@ -56,12 +55,11 @@ class Template(models.Model):
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(Template, self).save(*args, **kwargs)
super().save(*args, **kwargs)
def add_default_site(instance, **kwargs):

175
dbtemplates/test_cases.py Normal file
View file

@ -0,0 +1,175 @@
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')

View file

@ -0,0 +1,51 @@
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',
]
}
},
]

View file

@ -1,107 +0,0 @@
from __future__ import with_statement
import codecs
import os
import shutil
import tempfile
from django.core.cache.backends.base import BaseCache
from django.core.management import call_command
from django.template import loader, Context
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
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.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 test_basiscs(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(self):
result = loader.get_template("base.html").render(Context({}))
self.assertEqual(result, 'base')
result2 = loader.get_template("sub.html").render(Context({}))
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.TEMPLATE_DIRS
temp_template_dir = tempfile.mkdtemp('dbtemplates')
last_path_part = temp_template_dir.split('/')[-1]
temp_template_path = os.path.join(temp_template_dir, 'temp_test.html')
temp_template = codecs.open(temp_template_path, 'w')
try:
temp_template.write('temp test')
settings.TEMPLATE_DIRS = (temp_template_dir,)
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.assertTrue('modified' in codecs.open(temp_template_path).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.TEMPLATE_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])

View file

@ -1,23 +1,34 @@
from django.core.cache import get_cache
from django.contrib.sites.models import Site
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():
return get_cache(settings.DBTEMPLATES_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):
current_site = Site.objects.get_current()
return 'dbtemplates::%s::%s' % (name, current_site.pk)
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'
return get_cache_key(name) + "::notfound"
def remove_notfound_key(instance):
@ -47,4 +58,5 @@ 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.
"""
cache.delete(get_cache_key(instance.name))
for site in instance.sites.all():
cache.delete(get_cache_key(instance.name, site=site))

View file

@ -1,106 +0,0 @@
from inspect import getmembers
from django.conf import settings
class AppSettings(object):
"""
An app setting object to be used for handling app setting defaults
gracefully and providing a nice API for them. Say you have an app
called ``myapp`` and want to define a few defaults, and refer to the
defaults easily in the apps code. Add a ``settings.py`` to your app::
from path.to.utils import AppSettings
class MyAppSettings(AppSettings):
SETTING_1 = "one"
SETTING_2 = (
"two",
)
Then initialize the setting with the correct prefix in the location of
of your choice, e.g. ``conf.py`` of the app module::
settings = MyAppSettings(prefix="MYAPP")
The ``MyAppSettings`` instance will automatically look at Django's
global setting to determine each of the settings and respect the
provided ``prefix``. E.g. adding this to your site's ``settings.py``
will set the ``SETTING_1`` setting accordingly::
MYAPP_SETTING_1 = "uno"
Usage
-----
Instead of using ``from django.conf import settings`` as you would
usually do, you can switch to using your apps own settings module
to access the app settings::
from myapp.conf import settings
print myapp_settings.MYAPP_SETTING_1
``AppSettings`` instances also work as pass-throughs for other
global settings that aren't related to the app. For example the
following code is perfectly valid::
from myapp.conf import settings
if "myapp" in settings.INSTALLED_APPS:
print "yay, myapp is installed!"
Custom handling
---------------
Each of the settings can be individually configured with callbacks.
For example, in case a value of a setting depends on other settings
or other dependencies. The following example sets one setting to a
different value depending on a global setting::
from django.conf import settings
class MyCustomAppSettings(AppSettings):
ENABLED = True
def configure_enabled(self, value):
return value and not self.DEBUG
custom_settings = MyCustomAppSettings("MYAPP")
The value of ``custom_settings.MYAPP_ENABLED`` will vary depending on the
value of the global ``DEBUG`` setting.
Each of the app settings can be customized by providing
a method ``configure_<lower_setting_name>`` that takes the default
value as defined in the class attributes as the only parameter.
The method needs to return the value to be use for the setting in
question.
"""
def __dir__(self):
return sorted(list(set(self.__dict__.keys() + dir(settings))))
__members__ = lambda self: self.__dir__()
def __getattr__(self, name):
if name.startswith(self._prefix):
raise AttributeError("%r object has no attribute %r" %
(self.__class__.__name__, name))
return getattr(settings, name)
def __setattr__(self, name, value):
super(AppSettings, self).__setattr__(name, value)
if name in dir(settings):
setattr(settings, name, value)
def __init__(self, prefix):
super(AppSettings, self).__setattr__('_prefix', prefix)
for setting, class_value in getmembers(self.__class__):
if setting == setting.upper():
prefixed = "%s_%s" % (prefix.upper(), setting.upper())
configured_value = getattr(settings, prefixed, class_value)
callback_name = "configure_%s" % setting.lower()
callback = getattr(self, callback_name, None)
if callable(callback):
configured_value = callback(configured_value)
delattr(self.__class__, setting)
setattr(self, prefixed, configured_value)

View file

@ -1,24 +1,13 @@
from django import VERSION
from django.template import (Template, TemplateDoesNotExist,
TemplateSyntaxError)
from django.utils.importlib import import_module
TemplateSyntaxError)
def get_loaders():
from django.template.loader import template_source_loaders
if template_source_loaders is None:
try:
from django.template.loader import (
find_template as finder_func)
except ImportError:
from django.template.loader import (
find_template_source as finder_func)
try:
source, name = finder_func('test')
except TemplateDoesNotExist:
pass
from django.template.loader import template_source_loaders
return template_source_loaders or []
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):
@ -27,33 +16,18 @@ def get_template_source(name):
if loader.__module__.startswith('dbtemplates.'):
# Don't give a damn about dbtemplates' own loader.
continue
module = import_module(loader.__module__)
load_template_source = getattr(module, 'load_template_source', None)
if load_template_source is None:
load_template_source = loader.load_template_source
try:
source, origin = load_template_source(name)
for origin in loader.get_template_sources(name):
try:
source = loader.get_contents(origin)
except (NotImplementedError, TemplateDoesNotExist):
continue
if source:
return source
except NotImplementedError:
pass
except TemplateDoesNotExist:
pass
if source is None and VERSION[:2] < (1, 2):
# Django supported template source extraction still :/
try:
from django.template.loader import find_template_source
template, origin = find_template_source(name, None)
if not hasattr(template, 'render'):
return template
except (ImportError, TemplateDoesNotExist):
pass
return None
def check_template_syntax(template):
try:
Template(template.content)
except TemplateSyntaxError, e:
except TemplateSyntaxError as e:
return (False, e)
return (True, None)

View file

@ -20,7 +20,7 @@ To enable one of them you need to specify a setting called
.. 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.::
@ -61,8 +61,17 @@ Short installation howto
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://github.com/etianen/django-reversion/wiki/getting-started
.. _django-reversion's documentation: https://django-reversion.readthedocs.io/en/latest/
.. _django-reversion-compare: https://github.com/jedie/django-reversion-compare
.. _commands:

View file

@ -1,16 +1,133 @@
Changelog
=========
1.2 (08-15-11)
--------------
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.
1.1.1 (07-08-11)
----------------
v1.1.1 (2011-07-08)
-------------------
* Fixed bug in cache loading (again).
@ -23,8 +140,8 @@ Changelog
(``'dbtemplates.loader.Loader'``) and **not** the previosly included
function that ended with ``load_template_source``.
1.1 (07-06-11)
--------------
v1.1 (2011-07-06)
-----------------
* **BACKWARDS-INCOMPATIBLE** Requires Django 1.2 or higher.
For previous Django versions use an older versions of ``dbtemplates``,
@ -65,13 +182,13 @@ Changelog
* Fixed issue with cache settings handling.
1.0.1 (04-14-11)
----------------
v1.0.1 (2011-04-14)
-------------------
* Minor bugfixes with regard to the new cache handling.
1.0 (04-11-11)
--------------
v1.0 (2011-04-11)
-----------------
.. warning::
This is the first stable release of django-dbtemplates which comes with a
@ -94,46 +211,46 @@ Changelog
* Use ReadTheDocs for documentation hosting.
0.8.0 (11-07-10)
----------------
v0.8.0 (2010-11-07)
-------------------
* Added Finnish translation (by jholster)
* Added --overwrite and --app-first options to sync_templates command (by Alex Kamedov).
0.7.4 (09-23-10)
----------------
v0.7.4 (2010-09-23)
-------------------
* Fixed tests.
0.7.3 (09-21-10)
----------------
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.
0.7.2 (09-04-10)
----------------
v0.7.2 (2010-09-04)
-------------------
* Moved to Github again. Sigh.
0.7.1 (07-07-10)
----------------
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.
0.7.0 (06-24-10)
----------------
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
@ -154,14 +271,14 @@ Changelog
.. _work: https://gist.github.com/368758/86bcafe53c438e2e2a0e3442c3b30f2c6011fbba
.. _`Nic Pottier`: http://github.com/nicpottier
0.6.1 (10-19-09):
-----------------
v0.6.1 (2009-10-19)
-------------------
* Fixed issue with default site of a template, added ability to disable
default site (``DBTEMPLATES_ADD_DEFAULT_SITE``).
0.6.0 (10-09-09):
-----------------
v0.6.0 (2009-10-09)
-------------------
* Updated and added locales (Danish, Brazilian Portuguese)
@ -171,8 +288,8 @@ Changelog
* Added Sphinx documentation
0.5.7
-----
v0.5.7
------
* Updates to the docs
@ -186,8 +303,8 @@ Changelog
* fixed bug in ``create_error_template`` command.
0.5.4
-----
v0.5.4
------
* Made loader and cache backends site-aware.
@ -199,16 +316,16 @@ Changelog
* Template is now saved explicitly to backend if not existent in cache
(e.g. if deleted manually or invalidated).
0.5.3
-----
v0.5.3
------
* Removed automatic creation of 404.html and 500.html templates and added a
* 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
0.5.2
-----
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,
@ -216,8 +333,8 @@ Changelog
* Added an example Django project and docs for it
0.5.1
-----
v0.5.1
------
* Removed unneeded code that registered the model with reversion.
@ -228,8 +345,8 @@ Changelog
* Removed legacy ``sync_templates.py`` script, use ``django-admin.py
sync_templates`` from now on.
0.5.0
-----
v0.5.0
------
* Added support for `django-reversion`_
@ -237,69 +354,69 @@ Changelog
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
-----
v0.4.7
------
* Minor bugfix
0.4.6
-----
v0.4.6
------
* Minor doc change and PyPI support
0.4.5
-----
v0.4.5
------
* fixed the --force option of the sync_templates command
0.4.4
-----
v0.4.4
------
* fixed error in custom model save() after changes in Django `r8670`_.
.. _r8670: http://code.djangoproject.com/changeset/8670
0.4.3
-----
v0.4.3
------
* removed oldforms code
0.4.2
-----
v0.4.2
------
* added Hebrew translation (by mkriheli)
0.4.1
-----
v0.4.1
------
* added French (by Roland Frederic) and German locale
0.4.0
-----
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
0.3.1
-----
v0.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
-----
v0.2.5
------
* adds support for newforms-admin
@ -308,4 +425,4 @@ Support
Please leave your questions and messages on the designated site:
http://github.com/jezdez/django-dbtemplates/issues/
http://github.com/jazzband/django-dbtemplates/issues/

View file

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
#
# django-dbtemplates documentation build configuration file, created by
# sphinx-quickstart on Fri Oct 9 14:52:11 2009.
@ -16,7 +15,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 -----------------------------------------------------
@ -37,17 +36,22 @@ source_suffix = '.txt'
master_doc = 'index'
# General information about the project.
project = u'django-dbtemplates'
copyright = u'2007-2011, Jannis Leidel and contributors'
project = 'django-dbtemplates'
copyright = '2007-2019, Jannis Leidel and contributors'
# 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.
version = '1.2'
# The full version, including alpha/beta/rc tags.
release = '1.2'
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'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
@ -172,8 +176,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', u'django-dbtemplates Documentation',
u'Jannis Leidel and contributors', 'manual'),
('index', 'django-dbtemplates.tex', 'django-dbtemplates Documentation',
'Jannis Leidel and contributors', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of

View file

@ -11,9 +11,9 @@ 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 http://django-dbtemplates.readthedocs.org/ for more details.
Please see https://django-dbtemplates.readthedocs.io/ for more details.
The source code and issue tracker can be found on Github: https://github.com/jezdez/django-dbtemplates
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/#loading-templates

View file

@ -2,9 +2,8 @@ Setup
=====
1. Get the source from the `Git repository`_ or install it from the
Python Package Index by running ``pip django-dbtemplates``.
2. Follow the instructions in the INSTALL file
3. Edit the settings.py of your Django site:
Python Package Index by running ``pip install django-dbtemplates``.
2. Edit the settings.py of your Django site:
* Add ``dbtemplates`` to the ``INSTALLED_APPS`` setting
@ -24,28 +23,54 @@ Setup
'dbtemplates',
)
* Add ``dbtemplates.loader.Loader`` to the ``TEMPLATE_LOADERS`` list
* Add ``dbtemplates.loader.Loader`` to the ``TEMPLATES.OPTIONS.loaders`` list
in the settings.py of your Django project.
It should look something like this::
TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
'dbtemplates.loader.Loader',
)
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',
],
},
},
]
4. Sync your database ``python manage.py syncdb``
5. Restart your Django server
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``.
.. _Git repository: http://github.com/jezdez/django-dbtemplates/
3. Sync your database ``python manage.py migrate``
4. Restart your Django server
.. _Git repository: https://github.com/jazzband/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
"Dbtemplates" section.
"Database templates" 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.
@ -59,44 +84,3 @@ 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/

View file

@ -4,8 +4,8 @@ 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
``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``
@ -28,11 +28,24 @@ The dotted Python path to the cache backend class. See
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``
----------------------------

View file

View file

@ -1,15 +0,0 @@
#!/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)

View file

@ -1,2 +0,0 @@
south
django>=1.3

View file

@ -1,113 +0,0 @@
# 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.
DATABASES = {
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": DATABASE_NAME,
}
}
# 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.Loader',
'django.template.loaders.app_directories.Loader',
'django.template.loaders.eggs.Loader',
'dbtemplates.loader.Loader',
)
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',
'django.contrib.staticfiles',
'dbtemplates',
'south',
#'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 = "locmem://"
DBTEMPLATES_MEDIA_PREFIX = posixpath.join(STATIC_URL, "dbtemplates/")
DBTEMPLATES_USE_CODEMIRROR = True

View file

@ -1,18 +0,0 @@
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/', include(admin.site.urls)),
)

51
pyproject.toml Normal file
View file

@ -0,0 +1,51 @@
[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
requirements/docs.txt Normal file
View file

@ -0,0 +1 @@
django

2
requirements/tests.txt Normal file
View file

@ -0,0 +1,2 @@
flake8
coverage

View file

@ -1,37 +0,0 @@
#!/usr/bin/env python
import os
import sys
from django.conf import settings
if not settings.configured:
settings.configure(
DBTEMPLATES_CACHE_BACKEND = 'dummy://',
DATABASE_ENGINE='sqlite3',
SITE_ID=1,
INSTALLED_APPS=[
'django.contrib.contenttypes',
'django.contrib.sites',
'django.contrib.admin',
'dbtemplates',
],
TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
'dbtemplates.loader.Loader',
)
)
from django.test.simple import run_tests
def runtests(*test_args):
if not test_args:
test_args = ['dbtemplates']
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'dbtemplates'))
failures = run_tests(test_args, verbosity=1, interactive=True)
sys.exit(failures)
if __name__ == '__main__':
runtests(*sys.argv[1:])

View file

@ -1,13 +0,0 @@
[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

View file

@ -1,33 +0,0 @@
from setuptools import setup, find_packages
setup(
name='django-dbtemplates',
version=__import__('dbtemplates').__version__,
description='Template loader for templates stored in the database',
long_description=open('README.rst').read(),
author='Jannis Leidel',
author_email='jannis@leidel.info',
url='http://django-dbtemplates.readthedocs.org/',
packages=find_packages(exclude=['example']),
zip_safe=False,
package_data = {
'dbtemplates': [
'locale/*/LC_MESSAGES/*',
'static/dbtemplates/css/*.css',
'static/dbtemplates/js/*.js',
],
},
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 :: 2',
'Programming Language :: Python :: 2.5',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
'Framework :: Django',
],
)

86
tox.ini
View file

@ -1,41 +1,61 @@
[tox]
downloadcache = .tox/_download/
distribute = False
minversion = 4.0
envlist =
py25-1.2.X, py26-1.2.X, py27-1.2.X,
py25-1.3.X, py26-1.3.X, py27-1.3.X
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 runtests.py
python --version
python -c "import django ; print(django.VERSION)"
coverage run --branch --parallel-mode {envbindir}/django-admin test -v2 {posargs:dbtemplates}
[testenv:py25-1.2.X]
basepython = python2.5
deps =
django==1.2.5
[testenv:coverage]
basepython = python3.10
deps = coverage
commands =
coverage combine
coverage report
coverage xml
[testenv:py26-1.2.X]
basepython = python2.6
deps =
django==1.2.5
[testenv:flake8]
basepython = python3.10
commands = flake8 dbtemplates
deps = flake8
[testenv:py27-1.2.X]
basepython = python2.7
deps =
django==1.2.5
[testenv:py25-1.3.X]
basepython = python2.5
deps =
django==1.3
[testenv:py26-1.3.X]
basepython = python2.6
deps =
django==1.3
[testenv:py27-1.3.X]
basepython = python2.7
deps =
django==1.3
[flake8]
exclude=.tox
ignore=E501,E127,E128,E124