66 | {% endblock %}
67 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | import os
2 | from distutils.core import setup
3 | from distutils.command.install import INSTALL_SCHEMES
4 |
5 | app_name = 'templatesadmin'
6 | version = __import__(app_name).__version__
7 |
8 | # Tell distutils to put the data_files in platform-specific installation
9 | # locations. See here for an explanation:
10 | # http://groups.google.com/group/comp.lang.python/browse_thread/thread/35ec7b2fed36eaec/2105ee4d9e8042cb
11 | for scheme in INSTALL_SCHEMES.values():
12 | scheme['data'] = scheme['purelib']
13 |
14 | # Compile the list of packages available, because distutils doesn't have
15 | # an easy way to do this.
16 | packages, data_files = [], []
17 | root_dir = os.path.dirname(__file__)
18 | if root_dir:
19 | os.chdir(root_dir)
20 |
21 | for dirpath, dirnames, filenames in os.walk(app_name):
22 | # Ignore dirnames that start with '.'
23 | for i, dirname in enumerate(dirnames):
24 | if dirname.startswith('.'): del dirnames[i]
25 | if '__init__.py' in filenames:
26 | pkg = dirpath.replace(os.path.sep, '.')
27 | if os.path.altsep:
28 | pkg = pkg.replace(os.path.altsep, '.')
29 | packages.append(pkg)
30 | elif filenames:
31 | prefix = dirpath[len(app_name)+1:] # Strip "app_name/" or "app_name\"
32 | for f in filenames:
33 | data_files.append(os.path.join(prefix, f))
34 |
35 | setup(name='django-'+app_name,
36 | version=version,
37 | description='A Django app to make minor changes to your templates on the fly.',
38 | long_description=open('README').read(),
39 | author='Martin Mahner',
40 | author_email='martin@mahner.org',
41 | url='http://github.com/bartTC/django-templatesadmin/',
42 | package_dir={app_name: app_name},
43 | packages=packages,
44 | package_data={app_name: data_files},
45 | classifiers=['Development Status :: 4 - Beta',
46 | 'Environment :: Web Environment',
47 | 'Intended Audience :: Developers',
48 | 'License :: OSI Approved :: BSD License',
49 | 'Operating System :: OS Independent',
50 | 'Programming Language :: Python',
51 | 'Topic :: Utilities'],
52 | )
53 |
--------------------------------------------------------------------------------
/templatesadmin/edithooks/hgcommit.py:
--------------------------------------------------------------------------------
1 | from django import forms
2 | from django.conf import settings
3 | from django.utils.translation import ugettext_lazy as _
4 | from templatesadmin import TemplatesAdminException
5 | from templatesadmin.edithooks import TemplatesAdminHook
6 |
7 | from mercurial import hg, ui, match
8 | import os
9 |
10 |
11 | TEMPLATESADMIN_HG_ROOT = getattr(
12 | settings,
13 | 'TEMPLATESADMIN_HG_ROOT',
14 | None
15 | )
16 |
17 |
18 | class HgCommitHook(TemplatesAdminHook):
19 | '''
20 | Commit to git after saving
21 | '''
22 |
23 | @classmethod
24 | def post_save(cls, request, form, template_path):
25 | dir = os.path.dirname(template_path) + os.sep
26 | file = os.path.basename(template_path)
27 |
28 | if request.user.first_name and request.user.last_name:
29 | author = "%s %s" % (request.user.first_name, request.user.last_name)
30 | else:
31 | author = request.user.username
32 |
33 | message = form.cleaned_data['commitmessage'] or '--'
34 |
35 | path = TEMPLATESADMIN_HG_ROOT
36 | if path is None:
37 | for template_dir in settings.TEMPLATE_DIRS:
38 | if dir.startswith(template_dir):
39 | if path is None or len(templare_dir)>len(path):
40 | path = template_dir
41 | if path is None:
42 | raise TemplatesAdminException("Could not find template base directory")
43 | uio = ui.ui()
44 | uio.setconfig('ui', 'interactive', False)
45 | uio.setconfig('ui', 'report_untrusted', False)
46 | uio.setconfig('ui', 'quiet', True)
47 | repo = hg.repository(uio, path=path)
48 | filter = match.match(repo.root, dir, [file])
49 | repo.commit(match=filter, text=message, user="%s <%s>" % (author, request.user.email))
50 |
51 | return "Template '%s' was committed succesfully into mercurial repository." % file
52 |
53 | @classmethod
54 | def contribute_to_form(cls, template_path):
55 | return dict(commitmessage=forms.CharField(
56 | widget=forms.TextInput(attrs={'size':'100'}),
57 | label = _('Change message'),
58 | required = False,
59 | ))
60 |
--------------------------------------------------------------------------------
/templatesadmin/edithooks/gitcommit.py:
--------------------------------------------------------------------------------
1 | from django import forms
2 | from django.utils.translation import ugettext_lazy as _
3 | from templatesadmin import TemplatesAdminException
4 | from templatesadmin.edithooks import TemplatesAdminHook
5 |
6 | import subprocess
7 | import os
8 |
9 | class GitCommitHook(TemplatesAdminHook):
10 | '''
11 | Commit to git after saving
12 | '''
13 |
14 | @classmethod
15 | def post_save(cls, request, form, template_path):
16 | dir, file = os.path.dirname(template_path) + "/", os.path.basename(template_path)
17 |
18 | if request.user.first_name and request.user.last_name:
19 | author = "%s %s" % (request.user.first_name, request.user.last_name)
20 | else:
21 | author = request.user.username
22 |
23 | message = form.cleaned_data['commitmessage'] or '--'
24 |
25 | command = (
26 | 'GIT_COMMITTER_NAME="%(author)s" GIT_COMMITER_EMAIL="%(email)s" '
27 | 'GIT_AUTHOR_NAME="%(author)s" GIT_AUTHOR_EMAIL="%(email)s" '
28 | 'git commit -F - -- %(file)s'
29 | ) % {
30 | 'file': template_path,
31 | 'author': author,
32 | 'email': request.user.email,
33 | }
34 |
35 | # Stolen from gitpython's git/cmd.py
36 | proc = subprocess.Popen(
37 | args=command,
38 | shell=True,
39 | cwd=dir,
40 | stdin=subprocess.PIPE,
41 | stdout=subprocess.PIPE,
42 | stderr=subprocess.PIPE,
43 | )
44 |
45 | try:
46 | proc.stdin.write(message.encode('utf-8'))
47 | proc.stdin.close()
48 | stderr_value = proc.stderr.read()
49 | stdout_value = proc.stdout.read()
50 | status = proc.wait()
51 | finally:
52 | proc.stderr.close()
53 |
54 | if status != 0:
55 | raise TemplatesAdminException("Error while executing %s: %s" % (command, stderr_value.rstrip(), ))
56 |
57 | return stdout_value.rstrip()
58 |
59 | @classmethod
60 | def contribute_to_form(cls, template_path):
61 | return dict(commitmessage=forms.CharField(
62 | widget=forms.TextInput(attrs={'size':'100'}),
63 | label = _('Change message'),
64 | required = False,
65 | ))
66 |
--------------------------------------------------------------------------------
/README:
--------------------------------------------------------------------------------
1 | .. warning:: Not in active development. Probably not functional in latest
2 | Django version. If you like to take over the project please
3 | contact me.
4 |
5 | ===============
6 | Templates Admin
7 | ===============
8 |
9 | Templates Admin is a tiny, nifty application for your Django_ project to edit
10 | your templates, that are stored on your disk, via an admin interface.
11 |
12 | Originally this app was inspired by dbtemplates_.
13 |
14 | .. _Django: http://www.djangoproject.com/
15 | .. _dbtemplates: http://code.google.com/p/django-dbtemplates/
16 |
17 | Installation:
18 | =============
19 |
20 | 1. Put ``templatesadmin`` into your INSTALLED_APPS setting.
21 |
22 | 2. Add this line to your urlconf but **before** your admin include::
23 |
24 | (r'^admin/templatesadmin/', include('templatesadmin.urls')),
25 |
26 | 3. Create a group ``TemplateAdmins`` and put all users in there, who should been
27 | able to edit templates. You don't need to grant any permissions to that group.
28 | Just call it ``TemplateAdmins``.
29 |
30 | Keep in mind that also Superusers (*is_admin* flag) must belong to this group, if
31 | they should been able to edit templates. The group name is case-sensitive!
32 |
33 | 4. Point your webbrowser to ``http://localhost/admin/templatesadmin/`` and start
34 | editing.
35 |
36 | Optional Settings:
37 | ==================
38 |
39 | There are some settings that you can override in your ``settings.py``:
40 |
41 | 1. ``TEMPLATESADMIN_GROUP``: The name of your group of your TemplatesAdmin
42 | Users.
43 |
44 | Default: ``TemplateAdmins``
45 |
46 | 2. ``TEMPLATESADMIN_VALID_FILE_EXTENSIONS``: A tuple of file-extensions (without
47 | the leading dot) that are editable by TemplatesAdmin.
48 |
49 | Default::
50 |
51 | TEMPLATESADMIN_VALID_FILE_EXTENSIONS = (
52 | 'html',
53 | 'htm',
54 | 'txt',
55 | 'css',
56 | 'backup'
57 | )
58 |
59 | 3. ``TEMPLATESADMIN_TEMPLATE_DIRS``: A tuple of directories you want your users
60 | to edit, instead of all templates.
61 |
62 | Default: All user-defined and application template-dirs.
63 |
64 | 4. ``TEMPLATESADMIN_HIDE_READONLY``: A boolean to wether enable or disable
65 | displaying of read-only templates.
66 |
67 | Default: ``False``
68 |
69 | 5. ``TEMPLATESADMIN_EDITHOOKS``: A tuple of callables edithooks. Edithooks are
70 | a way to interact with changes made on a template. Think of a plugin system.
71 |
72 | There are two builtin edithooks:
73 |
74 | - ``dotbackupfiles.DotBackupFilesHook``: Creates a copy of the original file
75 | before overwriting, naming it ``