diff --git a/.gitignore b/.gitignore index 341cafe..9d5809f 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,5 @@ dist example/example.db docs/_build .tox/ -*.egg/ \ No newline at end of file +*.egg/ +.coverage diff --git a/.hgignore b/.hgignore deleted file mode 100644 index 508637e..0000000 --- a/.hgignore +++ /dev/null @@ -1,9 +0,0 @@ -syntax: glob -*.pyc -.*.swp -MANIFEST -build -dist -django_dbtemplates.egg-info/ -example/example.db -docs/_build \ No newline at end of file diff --git a/.hgtags b/.hgtags deleted file mode 100644 index c9e6f4c..0000000 --- a/.hgtags +++ /dev/null @@ -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 diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..71163ca --- /dev/null +++ b/.travis.yml @@ -0,0 +1,21 @@ +language: python +python: + - "2.6" + - "2.7" +before_install: + - export DJANGO_SETTINGS_MODULE=dbtemplates.test_settings +install: + - pip install -e . + - pip install -r requirements/tests.txt Django==$DJANGO +before_script: + - flake8 dbtemplates --ignore=E501 +script: + - coverage run --branch --source=dbtemplates `which django-admin.py` test dbtemplates + - coverage report --omit="dbtemplates/test*,dbtemplates/migrations*" +env: + - DJANGO=1.3.7 + - DJANGO=1.4.5 + - DJANGO=1.5.1 +branches: + only: + - develop diff --git a/.tx/config b/.tx/config index 55ac0bd..931d09f 100644 --- a/.tx/config +++ b/.tx/config @@ -1,4 +1,4 @@ -[django-dbtemplates.django] +[django-dbtemplates.main] file_filter = dbtemplates/locale//LC_MESSAGES/django.po source_file = dbtemplates/locale/en/LC_MESSAGES/django.po source_lang = en diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..9dd4105 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,18 @@ +Alen Mujezinovic +Alex Gaynor +Alex Kamedov +Alexander Artemenko +Arne Brodowski +David Paccoud +Diego Búrigo Zacarão +Dmitry Falk +Jannis Leidel +Jure Cuhalev +Jason Mayfield +Kevin Mooney +Mark Stahler +Matt Dorn +Oliver George +Selwin Ong +Stephan Peijnik , ANEXIA Internetdienstleistungs GmbH, http://www.anexia.at/ +Zhang Kun diff --git a/INSTALL b/INSTALL deleted file mode 100644 index 2e5bc7d..0000000 --- a/INSTALL +++ /dev/null @@ -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/ \ No newline at end of file diff --git a/LICENSE b/LICENSE index 66200eb..00c83fd 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2007-2010, Jannis Leidel and contributors +Copyright (c) 2007-2012, Jannis Leidel and contributors All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/MANIFEST.in b/MANIFEST.in index 4ce916b..9852006 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,5 +1,5 @@ -include INSTALL include LICENSE +include AUTHORS include README.rst include MANIFEST.in recursive-include docs *.txt diff --git a/README.rst b/README.rst index f817195..e0e9977 100644 --- a/README.rst +++ b/README.rst @@ -1,6 +1,10 @@ django-dbtemplates ================== +.. image:: https://secure.travis-ci.org/jezdez/django-dbtemplates.png?branch=develop + :alt: Build Status + :target: http://travis-ci.org/jezdez/django-dbtemplates + ``dbtemplates`` is a Django app that consists of two parts: 1. It allows you to store templates in your database @@ -12,4 +16,8 @@ command, integrates with Django's caching system and the admin actions. Please see http://django-dbtemplates.readthedocs.org/ for more details. +The source code and issue tracker can be found on Github: + +https://github.com/jezdez/django-dbtemplates + .. _template loader: http://docs.djangoproject.com/en/dev/ref/templates/api/#loader-types \ No newline at end of file diff --git a/dbtemplates/__init__.py b/dbtemplates/__init__.py index 7bba090..6524f6c 100644 --- a/dbtemplates/__init__.py +++ b/dbtemplates/__init__.py @@ -1,16 +1,2 @@ -VERSION = (1, 0, 1, "f", 0) # following PEP 386 -DEV_N = None - - -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() +# following PEP 386 +__version__ = "1.3" diff --git a/dbtemplates/admin.py b/dbtemplates/admin.py index 0979971..0a74237 100644 --- a/dbtemplates/admin.py +++ b/dbtemplates/admin.py @@ -1,19 +1,21 @@ import posixpath from django import forms from django.contrib import admin +from django.core.exceptions import ImproperlyConfigured from django.utils.translation import ungettext, ugettext_lazy as _ from django.utils.safestring import mark_safe -from dbtemplates import settings -from dbtemplates.models import (Template, - remove_cached_template, add_template_to_cache) +from dbtemplates.conf import settings +from dbtemplates.models import (Template, remove_cached_template, + add_template_to_cache) +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.USE_REVERSION: +if 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): @@ -22,9 +24,9 @@ class CodeMirrorTextArea(forms.Textarea): content field of the Template model. """ class Media: - css = dict(screen=[ - posixpath.join(settings.MEDIA_PREFIX, 'css/editor.css')]) - js = [posixpath.join(settings.MEDIA_PREFIX, 'js/codemirror.js')] + css = dict(screen=[posixpath.join( + settings.DBTEMPLATES_MEDIA_PREFIX, 'css/editor.css')]) + js = [posixpath.join(settings.DBTEMPLATES_MEDIA_PREFIX, 'js/codemirror.js')] def render(self, name, value, attrs=None): result = [] @@ -43,21 +45,30 @@ class CodeMirrorTextArea(forms.Textarea): lineNumbers: true }); -""" % dict(media_prefix=settings.MEDIA_PREFIX, name=name)) +""" % dict(media_prefix=settings.DBTEMPLATES_MEDIA_PREFIX, name=name)) return mark_safe(u"".join(result)) -if settings.USE_CODEMIRROR: +if settings.DBTEMPLATES_USE_CODEMIRROR: TemplateContentTextArea = CodeMirrorTextArea else: TemplateContentTextArea = forms.Textarea -if settings.AUTO_POPULATE_CONTENT: +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 + class TemplateAdminForm(forms.ModelForm): """ @@ -69,6 +80,7 @@ class TemplateAdminForm(forms.ModelForm): class Meta: model = Template + fields = ('name', 'content', 'sites', 'creation_date', 'last_changed') class TemplateAdmin(TemplateModelAdmin): @@ -86,33 +98,59 @@ class TemplateAdmin(TemplateModelAdmin): 'classes': ('collapse',), }), ) + filter_horizontal = ('sites',) list_display = ('name', 'creation_date', 'last_changed', 'site_list') list_filter = ('sites',) + save_as = True search_fields = ('name', 'content') - actions = ['invalidate_cache', 'repopulate_cache'] + actions = ['invalidate_cache', 'repopulate_cache', 'check_syntax'] def invalidate_cache(self, request, queryset): for template in queryset: remove_cached_template(template) + count = queryset.count() message = ungettext( "Cache of one template successfully invalidated.", "Cache of %(count)d templates successfully invalidated.", - len(queryset)) - self.message_user(request, message % {'count': len(queryset)}) + count) + self.message_user(request, message % {'count': count}) invalidate_cache.short_description = _("Invalidate cache of " "selected templates") def repopulate_cache(self, request, queryset): for template in queryset: add_template_to_cache(template) + count = queryset.count() message = ungettext( "Cache successfully repopulated with one template.", "Cache successfully repopulated with %(count)d templates.", - len(queryset)) - self.message_user(request, message % {'count': len(queryset)}) + count) + self.message_user(request, message % {'count': count}) repopulate_cache.short_description = _("Repopulate cache with " "selected templates") + def check_syntax(self, request, queryset): + errors = [] + for template in queryset: + valid, error = check_template_syntax(template) + if not valid: + errors.append('%s: %s' % (template.name, error)) + if errors: + count = len(errors) + message = ungettext( + "Template syntax check FAILED for %(names)s.", + "Template syntax check FAILED for %(count)d templates: %(names)s.", + count) + self.message_user(request, message % + {'count': count, 'names': ', '.join(errors)}) + else: + count = queryset.count() + message = ungettext( + "Template syntax OK.", + "Template syntax OK for %(count)d templates.", count) + self.message_user(request, message % {'count': count}) + check_syntax.short_description = _("Check template syntax") + def site_list(self, template): return ", ".join([site.name for site in template.sites.all()]) site_list.short_description = _('sites') diff --git a/dbtemplates/conf.py b/dbtemplates/conf.py new file mode 100644 index 0000000..eb401fb --- /dev/null +++ b/dbtemplates/conf.py @@ -0,0 +1,51 @@ +import posixpath + +from django.core.exceptions import ImproperlyConfigured +from django.conf import settings + +from appconf import AppConf + + +class DbTemplatesConf(AppConf): + USE_CODEMIRROR = False + USE_REVERSION = False + USE_TINYMCE = False + ADD_DEFAULT_SITE = True + AUTO_POPULATE_CONTENT = True + MEDIA_PREFIX = None + CACHE_BACKEND = None + + def configure_media_prefix(self, value): + if value is None: + base_url = getattr(settings, "STATIC_URL", None) + if base_url is None: + base_url = settings.MEDIA_URL + value = posixpath.join(base_url, "dbtemplates/") + return value + + def configure_cache_backend(self, value): + # If we are on Django 1.3 AND using the new CACHES setting.. + if hasattr(settings, "CACHES"): + if "dbtemplates" in settings.CACHES: + return "dbtemplates" + else: + return "default" + if isinstance(value, basestring) and value.startswith("dbtemplates."): + raise ImproperlyConfigured("Please upgrade to one of the " + "supported backends as defined " + "in the Django docs.") + return value + + def configure_use_reversion(self, value): + if value and 'reversion' not in settings.INSTALLED_APPS: + raise ImproperlyConfigured("Please add 'reversion' to your " + "INSTALLED_APPS setting to make " + "use of it in dbtemplates.") + return value + + def configure_use_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 diff --git a/dbtemplates/loader.py b/dbtemplates/loader.py index 8912ba4..118de33 100644 --- a/dbtemplates/loader.py +++ b/dbtemplates/loader.py @@ -1,14 +1,14 @@ -import warnings -from django import VERSION -from django.conf import settings from django.contrib.sites.models import Site +from django.db import router from django.template import TemplateDoesNotExist from dbtemplates.models import Template -from dbtemplates.utils import cache, get_cache_key +from dbtemplates.utils.cache import (cache, get_cache_key, + set_and_return, get_cache_notfound_key) +from django.template.loader import BaseLoader -def load_template_source(template_name, template_dirs=None, annoy=True): +class Loader(BaseLoader): """ A custom template loader to load templates from the database. @@ -17,43 +17,59 @@ def load_template_source(template_name, template_dirs=None, annoy=True): it falls back to query the database field ``name`` with the template path and ``sites`` with the current site. """ - if VERSION[:2] >= (1, 2) and annoy: - # For backward compatibility - warnings.warn( - "`dbtemplates.loader.load_template_source` is deprecated; " - "use `dbtemplates.loader.Loader` instead.", DeprecationWarning) - site = Site.objects.get_current() - display_name = 'db:%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: - pass - try: - template = Template.on_site.get(name__exact=template_name) - # Save in cache backend explicitly if manually deleted or invalidated + is_usable = True + + 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 = 'dbtemplates:%s:%s:%s' % (db, template_name, site.domain) + return set_and_return(cache_key, template.content, display_name) + + def load_template_source(self, template_name, template_dirs=None): + # The logic should work like this: + # * Try to find the template in the cache. If found, return it. + # * Now check the cache if a lookup for the given template + # has failed lately and hand over control to the next template + # loader waiting in line. + # * If this still did not fail we first try to find a site-specific + # template in the database. + # * On a failure from our last attempt we try to load the global + # template from the database. + # * If all of the above steps have failed we generate a new key + # in the cache indicating that queries failed, with the current + # timestamp. + site = Site.objects.get_current() + cache_key = get_cache_key(template_name) if cache: - cache.set(cache_key, template.content) - return (template.content, display_name) - except: - pass - raise TemplateDoesNotExist(template_name) -load_template_source.is_usable = True + try: + backend_template = cache.get(cache_key) + if backend_template: + return backend_template, template_name + except: + pass + # Not found in cache, move on. + cache_notfound_key = get_cache_notfound_key(template_name) + if cache: + try: + notfound = cache.get(cache_notfound_key) + if notfound: + raise TemplateDoesNotExist(template_name) + except: + raise TemplateDoesNotExist(template_name) -if VERSION[:2] >= (1, 2): - # providing a class based loader for Django >= 1.2, yay! - from django.template.loader import BaseLoader + # Not marked as not-found, move on... - class Loader(BaseLoader): - __doc__ = load_template_source.__doc__ + try: + return self.load_and_store_template(template_name, cache_key, + site, sites__in=[site.id]) + except (Template.MultipleObjectsReturned, Template.DoesNotExist): + try: + return self.load_and_store_template(template_name, cache_key, + site, sites__isnull=True) + except (Template.MultipleObjectsReturned, Template.DoesNotExist): + pass - is_usable = True - - def load_template_source(self, template_name, template_dirs=None): - return load_template_source( - template_name, template_dirs, annoy=False) + # Mark as not-found in cache. + cache.set(cache_notfound_key, '1') + raise TemplateDoesNotExist(template_name) diff --git a/dbtemplates/locale/da/LC_MESSAGES/django.mo b/dbtemplates/locale/da/LC_MESSAGES/django.mo index 8acc570..115a1f0 100644 Binary files a/dbtemplates/locale/da/LC_MESSAGES/django.mo and b/dbtemplates/locale/da/LC_MESSAGES/django.mo differ diff --git a/dbtemplates/locale/da/LC_MESSAGES/django.po b/dbtemplates/locale/da/LC_MESSAGES/django.po index e8e4e24..0a7cb9d 100644 --- a/dbtemplates/locale/da/LC_MESSAGES/django.po +++ b/dbtemplates/locale/da/LC_MESSAGES/django.po @@ -1,15 +1,14 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# Michael Lind Mortensen , 2009. -# +# msgid "" msgstr "" "Project-Id-Version: django-dbtemplates\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2009-10-09 13:45+0200\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME \n" +"Report-Msgid-Bugs-To: https://github.com/jezdez/django-dbtemplates/issues\n" +"POT-Creation-Date: 2011-08-15 13:13+0200\n" +"PO-Revision-Date: 2011-08-15 11:14+0000\n" +"Last-Translator: Jannis \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -17,72 +16,93 @@ msgstr "" "Language: da\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" -#: admin.py:53 +#: admin.py:56 msgid "" "Leaving this empty causes Django to look for a template with the given name " "and populate this field with its content." msgstr "" -"Hvis du efterlader dette felt tomt, så vil Django søge efter en template med " -"det givne navn og udfylde dette felt med dets indhold." +"Hvis du efterlader dette felt tomt, så vil Django søge efter en template med" +" det givne navn og udfylde dette felt med dets indhold." -#: admin.py:77 +#: admin.py:82 msgid "Advanced" msgstr "" -#: admin.py:80 +#: admin.py:85 msgid "Date/time" msgstr "Dato/tid" -#: admin.py:98 +#: admin.py:102 #, python-format msgid "Cache of one template successfully invalidated." msgid_plural "Cache of %(count)d templates successfully invalidated." msgstr[0] "" msgstr[1] "" -#: admin.py:102 +#: admin.py:106 msgid "Invalidate cache of selected templates" msgstr "" -#: admin.py:111 +#: admin.py:114 #, python-format msgid "Cache successfully repopulated with one template." msgid_plural "Cache successfully repopulated with %(count)d templates." msgstr[0] "" msgstr[1] "" -#: admin.py:115 +#: admin.py:118 msgid "Repopulate cache with selected templates" msgstr "" -#: admin.py:119 models.py:29 +#: admin.py:130 +#, python-format +msgid "Template syntax check FAILED for %(names)s." +msgid_plural "" +"Template syntax check FAILED for %(count)d templates: %(names)s." +msgstr[0] "" +msgstr[1] "" + +#: admin.py:138 +#, python-format +msgid "Template syntax OK." +msgid_plural "Template syntax OK for %(count)d templates." +msgstr[0] "" +msgstr[1] "" + +#: admin.py:141 +msgid "Check template syntax" +msgstr "" + +#: admin.py:145 models.py:25 msgid "sites" msgstr "websider" -#: models.py:26 +#: models.py:22 msgid "name" msgstr "navn" -#: models.py:27 +#: models.py:23 msgid "Example: 'flatpages/default.html'" msgstr "Eksempel: 'flatpages/default.html'" -#: models.py:28 +#: models.py:24 msgid "content" msgstr "indhold" -#: models.py:30 +#: models.py:27 msgid "creation date" msgstr "oprettelsesdato" -#: models.py:32 +#: models.py:29 msgid "last changed" msgstr "sidst ændret" -#: models.py:40 +#: models.py:37 msgid "template" msgstr "skabelon" -#: models.py:41 +#: models.py:38 msgid "templates" msgstr "skabeloner" + + diff --git a/dbtemplates/locale/de/LC_MESSAGES/django.mo b/dbtemplates/locale/de/LC_MESSAGES/django.mo index cfc7ba0..50f7fd5 100644 Binary files a/dbtemplates/locale/de/LC_MESSAGES/django.mo and b/dbtemplates/locale/de/LC_MESSAGES/django.mo differ diff --git a/dbtemplates/locale/de/LC_MESSAGES/django.po b/dbtemplates/locale/de/LC_MESSAGES/django.po index f41a7d7..f146836 100644 --- a/dbtemplates/locale/de/LC_MESSAGES/django.po +++ b/dbtemplates/locale/de/LC_MESSAGES/django.po @@ -1,19 +1,23 @@ -# +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Jannis Leidel , 2011. msgid "" msgstr "" "Project-Id-Version: django-dbtemplates\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-11-07 00:01+0100\n" -"PO-Revision-Date: 2008-08-19 17:11+0100\n" -"Last-Translator: Jannis Leidel \n" -"Language-Team: Jannis Leidel \n" +"Report-Msgid-Bugs-To: https://github.com/jezdez/django-dbtemplates/issues\n" +"POT-Creation-Date: 2011-08-15 13:13+0200\n" +"PO-Revision-Date: 2011-08-15 11:14+0000\n" +"Last-Translator: Jannis \n" +"Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: de\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" -#: admin.py:53 +#: admin.py:56 msgid "" "Leaving this empty causes Django to look for a template with the given name " "and populate this field with its content." @@ -21,66 +25,86 @@ msgstr "" "Wenn Sie dieses Feld leer lassen, wird Django versuchen, das Template mit " "dem angegebenen Namen zu finden und mit dessen Inhalt das Feld zu füllen." -#: admin.py:77 +#: admin.py:82 msgid "Advanced" msgstr "Erweiterte Einstellungen" -#: admin.py:80 +#: admin.py:85 msgid "Date/time" msgstr "Datum/Uhrzeit" -#: admin.py:98 +#: admin.py:102 #, python-format msgid "Cache of one template successfully invalidated." msgid_plural "Cache of %(count)d templates successfully invalidated." msgstr[0] "Der Cache eines Templates wurde erfolgreich geleert." msgstr[1] "Der Cache von %(count)d Templates wurde erfolgreich geleert." -#: admin.py:102 +#: admin.py:106 msgid "Invalidate cache of selected templates" msgstr "Cache der ausgewählten Templates leeren" -#: admin.py:111 +#: admin.py:114 #, python-format msgid "Cache successfully repopulated with one template." msgid_plural "Cache successfully repopulated with %(count)d templates." -msgstr[0] "" -"Der Cache eines Templates wurde erfolgreich geleert und neu gefüllt." +msgstr[0] "Der Cache eines Templates wurde erfolgreich geleert und neu gefüllt." msgstr[1] "" "Der Cache von %(count)d Templates wurde erfolgreich geleert und neu gefüllt." -#: admin.py:115 +#: admin.py:118 msgid "Repopulate cache with selected templates" msgstr "Cache der ausgewählten Templates neu füllen" -#: admin.py:119 models.py:29 +#: admin.py:130 +#, python-format +msgid "Template syntax check FAILED for %(names)s." +msgid_plural "" +"Template syntax check FAILED for %(count)d templates: %(names)s." +msgstr[0] "Template-Syntax von %(names)s ist FEHLERHAFT." +msgstr[1] "Template-Syntax von %(count)d Templates (%(names)s) ist FEHLERHAFT." + +#: admin.py:138 +#, python-format +msgid "Template syntax OK." +msgid_plural "Template syntax OK for %(count)d templates." +msgstr[0] "Template-Syntax ist OK." +msgstr[1] "Template-Syntax von %(count)d Templates ist OK." + +#: admin.py:141 +msgid "Check template syntax" +msgstr "Template-Syntax überprüfen" + +#: admin.py:145 models.py:25 msgid "sites" msgstr "Seiten" -#: models.py:26 +#: models.py:22 msgid "name" msgstr "Name" -#: models.py:27 +#: models.py:23 msgid "Example: 'flatpages/default.html'" msgstr "Zum Beispiel: 'flatpages/default.html'" -#: models.py:28 +#: models.py:24 msgid "content" msgstr "Inhalt" -#: models.py:30 +#: models.py:27 msgid "creation date" msgstr "Erstellt" -#: models.py:32 +#: models.py:29 msgid "last changed" msgstr "Geändert" -#: models.py:40 +#: models.py:37 msgid "template" msgstr "Template" -#: models.py:41 +#: models.py:38 msgid "templates" msgstr "Templates" + + diff --git a/dbtemplates/locale/en/LC_MESSAGES/django.mo b/dbtemplates/locale/en/LC_MESSAGES/django.mo index b5e8316..da3c06a 100644 Binary files a/dbtemplates/locale/en/LC_MESSAGES/django.mo and b/dbtemplates/locale/en/LC_MESSAGES/django.mo differ diff --git a/dbtemplates/locale/en/LC_MESSAGES/django.po b/dbtemplates/locale/en/LC_MESSAGES/django.po index 6c5e97c..351a27a 100644 --- a/dbtemplates/locale/en/LC_MESSAGES/django.po +++ b/dbtemplates/locale/en/LC_MESSAGES/django.po @@ -8,78 +8,97 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-11-07 00:02+0100\n" +"POT-Creation-Date: 2011-08-15 13:13+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" +"Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: admin.py:53 +#: admin.py:56 msgid "" "Leaving this empty causes Django to look for a template with the given name " "and populate this field with its content." msgstr "" -#: admin.py:77 +#: admin.py:82 msgid "Advanced" msgstr "" -#: admin.py:80 +#: admin.py:85 msgid "Date/time" msgstr "" -#: admin.py:98 +#: admin.py:102 #, python-format msgid "Cache of one template successfully invalidated." msgid_plural "Cache of %(count)d templates successfully invalidated." msgstr[0] "" msgstr[1] "" -#: admin.py:102 +#: admin.py:106 msgid "Invalidate cache of selected templates" msgstr "" -#: admin.py:111 +#: admin.py:114 #, python-format msgid "Cache successfully repopulated with one template." msgid_plural "Cache successfully repopulated with %(count)d templates." msgstr[0] "" msgstr[1] "" -#: admin.py:115 +#: admin.py:118 msgid "Repopulate cache with selected templates" msgstr "" -#: admin.py:119 models.py:29 +#: admin.py:130 +#, python-format +msgid "Template syntax check FAILED for %(names)s." +msgid_plural "Template syntax check FAILED for %(count)d templates: %(names)s." +msgstr[0] "" +msgstr[1] "" + +#: admin.py:138 +#, python-format +msgid "Template syntax OK." +msgid_plural "Template syntax OK for %(count)d templates." +msgstr[0] "" +msgstr[1] "" + +#: admin.py:141 +msgid "Check template syntax" +msgstr "" + +#: admin.py:145 models.py:25 msgid "sites" msgstr "" -#: models.py:26 +#: models.py:22 msgid "name" msgstr "" -#: models.py:27 +#: models.py:23 msgid "Example: 'flatpages/default.html'" msgstr "" -#: models.py:28 +#: models.py:24 msgid "content" msgstr "" -#: models.py:30 +#: models.py:27 msgid "creation date" msgstr "" -#: models.py:32 +#: models.py:29 msgid "last changed" msgstr "" -#: models.py:40 +#: models.py:37 msgid "template" msgstr "" -#: models.py:41 +#: models.py:38 msgid "templates" msgstr "" diff --git a/dbtemplates/locale/fi/LC_MESSAGES/django.mo b/dbtemplates/locale/fi/LC_MESSAGES/django.mo index 46ab68c..cf23e9a 100644 Binary files a/dbtemplates/locale/fi/LC_MESSAGES/django.mo and b/dbtemplates/locale/fi/LC_MESSAGES/django.mo differ diff --git a/dbtemplates/locale/fi/LC_MESSAGES/django.po b/dbtemplates/locale/fi/LC_MESSAGES/django.po index 42b66d6..2a486b4 100644 --- a/dbtemplates/locale/fi/LC_MESSAGES/django.po +++ b/dbtemplates/locale/fi/LC_MESSAGES/django.po @@ -1,15 +1,15 @@ # 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 , YEAR. -# +# +# Ville Säävuori , 2011. msgid "" msgstr "" "Project-Id-Version: django-dbtemplates\n" -"Report-Msgid-Bugs-To: \n" -"Last-Translator: Jaakko Holster \n" -"POT-Creation-Date: 2011-01-31 11:10+0100\n" -"PO-Revision-Date: 2011-01-31 10:08+0000\n" +"Report-Msgid-Bugs-To: https://github.com/jezdez/django-dbtemplates/issues\n" +"POT-Creation-Date: 2011-08-15 13:13+0200\n" +"PO-Revision-Date: 2011-08-15 11:14+0000\n" +"Last-Translator: Jannis \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -17,72 +17,93 @@ msgstr "" "Language: fi\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" -#: admin.py:53 +#: admin.py:56 msgid "" "Leaving this empty causes Django to look for a template with the given name " "and populate this field with its content." msgstr "" -"Mikäli kenttä on tyhjä, Django etsii samannimistä sivupohjaa ja täyttää " -"kentän sen sisällöllä." +"Jos tämä jätetään tyhjäksi, Django etsiin annetulla nimellä olevan " +"mallipohjan ja täyttää tähän kenttään sen sisällön." -#: admin.py:77 +#: admin.py:82 msgid "Advanced" msgstr "Lisäasetukset" -#: admin.py:80 +#: admin.py:85 msgid "Date/time" msgstr "Päiväys/aika" -#: admin.py:98 +#: admin.py:102 #, python-format msgid "Cache of one template successfully invalidated." msgid_plural "Cache of %(count)d templates successfully invalidated." -msgstr[0] "Sivupohja poistettu välimuistista." -msgstr[1] "%(count)d sivupohjaa poistettu välimuistista." +msgstr[0] "Yhden mallipohjan välimuisti on onnistuneesti tyhjennetty." +msgstr[1] "%(count)d mallipohjan välimusti on onnistuneesti tyhjennetty." -#: admin.py:102 +#: admin.py:106 msgid "Invalidate cache of selected templates" -msgstr "Poista valitut sivupohjat välimuistista." +msgstr "Tyhjennä valittujen mallipohjien välimuisti." -#: admin.py:111 +#: admin.py:114 #, python-format msgid "Cache successfully repopulated with one template." msgid_plural "Cache successfully repopulated with %(count)d templates." -msgstr[0] "Sivupohja lisätty välimuistiin." -msgstr[1] "%(count)d sivupohjaa lisätty välimuistiin." +msgstr[0] "Yhden mallipohjan välimuisti on täytetty onnistuneesti." +msgstr[1] "%(count)d mallipohjan välimuisti on täytetty onnistuneesti." -#: admin.py:115 +#: admin.py:118 msgid "Repopulate cache with selected templates" -msgstr "Lisää valitut sivupohjat välimuistiin." +msgstr "Täytä valittujen mallipohjien välimuisti." -#: admin.py:119 +#: admin.py:130 +#, python-format +msgid "Template syntax check FAILED for %(names)s." +msgid_plural "" +"Template syntax check FAILED for %(count)d templates: %(names)s." +msgstr[0] "" +msgstr[1] "" + +#: admin.py:138 +#, python-format +msgid "Template syntax OK." +msgid_plural "Template syntax OK for %(count)d templates." +msgstr[0] "" +msgstr[1] "" + +#: admin.py:141 +msgid "Check template syntax" +msgstr "" + +#: admin.py:145 models.py:25 msgid "sites" msgstr "sivustot" -#: models.py:26 +#: models.py:22 msgid "name" msgstr "nimi" -#: models.py:27 +#: models.py:23 msgid "Example: 'flatpages/default.html'" -msgstr "Esimerkki: 'flatpages/default.html'" +msgstr "Esimerkiksi: 'flatpages/default.html'" -#: models.py:28 +#: models.py:24 msgid "content" -msgstr "sisältö" +msgstr "sisätö" -#: models.py:30 +#: models.py:27 msgid "creation date" -msgstr "luotu" +msgstr "luontipäivä" -#: models.py:32 +#: models.py:29 msgid "last changed" -msgstr "muokattu" +msgstr "viimeksi muutettu" -#: models.py:40 +#: models.py:37 msgid "template" -msgstr "sivupohja" +msgstr "mallipohja" -#: models.py:41 +#: models.py:38 msgid "templates" -msgstr "sivupohjat" +msgstr "mallipohjat" + + diff --git a/dbtemplates/locale/fr/LC_MESSAGES/django.mo b/dbtemplates/locale/fr/LC_MESSAGES/django.mo index 5b975da..c52b05e 100644 Binary files a/dbtemplates/locale/fr/LC_MESSAGES/django.mo and b/dbtemplates/locale/fr/LC_MESSAGES/django.mo differ diff --git a/dbtemplates/locale/fr/LC_MESSAGES/django.po b/dbtemplates/locale/fr/LC_MESSAGES/django.po index b2b23f7..d177520 100644 --- a/dbtemplates/locale/fr/LC_MESSAGES/django.po +++ b/dbtemplates/locale/fr/LC_MESSAGES/django.po @@ -1,21 +1,22 @@ -# Roland Frédéric , 2009. -# +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. # msgid "" msgstr "" "Project-Id-Version: django-dbtemplates\n" -"Report-Msgid-Bugs-To: \n" -"Last-Translator: David Paccoud \n" -"Language-Team: French\n" -"POT-Creation-Date: 2011-01-31 11:10+0100\n" -"PO-Revision-Date: 2011-01-31 10:08+0000\n" +"Report-Msgid-Bugs-To: https://github.com/jezdez/django-dbtemplates/issues\n" +"POT-Creation-Date: 2011-08-15 13:13+0200\n" +"PO-Revision-Date: 2011-08-15 11:14+0000\n" +"Last-Translator: Jannis \n" +"Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: fr\n" "Plural-Forms: nplurals=2; plural=(n > 1)\n" -#: admin.py:53 +#: admin.py:56 msgid "" "Leaving this empty causes Django to look for a template with the given name " "and populate this field with its content." @@ -23,64 +24,85 @@ msgstr "" "Si vous laissez ceci vide , Django recherchera un modèle avec le nom donné " "et remplira ce champ avec son contenu." -#: admin.py:77 +#: admin.py:82 msgid "Advanced" msgstr "" -#: admin.py:80 +#: admin.py:85 msgid "Date/time" msgstr "Date/heure" -#: admin.py:98 -#, python-format +#: admin.py:102 +#, fuzzy, python-format msgid "Cache of one template successfully invalidated." msgid_plural "Cache of %(count)d templates successfully invalidated." msgstr[0] "Le cache d'un modèle a été invalidé avec succès." msgstr[1] "" -#: admin.py:102 +#: admin.py:106 msgid "Invalidate cache of selected templates" msgstr "Invalidation du cache des modèles sélectionnés" -#: admin.py:111 -#, python-format +#: admin.py:114 +#, fuzzy, python-format msgid "Cache successfully repopulated with one template." msgid_plural "Cache successfully repopulated with %(count)d templates." msgstr[0] "Le cache d'un modèle a été rechargé avec succès." msgstr[1] "" -#: admin.py:115 +#: admin.py:118 msgid "Repopulate cache with selected templates" msgstr "Rechargement du cache des modèles sélectionnés" -#: admin.py:119 models.py:29 +#: admin.py:130 +#, python-format +msgid "Template syntax check FAILED for %(names)s." +msgid_plural "" +"Template syntax check FAILED for %(count)d templates: %(names)s." +msgstr[0] "" +msgstr[1] "" + +#: admin.py:138 +#, python-format +msgid "Template syntax OK." +msgid_plural "Template syntax OK for %(count)d templates." +msgstr[0] "" +msgstr[1] "" + +#: admin.py:141 +msgid "Check template syntax" +msgstr "" + +#: admin.py:145 models.py:25 msgid "sites" msgstr "sites" -#: models.py:26 +#: models.py:22 msgid "name" msgstr "nom" -#: models.py:27 +#: models.py:23 msgid "Example: 'flatpages/default.html'" msgstr "Exemple : 'flatpages/default.html'" -#: models.py:28 +#: models.py:24 msgid "content" msgstr "contenu" -#: models.py:30 +#: models.py:27 msgid "creation date" msgstr "date de création" -#: models.py:32 +#: models.py:29 msgid "last changed" msgstr "dernier changement" -#: models.py:40 +#: models.py:37 msgid "template" msgstr "modèle" -#: models.py:41 +#: models.py:38 msgid "templates" msgstr "modèles" + + diff --git a/dbtemplates/locale/he/LC_MESSAGES/django.mo b/dbtemplates/locale/he/LC_MESSAGES/django.mo index 857a7df..7bf392c 100644 Binary files a/dbtemplates/locale/he/LC_MESSAGES/django.mo and b/dbtemplates/locale/he/LC_MESSAGES/django.mo differ diff --git a/dbtemplates/locale/he/LC_MESSAGES/django.po b/dbtemplates/locale/he/LC_MESSAGES/django.po index 273a20d..cfab377 100644 --- a/dbtemplates/locale/he/LC_MESSAGES/django.po +++ b/dbtemplates/locale/he/LC_MESSAGES/django.po @@ -1,86 +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 , YEAR. -# +# msgid "" msgstr "" "Project-Id-Version: django-dbtemplates\n" -"Report-Msgid-Bugs-To: \n" -"Last-Translator: <>\n" -"Language-Team: \n" -"POT-Creation-Date: 2011-01-31 11:10+0100\n" -"PO-Revision-Date: 2011-01-31 10:08+0000\n" +"Report-Msgid-Bugs-To: https://github.com/jezdez/django-dbtemplates/issues\n" +"POT-Creation-Date: 2011-08-15 13:13+0200\n" +"PO-Revision-Date: 2011-08-15 11:14+0000\n" +"Last-Translator: Jannis \n" +"Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: he\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" -#: admin.py:53 +#: admin.py:56 msgid "" "Leaving this empty causes Django to look for a template with the given name " "and populate this field with its content." msgstr "אם זה ריק אז ג'נגו מחפש תבנית עם שם סיפק וממלא את השדה עם תוכנו" -#: admin.py:77 +#: admin.py:82 msgid "Advanced" msgstr "" -#: admin.py:80 +#: admin.py:85 msgid "Date/time" msgstr "תאריך / זמן" -#: admin.py:98 +#: admin.py:102 #, python-format msgid "Cache of one template successfully invalidated." msgid_plural "Cache of %(count)d templates successfully invalidated." msgstr[0] "" msgstr[1] "" -#: admin.py:102 +#: admin.py:106 msgid "Invalidate cache of selected templates" msgstr "" -#: admin.py:111 +#: admin.py:114 #, python-format msgid "Cache successfully repopulated with one template." msgid_plural "Cache successfully repopulated with %(count)d templates." msgstr[0] "" msgstr[1] "" -#: admin.py:115 +#: admin.py:118 msgid "Repopulate cache with selected templates" msgstr "" -#: admin.py:119 models.py:29 +#: admin.py:130 +#, python-format +msgid "Template syntax check FAILED for %(names)s." +msgid_plural "" +"Template syntax check FAILED for %(count)d templates: %(names)s." +msgstr[0] "" +msgstr[1] "" + +#: admin.py:138 +#, python-format +msgid "Template syntax OK." +msgid_plural "Template syntax OK for %(count)d templates." +msgstr[0] "" +msgstr[1] "" + +#: admin.py:141 +msgid "Check template syntax" +msgstr "" + +#: admin.py:145 models.py:25 msgid "sites" msgstr "אתרים" -#: models.py:26 +#: models.py:22 msgid "name" msgstr "שם" -#: models.py:27 +#: models.py:23 msgid "Example: 'flatpages/default.html'" msgstr "דוגמא: 'flatpages/default.html'" -#: models.py:28 +#: models.py:24 msgid "content" msgstr "תוכן" -#: models.py:30 +#: models.py:27 msgid "creation date" msgstr "נוצר ב" -#: models.py:32 +#: models.py:29 msgid "last changed" msgstr "שונה ב" -#: models.py:40 +#: models.py:37 msgid "template" msgstr "תבנית" -#: models.py:41 +#: models.py:38 msgid "templates" msgstr "תבניות" + + diff --git a/dbtemplates/locale/it/LC_MESSAGES/django.mo b/dbtemplates/locale/it/LC_MESSAGES/django.mo index 4070434..a3534ee 100644 Binary files a/dbtemplates/locale/it/LC_MESSAGES/django.mo and b/dbtemplates/locale/it/LC_MESSAGES/django.mo differ diff --git a/dbtemplates/locale/it/LC_MESSAGES/django.po b/dbtemplates/locale/it/LC_MESSAGES/django.po index fb58eaf..37effcb 100644 --- a/dbtemplates/locale/it/LC_MESSAGES/django.po +++ b/dbtemplates/locale/it/LC_MESSAGES/django.po @@ -1,18 +1,22 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# msgid "" msgstr "" "Project-Id-Version: django-dbtemplates\n" -"Report-Msgid-Bugs-To: \n" -"Last-Translator: Marco Beri \n" -"Language-Team: Jannis Leidel \n" -"POT-Creation-Date: 2011-01-31 11:10+0100\n" -"PO-Revision-Date: 2011-01-31 10:08+0000\n" +"Report-Msgid-Bugs-To: https://github.com/jezdez/django-dbtemplates/issues\n" +"POT-Creation-Date: 2011-08-15 13:13+0200\n" +"PO-Revision-Date: 2011-08-15 11:14+0000\n" +"Last-Translator: Jannis \n" +"Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: it\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" -#: admin.py:53 +#: admin.py:56 msgid "" "Leaving this empty causes Django to look for a template with the given name " "and populate this field with its content." @@ -20,64 +24,85 @@ msgstr "" "Lasciandolo vuoto, Django cercherà un template con lo stesso nome che avete " "indicato sopra e userà il suo contenuto per riempire questo campo." -#: admin.py:77 +#: admin.py:82 msgid "Advanced" msgstr "" -#: admin.py:80 +#: admin.py:85 msgid "Date/time" msgstr "" -#: admin.py:98 +#: admin.py:102 #, python-format msgid "Cache of one template successfully invalidated." msgid_plural "Cache of %(count)d templates successfully invalidated." msgstr[0] "" msgstr[1] "" -#: admin.py:102 +#: admin.py:106 msgid "Invalidate cache of selected templates" msgstr "" -#: admin.py:111 +#: admin.py:114 #, python-format msgid "Cache successfully repopulated with one template." msgid_plural "Cache successfully repopulated with %(count)d templates." msgstr[0] "" msgstr[1] "" -#: admin.py:115 +#: admin.py:118 msgid "Repopulate cache with selected templates" msgstr "" -#: admin.py:119 models.py:29 +#: admin.py:130 +#, python-format +msgid "Template syntax check FAILED for %(names)s." +msgid_plural "" +"Template syntax check FAILED for %(count)d templates: %(names)s." +msgstr[0] "" +msgstr[1] "" + +#: admin.py:138 +#, python-format +msgid "Template syntax OK." +msgid_plural "Template syntax OK for %(count)d templates." +msgstr[0] "" +msgstr[1] "" + +#: admin.py:141 +msgid "Check template syntax" +msgstr "" + +#: admin.py:145 models.py:25 msgid "sites" msgstr "" -#: models.py:26 +#: models.py:22 msgid "name" msgstr "nome" -#: models.py:27 +#: models.py:23 msgid "Example: 'flatpages/default.html'" msgstr "Esempio: 'flatpages/default.html'" -#: models.py:28 +#: models.py:24 msgid "content" msgstr "contenuto" -#: models.py:30 +#: models.py:27 msgid "creation date" msgstr "data di creazione" -#: models.py:32 +#: models.py:29 msgid "last changed" msgstr "ultimo cambiamento" -#: models.py:40 +#: models.py:37 msgid "template" msgstr "template" -#: models.py:41 +#: models.py:38 msgid "templates" msgstr "template" + + diff --git a/dbtemplates/locale/pt_BR/LC_MESSAGES/django.mo b/dbtemplates/locale/pt_BR/LC_MESSAGES/django.mo index 14e12f3..335fbb6 100644 Binary files a/dbtemplates/locale/pt_BR/LC_MESSAGES/django.mo and b/dbtemplates/locale/pt_BR/LC_MESSAGES/django.mo differ diff --git a/dbtemplates/locale/pt_BR/LC_MESSAGES/django.po b/dbtemplates/locale/pt_BR/LC_MESSAGES/django.po index 9d32458..230d88f 100644 --- a/dbtemplates/locale/pt_BR/LC_MESSAGES/django.po +++ b/dbtemplates/locale/pt_BR/LC_MESSAGES/django.po @@ -1,23 +1,23 @@ # 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 , YEAR. -# +# +# Herson Hersonls , 2011. msgid "" msgstr "" "Project-Id-Version: django-dbtemplates\n" -"Report-Msgid-Bugs-To: \n" -"Last-Translator: Diego Búrigo Zacarão \n" -"Language-Team: Brazilian Portuguese \n" -"POT-Creation-Date: 2011-01-31 11:10+0100\n" -"PO-Revision-Date: 2011-01-31 10:08+0000\n" +"Report-Msgid-Bugs-To: https://github.com/jezdez/django-dbtemplates/issues\n" +"POT-Creation-Date: 2011-08-15 13:13+0200\n" +"PO-Revision-Date: 2011-08-15 11:14+0000\n" +"Last-Translator: Jannis \n" +"Language-Team: Portuguese (Brazilian) (http://www.transifex.net/projects/p/django-dbtemplates/team/pt_BR/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: pt_BR\n" "Plural-Forms: nplurals=2; plural=(n > 1)\n" -#: admin.py:53 +#: admin.py:56 msgid "" "Leaving this empty causes Django to look for a template with the given name " "and populate this field with its content." @@ -25,64 +25,85 @@ msgstr "" "Manter isto vazio faz com que o Django procure por um modelo (template) com " "o dado nome e preencha este campo com o seu conteúdo" -#: admin.py:77 +#: admin.py:82 msgid "Advanced" -msgstr "" +msgstr "Avançado" -#: admin.py:80 +#: admin.py:85 msgid "Date/time" msgstr "Data/hora" -#: admin.py:98 +#: admin.py:102 #, python-format msgid "Cache of one template successfully invalidated." msgid_plural "Cache of %(count)d templates successfully invalidated." msgstr[0] "" msgstr[1] "" -#: admin.py:102 +#: admin.py:106 msgid "Invalidate cache of selected templates" msgstr "" -#: admin.py:111 +#: admin.py:114 #, python-format msgid "Cache successfully repopulated with one template." msgid_plural "Cache successfully repopulated with %(count)d templates." msgstr[0] "" msgstr[1] "" -#: admin.py:115 +#: admin.py:118 msgid "Repopulate cache with selected templates" msgstr "" -#: admin.py:119 models.py:29 +#: admin.py:130 +#, python-format +msgid "Template syntax check FAILED for %(names)s." +msgid_plural "" +"Template syntax check FAILED for %(count)d templates: %(names)s." +msgstr[0] "" +msgstr[1] "" + +#: admin.py:138 +#, python-format +msgid "Template syntax OK." +msgid_plural "Template syntax OK for %(count)d templates." +msgstr[0] "" +msgstr[1] "" + +#: admin.py:141 +msgid "Check template syntax" +msgstr "" + +#: admin.py:145 models.py:25 msgid "sites" msgstr "sites" -#: models.py:26 +#: models.py:22 msgid "name" msgstr "Name" -#: models.py:27 +#: models.py:23 msgid "Example: 'flatpages/default.html'" msgstr "Exemplo: 'flatpages/default.html'" -#: models.py:28 +#: models.py:24 msgid "content" msgstr "conteúdo" -#: models.py:30 +#: models.py:27 msgid "creation date" msgstr "Data de criação" -#: models.py:32 +#: models.py:29 msgid "last changed" msgstr "ultima modificação" -#: models.py:40 +#: models.py:37 msgid "template" msgstr "modelo" -#: models.py:41 +#: models.py:38 msgid "templates" msgstr "modelos" + + diff --git a/dbtemplates/locale/ru/LC_MESSAGES/django.mo b/dbtemplates/locale/ru/LC_MESSAGES/django.mo new file mode 100644 index 0000000..82f769e Binary files /dev/null and b/dbtemplates/locale/ru/LC_MESSAGES/django.mo differ diff --git a/dbtemplates/locale/ru/LC_MESSAGES/django.po b/dbtemplates/locale/ru/LC_MESSAGES/django.po new file mode 100644 index 0000000..37479a7 --- /dev/null +++ b/dbtemplates/locale/ru/LC_MESSAGES/django.po @@ -0,0 +1,107 @@ +# 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 , 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 \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\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 "шаблоны" diff --git a/dbtemplates/locale/zh_CN/LC_MESSAGES/django.mo b/dbtemplates/locale/zh_CN/LC_MESSAGES/django.mo index 88c9d37..e510bcc 100644 Binary files a/dbtemplates/locale/zh_CN/LC_MESSAGES/django.mo and b/dbtemplates/locale/zh_CN/LC_MESSAGES/django.mo differ diff --git a/dbtemplates/locale/zh_CN/LC_MESSAGES/django.po b/dbtemplates/locale/zh_CN/LC_MESSAGES/django.po index 1b9ec8e..f46a6d2 100644 --- a/dbtemplates/locale/zh_CN/LC_MESSAGES/django.po +++ b/dbtemplates/locale/zh_CN/LC_MESSAGES/django.po @@ -1,15 +1,14 @@ # 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 , YEAR. -# +# msgid "" msgstr "" "Project-Id-Version: django-dbtemplates\n" -"Report-Msgid-Bugs-To: \n" -"Last-Translator: 张昆 \n" -"POT-Creation-Date: 2011-01-31 11:10+0100\n" -"PO-Revision-Date: 2011-01-31 10:08+0000\n" +"Report-Msgid-Bugs-To: https://github.com/jezdez/django-dbtemplates/issues\n" +"POT-Creation-Date: 2011-08-15 13:13+0200\n" +"PO-Revision-Date: 2011-08-15 11:14+0000\n" +"Last-Translator: Jannis \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -17,68 +16,87 @@ msgstr "" "Language: zh_CN\n" "Plural-Forms: nplurals=1; plural=0\n" -#: admin.py:53 +#: admin.py:56 msgid "" "Leaving this empty causes Django to look for a template with the given name " "and populate this field with its content." msgstr "此项目留空将使系统用指定的名称寻找模板并应用到该项目。" -#: admin.py:77 +#: admin.py:82 msgid "Advanced" msgstr "" -#: admin.py:80 +#: admin.py:85 msgid "Date/time" msgstr "日期/时间" -#: admin.py:98 -#, python-format +#: admin.py:102 +#, fuzzy, python-format msgid "Cache of one template successfully invalidated." msgid_plural "Cache of %(count)d templates successfully invalidated." msgstr[0] "该模板的缓存已经成功撤销。" -#: admin.py:102 +#: admin.py:106 msgid "Invalidate cache of selected templates" msgstr "撤销选中模板的缓存" -#: admin.py:111 -#, python-format +#: admin.py:114 +#, fuzzy, python-format msgid "Cache successfully repopulated with one template." msgid_plural "Cache successfully repopulated with %(count)d templates." msgstr[0] "该模板的缓存已经成功启用。" -#: admin.py:115 +#: admin.py:118 msgid "Repopulate cache with selected templates" msgstr "重新启用选中模板的缓存" -#: admin.py:119 models.py:29 +#: admin.py:130 +#, python-format +msgid "Template syntax check FAILED for %(names)s." +msgid_plural "" +"Template syntax check FAILED for %(count)d templates: %(names)s." +msgstr[0] "" + +#: admin.py:138 +#, python-format +msgid "Template syntax OK." +msgid_plural "Template syntax OK for %(count)d templates." +msgstr[0] "" + +#: admin.py:141 +msgid "Check template syntax" +msgstr "" + +#: admin.py:145 models.py:25 msgid "sites" msgstr "站点" -#: models.py:26 +#: models.py:22 msgid "name" msgstr "名称" -#: models.py:27 +#: models.py:23 msgid "Example: 'flatpages/default.html'" msgstr "例如: 'flatpages/default.html'" -#: models.py:28 +#: models.py:24 msgid "content" msgstr "内容" -#: models.py:30 +#: models.py:27 msgid "creation date" msgstr "创建日期" -#: models.py:32 +#: models.py:29 msgid "last changed" msgstr "最新变更" -#: models.py:40 +#: models.py:37 msgid "template" msgstr "模板" -#: models.py:41 +#: models.py:38 msgid "templates" msgstr "模板" + + diff --git a/dbtemplates/management/commands/check_template_syntax.py b/dbtemplates/management/commands/check_template_syntax.py new file mode 100644 index 0000000..214f531 --- /dev/null +++ b/dbtemplates/management/commands/check_template_syntax.py @@ -0,0 +1,21 @@ +from django.core.management.base import CommandError, NoArgsCommand + +from dbtemplates.models import Template +from dbtemplates.utils.template import check_template_syntax + + +class Command(NoArgsCommand): + help = "Ensures templates stored in the database don't have syntax errors." + + def handle_noargs(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)) + 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') diff --git a/dbtemplates/management/commands/create_error_templates.py b/dbtemplates/management/commands/create_error_templates.py index 37c6167..cbaa1d5 100644 --- a/dbtemplates/management/commands/create_error_templates.py +++ b/dbtemplates/management/commands/create_error_templates.py @@ -30,7 +30,8 @@ class Command(NoArgsCommand): 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"),) + default=False, + help="overwrite existing database templates"),) def handle_noargs(self, **options): force = options.get('force') diff --git a/dbtemplates/management/commands/sync_templates.py b/dbtemplates/management/commands/sync_templates.py index c4330e4..33feb52 100644 --- a/dbtemplates/management/commands/sync_templates.py +++ b/dbtemplates/management/commands/sync_templates.py @@ -1,36 +1,46 @@ import os +import codecs from optparse import make_option -from django.conf import settings from django.contrib.sites.models import Site from django.core.management.base import CommandError, NoArgsCommand from django.template.loaders.app_directories import app_template_dirs +from dbtemplates.conf import settings from dbtemplates.models import Template ALWAYS_ASK, FILES_TO_DATABASE, DATABASE_TO_FILES = ('0', '1', '2') + class Command(NoArgsCommand): 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("-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') if not extension.startswith("."): extension = ".%s" % extension @@ -53,10 +63,12 @@ class Command(NoArgsCommand): 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][1:] + name = path.split(templatedir)[1] + if name.startswith('/'): + name = name[1:] try: t = Template.on_site.get(name__exact=name) except Template.DoesNotExist: @@ -64,35 +76,40 @@ class Command(NoArgsCommand): confirm = raw_input( "\nA '%s' template doesn't exist in the " "database.\nCreate it with '%s'?" - " (y/[n]): """ % (name, path)) + " (y/[n]): """ % (name, path)) if force or confirm.lower().startswith('y'): t = Template(name=name, - content=open(path, "r").read()) + content=codecs.open(path, "r").read()) t.save() t.sites.add(site) else: while 1: 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" - "Type 1 or 2 or press to skip: " - % (t.__repr__(), - t.__repr__(), path, - path, t.__repr__())) + "\n%(template)s exists in the database.\n" + "(1) Overwrite %(template)s with '%(path)s'\n" + "(2) Overwrite '%(path)s' with %(template)s\n" + "Type 1 or 2 or press to skip: " % + {'template': t.__repr__(), 'path': path}) else: confirm = overwrite - if confirm == '' or confirm in ( - FILES_TO_DATABASE, DATABASE_TO_FILES): + if confirm in ('', FILES_TO_DATABASE, + DATABASE_TO_FILES): if confirm == FILES_TO_DATABASE: - t.content = open(path, 'r').read() + t.content = codecs.open(path, 'r').read() t.save() t.sites.add(site) + if delete: + try: + os.remove(path) + except OSError: + raise CommandError(u"Couldn't delete %s" % path) elif confirm == DATABASE_TO_FILES: + f = codecs.open(path, 'w', 'utf-8') try: - f = open(path, 'w') f.write(t.content) finally: f.close() + if delete: + t.delete() break diff --git a/dbtemplates/migrations/0001_initial.py b/dbtemplates/migrations/0001_initial.py new file mode 100644 index 0000000..0e08603 --- /dev/null +++ b/dbtemplates/migrations/0001_initial.py @@ -0,0 +1,55 @@ +# 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']) + + def backwards(self, orm): + # Deleting model 'Template' + db.delete_table('django_template') + + # Removing M2M table for field sites on 'Template' + db.delete_table('django_template_sites') + + 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'] diff --git a/dbtemplates/migrations/0002_auto__del_unique_template_name.py b/dbtemplates/migrations/0002_auto__del_unique_template_name.py new file mode 100644 index 0000000..418a3ab --- /dev/null +++ b/dbtemplates/migrations/0002_auto__del_unique_template_name.py @@ -0,0 +1,34 @@ +# encoding: utf-8 +from south.db import db +from south.v2 import SchemaMigration + + +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'] diff --git a/dbtemplates/migrations/__init__.py b/dbtemplates/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/dbtemplates/models.py b/dbtemplates/models.py index cf7035c..02e8081 100644 --- a/dbtemplates/models.py +++ b/dbtemplates/models.py @@ -1,17 +1,21 @@ # -*- coding: utf-8 -*- -from datetime import datetime - 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.utils.translation import ugettext_lazy as _ from django.contrib.sites.models import Site from django.contrib.sites.managers import CurrentSiteManager -from dbtemplates import settings -from dbtemplates.utils import (add_default_site, add_template_to_cache, - remove_cached_template, get_template_source) +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 + +try: + from django.utils.timezone import now +except ImportError: + from datetime import datetime + now = datetime.now class Template(models.Model): @@ -19,14 +23,15 @@ 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. """ - name = models.CharField(_('name'), unique=True, max_length=100, + 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')) + sites = models.ManyToManyField(Site, verbose_name=_(u'sites'), + blank=True, null=True) creation_date = models.DateTimeField(_('creation date'), - default=datetime.now) + default=now) last_changed = models.DateTimeField(_('last changed'), - default=datetime.now) + default=now) objects = models.Manager() on_site = CurrentSiteManager('sites') @@ -55,14 +60,27 @@ class Template(models.Model): pass def save(self, *args, **kwargs): - self.last_changed = datetime.now() + self.last_changed = now() # If content is empty look for a template with the given name and # populate the template instance with its content. - if settings.AUTO_POPULATE_CONTENT and not self.content: + if settings.DBTEMPLATES_AUTO_POPULATE_CONTENT and not self.content: self.populate() super(Template, self).save(*args, **kwargs) +def add_default_site(instance, **kwargs): + """ + Called via Django's signals to cache the templates, if the template + in the database was added or changed, only if + DBTEMPLATES_ADD_DEFAULT_SITE setting is set. + """ + if not settings.DBTEMPLATES_ADD_DEFAULT_SITE: + return + current_site = Site.objects.get_current() + if current_site not in instance.sites.all(): + instance.sites.add(current_site) + + signals.post_save.connect(add_default_site, sender=Template) signals.post_save.connect(add_template_to_cache, sender=Template) signals.pre_delete.connect(remove_cached_template, sender=Template) diff --git a/dbtemplates/settings.py b/dbtemplates/settings.py deleted file mode 100644 index 7fc5141..0000000 --- a/dbtemplates/settings.py +++ /dev/null @@ -1,33 +0,0 @@ -import posixpath -from django.conf import settings -from django.core.exceptions import ImproperlyConfigured - -if "dbtemplates" in getattr(settings, "CACHES", {}): - # If we are on Django 1.3 AND using the new CACHES setting.. - cache = "dbtemplates" -else: - # ..or fall back to the old CACHE_BACKEND setting - cache = getattr(settings, "DBTEMPLATES_CACHE_BACKEND", None) -if isinstance(cache, basestring) and cache.startswith("dbtemplates."): - raise ImproperlyConfigured("Please upgrade to one of the supported " - "backends as defined in the Django docs.") -CACHE_BACKEND = cache - -ADD_DEFAULT_SITE = getattr(settings, 'DBTEMPLATES_ADD_DEFAULT_SITE', True) - -AUTO_POPULATE_CONTENT = getattr( - settings, 'DBTEMPLATES_AUTO_POPULATE_CONTENT', True) - -base_url = getattr(settings, "STATIC_URL", None) -if base_url is None: - base_url = settings.MEDIA_URL -MEDIA_PREFIX = getattr(settings, 'DBTEMPLATES_MEDIA_PREFIX', - posixpath.join(base_url, "dbtemplates/")) - -USE_REVERSION = getattr(settings, 'DBTEMPLATES_USE_REVERSION', False) - -if USE_REVERSION and 'reversion'not in settings.INSTALLED_APPS: - raise ImproperlyConfigured("Please add reversion to your " - "INSTALLED_APPS setting to make use of it in dbtemplates.") - -USE_CODEMIRROR = getattr(settings, 'DBTEMPLATES_USE_CODEMIRROR', False) diff --git a/dbtemplates/test_cases.py b/dbtemplates/test_cases.py new file mode 100644 index 0000000..1878b29 --- /dev/null +++ b/dbtemplates/test_cases.py @@ -0,0 +1,147 @@ +import codecs +import os +import shutil +import tempfile + +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, Context, 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_template_loaders = settings.TEMPLATE_LOADERS + if 'dbtemplates.loader.Loader' not in settings.TEMPLATE_LOADERS: + loader.template_source_loaders = None + settings.TEMPLATE_LOADERS = (list(settings.TEMPLATE_LOADERS) + + ['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.TEMPLATE_LOADERS = self.old_template_loaders + + 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_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(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') + 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]) + + def test_get_cache_name(self): + self.assertEqual(get_cache_key('name with spaces'), + 'dbtemplates::name-with-spaces::1') diff --git a/dbtemplates/test_settings.py b/dbtemplates/test_settings.py new file mode 100644 index 0000000..a948cba --- /dev/null +++ b/dbtemplates/test_settings.py @@ -0,0 +1,32 @@ +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.admin', + 'django.contrib.auth', + 'dbtemplates', +] + +TEMPLATE_LOADERS = ( + 'django.template.loaders.filesystem.Loader', + 'django.template.loaders.app_directories.Loader', + 'dbtemplates.loader.Loader', +) + +TEST_RUNNER = 'discover_runner.DiscoverRunner' diff --git a/dbtemplates/tests.py b/dbtemplates/tests.py deleted file mode 100644 index ebf35ce..0000000 --- a/dbtemplates/tests.py +++ /dev/null @@ -1,66 +0,0 @@ -from django import VERSION -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 import settings -from dbtemplates.loader import load_template_source -from dbtemplates.models import Template, get_template_source - -class DbTemplatesTestCase(TestCase): - def setUp(self): - self.site1, created1 = Site.objects.get_or_create(domain="example.com", name="example.com") - self.site2, created2 = Site.objects.get_or_create(domain="example.org", name="example.org") - - def test_basiscs(self): - t1 = Template(name='base.html', content='{% block content %}Welcome at {{ title }}{% endblock %}') - t1.save() - self.assertEqual(Site.objects.get_current(), t1.sites.all()[0]) - self.assertTrue("Welcome at" in t1.content) - - t2 = Template(name='sub.html', content='{% extends "base.html" %}{% block content %}This is {{ title }}{% endblock %}') - t2.save() - t2.sites.add(self.site2) - - self.assertEqual(list(Template.objects.filter(sites=self.site1)), [t1, t2]) - self.assertEqual(list(t2.sites.all()), [self.site1, self.site2]) - - def test_load_templates(self): - self.test_basiscs() - original_template_source_loaders = loader.template_source_loaders - loader.template_source_loaders = [load_template_source] - try: - result1 = loader.get_template("base.html").render(Context({'title':'MainPage'})) - self.assertEqual(result1, u'Welcome at MainPage') - result2 = loader.get_template("sub.html").render(Context({'title':'SubPage'})) - self.assertEqual(result2, u'This is SubPage') - - if VERSION[:2] >= (1, 2): - from dbtemplates.loader import Loader - dbloader = Loader() - loader.template_source_loaders = [dbloader.load_template_source] - result = loader.get_template("base.html").render(Context({'title':'MainPage'})) - self.assertEqual(result, u'Welcome at MainPage') - result2 = loader.get_template("sub.html").render(Context({'title':'SubPage'})) - self.assertEqual(result2, u'This is SubPage') - finally: - loader.template_source_loaders = original_template_source_loaders - - def test_error_templates_creation(self): - call_command('create_error_templates', force=True, verbosity=0) - self.assertEqual(list(Template.objects.filter(sites=self.site1)), - list(Template.objects.filter())) - - def test_disabling_default_site(self): - old_add_default_site = settings.ADD_DEFAULT_SITE - settings.ADD_DEFAULT_SITE = False - t3 = Template.objects.create(name='footer.html', content='ohai') - self.assertEqual(list(t3.sites.all()), []) - settings.ADD_DEFAULT_SITE = old_add_default_site - - def test_automatic_sync(self): - admin_base_template = get_template_source('admin/base.html') - template = Template.objects.create(name='admin/base.html') - self.assertEqual(admin_base_template, template.content) diff --git a/dbtemplates/utils.py b/dbtemplates/utils.py deleted file mode 100644 index 8ebeff9..0000000 --- a/dbtemplates/utils.py +++ /dev/null @@ -1,95 +0,0 @@ -from django import VERSION -from django.core.cache import get_cache -from django.template import TemplateDoesNotExist -from django.utils.importlib import import_module - -from django.contrib.sites.models import Site - -from dbtemplates import settings - - -def get_cache_backend(): - return get_cache(settings.CACHE_BACKEND) - -cache = get_cache_backend() - - -def add_default_site(instance, **kwargs): - """ - Called via Django's signals to cache the templates, if the template - in the database was added or changed, only if DBTEMPLATES_ADD_DEFAULT_SITE - setting is set. - """ - if settings.ADD_DEFAULT_SITE: - current_site = Site.objects.get_current() - if current_site not in instance.sites.all(): - instance.sites.add(current_site) - - -def get_cache_key(name): - current_site = Site.objects.get_current() - return 'dbtemplates::%s::%s' % (name, current_site.pk) - - -def add_template_to_cache(instance, **kwargs): - """ - Called via Django's signals to cache the templates, if the template - in the database was added or changed. - """ - remove_cached_template(instance) - cache.set(get_cache_key(instance.name), instance.content) - - -def remove_cached_template(instance, **kwargs): - """ - Called via Django's signals to remove cached templates, if the template - in the database was changed or deleted. - """ - cache.delete(get_cache_key(instance.name)) - - -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 [] - - -def get_template_source(name): - source = None - for loader in get_loaders(): - if loader.__module__.startswith('dbtemplates.'): - # Don't give a damn about dbtemplates' own loader. - continue - 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) - 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 diff --git a/dbtemplates/utils/__init__.py b/dbtemplates/utils/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/dbtemplates/utils/cache.py b/dbtemplates/utils/cache.py new file mode 100644 index 0000000..13a48d7 --- /dev/null +++ b/dbtemplates/utils/cache.py @@ -0,0 +1,51 @@ +from django.core.cache import get_cache + +from django.contrib.sites.models import Site +from django.template.defaultfilters import slugify + +from dbtemplates.conf import settings + + +def get_cache_backend(): + return get_cache(settings.DBTEMPLATES_CACHE_BACKEND) + +cache = get_cache_backend() + + +def get_cache_key(name): + current_site = Site.objects.get_current() + return 'dbtemplates::%s::%s' % (slugify(name), current_site.pk) + + +def get_cache_notfound_key(name): + return get_cache_key(name) + '::notfound' + + +def remove_notfound_key(instance): + # Remove notfound key as soon as we save the template. + cache.delete(get_cache_notfound_key(instance.name)) + + +def set_and_return(cache_key, content, display_name): + # Save in cache backend explicitly if manually deleted or invalidated + if cache: + cache.set(cache_key, content) + return (content, display_name) + + +def add_template_to_cache(instance, **kwargs): + """ + Called via Django's signals to cache the templates, if the template + in the database was added or changed. + """ + remove_cached_template(instance) + remove_notfound_key(instance) + cache.set(get_cache_key(instance.name), instance.content) + + +def remove_cached_template(instance, **kwargs): + """ + Called via Django's signals to remove cached templates, if the template + in the database was changed or deleted. + """ + cache.delete(get_cache_key(instance.name)) diff --git a/dbtemplates/utils/template.py b/dbtemplates/utils/template.py new file mode 100644 index 0000000..93bc1fd --- /dev/null +++ b/dbtemplates/utils/template.py @@ -0,0 +1,57 @@ +from django import VERSION +from django.template import (Template, TemplateDoesNotExist, + TemplateSyntaxError) +from django.utils.importlib import import_module + + +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 + except ImportError: + from django.template.loader import find_template_source as finder # noqa + try: + source, name = finder('test') + except TemplateDoesNotExist: + pass + from django.template.loader import template_source_loaders + return template_source_loaders or [] + + +def get_template_source(name): + source = None + for loader in get_loaders(): + if loader.__module__.startswith('dbtemplates.'): + # Don't give a damn about dbtemplates' own loader. + continue + 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) + 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: + return (False, e) + return (True, None) diff --git a/docs/advanced.txt b/docs/advanced.txt index bc30709..273ab03 100644 --- a/docs/advanced.txt +++ b/docs/advanced.txt @@ -62,7 +62,7 @@ Short installation howto 4. Set ``DBTEMPLATES_USE_REVERSION`` setting to ``True`` .. _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: http://django-reversion.readthedocs.org/en/latest/ .. _commands: @@ -82,6 +82,12 @@ Management commands Tries to add the two templates ``404.html`` and ``500.html`` that are used by Django when a error occurs. +* ``check_template_syntax`` + + .. versionadded:: 1.2 + + Checks the saved templates whether they are valid Django templates. + .. _Django management commands: http://docs.djangoproject.com/en/dev/ref/django-admin/ .. _admin_actions: @@ -101,4 +107,10 @@ Admin actions Repopulates the cache with selected templates by invalidating it first and filling then after that. +* ``check_syntax`` + + .. versionadded:: 1.2 + + Checks the selected tempaltes for syntax errors. + .. _admin actions: http://docs.djangoproject.com/en/dev/ref/contrib/admin/actions/ diff --git a/docs/changelog.txt b/docs/changelog.txt index 841023e..43a9f28 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -1,13 +1,116 @@ Changelog ========= -1.0.1 (04-14-11) ----------------- +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/jezdez/django-dbtemplates + +.. _nose: http://nose.rtfd.org/ +.. _Travis: http://travis-ci.org + +v1.2.1 (2011-09-07) +------------------- + +* Fixed a wrong use of the non-lazy localization tools. + +* Fixed bugs in the documentation. + +* Make use of django-appconf and versiontools. + +v1.2 (2011-08-15) +----------------- + +* Refactored the template loader to be even more cache effective. + +* Added ``check_template_syntax`` management command and admin action + to make sure the saved templates are valid Django templates. + +v1.1.1 (2011-07-08) +------------------- + +* Fixed bug in cache loading (again). + +* Fixed bugs in the documentation. + +.. note:: + + Since ``dbtemplates`` removed support for Django lower than 1.2 you + have to use the template loader class in the ``TEMPLATE_LOADERS`` + (``'dbtemplates.loader.Loader'``) and **not** the previosly included + function that ended with ``load_template_source``. + +v1.1 (2011-07-06) +----------------- + +* **BACKWARDS-INCOMPATIBLE** Requires Django 1.2 or higher. + For previous Django versions use an older versions of ``dbtemplates``, + e.g.:: + + $ pip install "django-dbtemplates<1.1" + +* Added South migrations. + +.. note:: + + If you are using South in your Django project, you can easily enable + dbtemplates' migrations, *faking* the first migration by using the + ``--fake`` option of South's ``migrate`` management command:: + + $ manage.py migrate --fake 0001 dbtemplates + + Then run the rest of the migrations:: + + $ manage.py migrate dbtemplates + +* Removed uniqueness on the ``name`` field of the ``Template`` model. This is + needed because there isn't a ``unique_together`` for M2M fields in Django + such as the ``sites`` field in the ``Template`` model. + +* Made the ``sites`` field optional to support a way to apply a template to + all sites. + +* Added ``--delete`` option to ``sync_templates`` managment command to delete + the file or database entry after syncing (depending on used ``--overwrite`` + mode). + +* Updated translations. + +* Fixed issue with incorrectly splitting paths in ``sync_templates``. + +* Extended tests. + +* Fixed issue with cache settings handling. + +v1.0.1 (2011-04-14) +------------------- * Minor bugfixes with regard to the new cache handling. -1.0 (04-11-11) --------------- +v1.0 (2011-04-11) +----------------- .. warning:: This is the first stable release of django-dbtemplates which comes with a @@ -30,33 +133,33 @@ 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. @@ -68,8 +171,8 @@ Changelog 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 @@ -90,14 +193,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) @@ -107,8 +210,8 @@ Changelog * Added Sphinx documentation -0.5.7 ------ +v0.5.7 +------ * Updates to the docs @@ -122,8 +225,8 @@ Changelog * fixed bug in ``create_error_template`` command. -0.5.4 ------ +v0.5.4 +------ * Made loader and cache backends site-aware. @@ -135,16 +238,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, @@ -152,8 +255,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. @@ -164,8 +267,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`_ @@ -182,60 +285,60 @@ Changelog .. _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 diff --git a/docs/conf.py b/docs/conf.py index ee20d84..0bccac6 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -16,7 +16,7 @@ import sys, os # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. -#sys.path.append(os.path.abspath('.')) +sys.path.append(os.path.abspath('.')) # -- General configuration ----------------------------------------------------- @@ -38,16 +38,21 @@ master_doc = 'index' # General information about the project. project = u'django-dbtemplates' -copyright = u'2010, Jannis Leidel' +copyright = u'2007-2012, 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.0' -# The full version, including alpha/beta/rc tags. -release = '1.0.1' +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. @@ -173,7 +178,7 @@ htmlhelp_basename = 'django-dbtemplatesdoc' # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ ('index', 'django-dbtemplates.tex', u'django-dbtemplates Documentation', - u'Jannis Leidel', 'manual'), + u'Jannis Leidel and contributors', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of diff --git a/docs/index.txt b/docs/index.txt index 06c5bb7..2b1336c 100644 --- a/docs/index.txt +++ b/docs/index.txt @@ -11,6 +11,10 @@ It also features optional support for :ref:`versioned storage ` and :ref:`django-admin command `, integrates with Django's :ref:`caching system ` and the :ref:`admin actions `. +Please see http://django-dbtemplates.readthedocs.org/ for more details. + +The source code and issue tracker can be found on Github: https://github.com/jezdez/django-dbtemplates + .. _template loader: http://docs.djangoproject.com/en/dev/ref/templates/api/#loading-templates Contents: diff --git a/docs/overview.txt b/docs/overview.txt index 2465a3c..8d67121 100644 --- a/docs/overview.txt +++ b/docs/overview.txt @@ -2,7 +2,7 @@ Setup ===== 1. Get the source from the `Git repository`_ or install it from the - Python Package Index by running ``pip django-dbtemplates``. + Python Package Index by running ``pip install django-dbtemplates``. 2. Follow the instructions in the INSTALL file 3. Edit the settings.py of your Django site: @@ -30,11 +30,16 @@ Setup It should look something like this:: TEMPLATE_LOADERS = ( - 'django.template.loaders.filesystem.load_template_source', - 'django.template.loaders.app_directories.load_template_source', + 'django.template.loaders.filesystem.Loader', + 'django.template.loaders.app_directories.Loader', 'dbtemplates.loader.Loader', ) + Order of TEMPLATE_LOADERS is important. In the former example, templates from database + will be used as a fallback (ie. when template does not exists in other locations). + If you want template from database to be used to override templates in other locations, + put ``dbtemplates.loader.Loader`` at beginning of ``TEMPLATE_LOADERS`` settting. + 4. Sync your database ``python manage.py syncdb`` 5. Restart your Django server diff --git a/docs/settings.txt b/docs/settings.txt index 3494c14..45b5bbe 100644 --- a/docs/settings.txt +++ b/docs/settings.txt @@ -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,6 +28,14 @@ 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`` ----------------------------- diff --git a/example/requirements.txt b/example/requirements.txt index b9eea7a..0819cc5 100644 --- a/example/requirements.txt +++ b/example/requirements.txt @@ -1 +1,2 @@ -django-staticfiles \ No newline at end of file +south +django>=1.3 \ No newline at end of file diff --git a/example/settings.py b/example/settings.py index c18b770..392214c 100644 --- a/example/settings.py +++ b/example/settings.py @@ -70,10 +70,10 @@ SECRET_KEY = 'e-%(1e1f8ar2v)_8d!%-75a2ag(w(ht*l%n-wts5$li!5=97)8' # List of callables that know how to import templates from various sources. TEMPLATE_LOADERS = ( - 'django.template.loaders.filesystem.load_template_source', - 'django.template.loaders.app_directories.load_template_source', - 'django.template.loaders.eggs.load_template_source', - 'dbtemplates.loader.load_template_source', + 'django.template.loaders.filesystem.Loader', + 'django.template.loaders.app_directories.Loader', + 'django.template.loaders.eggs.Loader', + 'dbtemplates.loader.Loader', ) MIDDLEWARE_CLASSES = ( @@ -98,8 +98,9 @@ INSTALLED_APPS = ( 'django.contrib.sites', 'django.contrib.admin', 'django.contrib.flatpages', + 'django.contrib.staticfiles', 'dbtemplates', - 'staticfiles', + 'south', #'reversion', ) diff --git a/example/urls.py b/example/urls.py index 323d970..7b8c5ff 100644 --- a/example/urls.py +++ b/example/urls.py @@ -16,9 +16,3 @@ urlpatterns = patterns('', # Uncomment the next line to enable the admin: (r'^admin/', include(admin.site.urls)), ) - -# the following is used to serve up local media files like images -if settings.DEBUG: - urlpatterns += patterns("", - (r"", include("staticfiles.urls")), - ) diff --git a/requirements/tests.txt b/requirements/tests.txt new file mode 100644 index 0000000..b29024e --- /dev/null +++ b/requirements/tests.txt @@ -0,0 +1,3 @@ +flake8 +django-discover-runner +coverage diff --git a/runtests.py b/runtests.py deleted file mode 100644 index a9b1115..0000000 --- a/runtests.py +++ /dev/null @@ -1,32 +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', - ], - ) - -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:]) diff --git a/setup.py b/setup.py index 6a82ee7..778878f 100644 --- a/setup.py +++ b/setup.py @@ -1,16 +1,33 @@ +import os +import re +import codecs from setuptools import setup, find_packages + +def read(*parts): + return codecs.open(os.path.join(os.path.dirname(__file__), *parts)).read() + + +def find_version(*file_paths): + version_file = read(*file_paths) + version_match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]", + version_file, re.M) + if version_match: + return version_match.group(1) + raise RuntimeError("Unable to find version string.") + + setup( name='django-dbtemplates', - version=__import__('dbtemplates').__version__, + version=find_version('dbtemplates', '__init__.py'), description='Template loader for templates stored in the database', - long_description=open('README.rst').read(), + long_description=read('README.rst'), author='Jannis Leidel', author_email='jannis@leidel.info', url='http://django-dbtemplates.readthedocs.org/', packages=find_packages(exclude=['example']), zip_safe=False, - package_data = { + package_data={ 'dbtemplates': [ 'locale/*/LC_MESSAGES/*', 'static/dbtemplates/css/*.css', @@ -18,12 +35,17 @@ setup( ], }, classifiers=[ - 'Development Status :: 4 - Beta', + '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', ], + install_requires=['django-appconf >= 0.4'], ) diff --git a/tox.ini b/tox.ini deleted file mode 100644 index deb8479..0000000 --- a/tox.ini +++ /dev/null @@ -1,58 +0,0 @@ -[tox] -downloadcache = .tox/_download/ -distribute = False -envlist = - py25-1.1.X, py26-1.1.X, py27-1.1.X, - py25-1.2.X, py26-1.2.X, py27-1.2.X, - py25-1.3.X, py26-1.3.X, py27-1.3.X - -[testenv] -commands = - python runtests.py - -[testenv:py25-1.1.X] -basepython = python2.5 -deps = - django==1.1.4 - -[testenv:py26-1.1.X] -basepython = python2.6 -deps = - django==1.1.4 - -[testenv:py27-1.1.X] -basepython = python2.7 -deps = - django==1.1.4 - - -[testenv:py25-1.2.X] -basepython = python2.5 -deps = - django==1.2.5 - -[testenv:py26-1.2.X] -basepython = python2.6 -deps = - django==1.2.5 - -[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