Permalink
Browse files

Initial version.

  • Loading branch information...
1 parent fe08ba8 commit aad12a66c3f3e5a7c013cefa5f826c8103f676c5 @BertrandBordage committed Aug 5, 2012
View
@@ -1,4 +1,3 @@
*.log
-*.pot
*.pyc
-local_settings.py
+*~
View
@@ -0,0 +1,25 @@
+Copyright © 2012, Bertrand Bordage <bordage.bertrand@gmail.com>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the Xenofox, LLC nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
View
@@ -0,0 +1,2 @@
+include README.rst COPYING
+recursive-include terms *.html
View
@@ -1,4 +0,0 @@
-django-terms
-============
-
-Site-wide adds a description or a link for specialized terms.
View
@@ -0,0 +1,42 @@
+************
+django-terms
+************
+
+Site-wide adds a description or a link for specialized terms.
+
+
+
+Requirements
+============
+
+Mandatory
+---------
+
+* Django (tested with 1.4)
+
+
+Optional
+--------
+
+* django-reversion
+* django-cms (apphook and menu)
+
+
+
+Installation
+============
+
+#. ``pip install django-terms``
+#. Add ``'terms',`` to your ``INSTALLED_APPS``.
+#. Add ``'terms.middleware.TermsMiddleware',`` to your ``MIDDLEWARE_CLASSES``.
+#. Add terms to your urls:
+ * add ``url(r'^/', include('cmsplugin_poll.urls')),`` to your ``urls.py`` ;
+ * or, if you are using django-CMS, add a page and use the apphook and menu.
+
+
+
+Usage
+=====
+
+Add some terms in the admin and a link will be automatically added to its
+definition.
View
@@ -0,0 +1,32 @@
+#!/usr/bin/env python
+# coding: utf-8
+
+import os
+from setuptools import setup, find_packages
+
+
+setup(
+ name = 'django-terms',
+ version = '0.1',
+ author = 'Bertrand Bordage',
+ author_email = 'bordage.bertrand@gmail.com',
+ url = 'https://github.com/BertrandBordage/django-terms',
+ description = 'Site-wide adds a description or a link for specialized terms.',
+ long_description = open('README.rst').read(),
+ classifiers = [
+ 'Development Status :: 3 - Alpha',
+ 'Framework :: Django',
+ 'Intended Audience :: Developers',
+ 'License :: OSI Approved :: BSD License',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python',
+ 'Topic :: Internet :: WWW/HTTP',
+ ],
+ license = 'BSD',
+ packages = find_packages(),
+ install_requires=[
+ "Django >= 1.4",
+ ],
+ include_package_data=True,
+ zip_safe = False,
+)
View
No changes.
View
@@ -0,0 +1,15 @@
+# coding: utf-8
+
+from django.contrib.admin import site
+from .models import Term
+try:
+ from reversion import VersionAdmin as ModelAdmin
+except ImportError:
+ from django.contrib.admin import ModelAdmin
+
+
+class TermAdmin(ModelAdmin):
+ model = Term
+
+
+site.register(Term, TermAdmin)
View
@@ -0,0 +1,14 @@
+from cms.app_base import CMSApp
+from cms.apphook_pool import apphook_pool
+from .menu import TermMenu
+from django.utils.translation import ugettext_lazy as _
+
+
+class TermApp(CMSApp):
+ name = _('Term')
+ urls = ['terms.urls']
+ menus = [TermMenu]
+
+
+apphook_pool.register(TermApp)
+
View
@@ -0,0 +1,18 @@
+# coding: utf-8
+
+from django.db.models import Manager
+from django.template.loader import render_to_string
+import re
+
+
+class TermManager(Manager):
+ def replace_dict(self):
+ t = 'terms/term_replace.html'
+ d = {}
+ for term in self.get_query_set().iterator():
+ d[term.name] = render_to_string(t, {'term': term})
+ return d
+
+ def replace_regexp(self):
+ replace_dict = self.replace_dict()
+ return re.compile('|'.join(map(re.escape, replace_dict)))
View
@@ -0,0 +1,30 @@
+from cms.menu_bases import CMSAttachMenu
+from menus.base import Menu, NavigationNode
+from menus.menu_pool import menu_pool
+from django.core.urlresolvers import reverse, NoReverseMatch
+from .models import Term
+from django.utils.translation import ugettext_lazy as _
+
+
+class TermMenu(CMSAttachMenu):
+ name = _('Term Menu')
+
+ def get_nodes(self, request):
+ '''
+ This method is used to build the menu tree.
+ '''
+ nodes = []
+ for term in Term.objects.iterator():
+ try:
+ node = NavigationNode(
+ unicode(term),
+ term.get_absolute_url(),
+ term.pk,
+ )
+ nodes.append(node)
+ except NoReverseMatch:
+ pass
+ return nodes
+
+
+menu_pool.register_menu(TermMenu)
View
@@ -0,0 +1,36 @@
+# coding: utf-8
+
+from .utils import NeutralHTMLReconstructor
+from .models import Term
+
+
+class TermsHTMLReconstructor(NeutralHTMLReconstructor):
+ def reset(self):
+ NeutralHTMLReconstructor.reset(self)
+ self.replace_dict = Term.objects.replace_dict()
+ self.replace_regexp = Term.objects.replace_regexp()
+
+ def replace(self, text):
+ def translate(match):
+ try:
+ return self.replace_dict[match.group(0)]
+ except KeyError:
+ pass
+
+ return self.replace_regexp.sub(translate, text)
+
+ def handle_data(self, data):
+ data = self.replace(data)
+ self.out.append(data)
+
+
+class TermsMiddleware:
+ def __init__(self):
+ self.parser = TermsHTMLReconstructor()
+
+ def process_response(self, request, response):
+ if 'text/html' in response['Content-Type']:
+ self.parser.feed(response.content.decode('utf-8'))
+ response.content = ''.join(self.parser.out)
+ self.parser.reset()
+ return response
View
@@ -0,0 +1,21 @@
+# coding: utf-8
+
+from django.db.models import Model, CharField, TextField, URLField
+from django.utils.translation import ugettext_lazy as _
+from .managers import TermManager
+from django.core.urlresolvers import reverse
+
+
+class Term(Model):
+ name = CharField(_('name'), max_length=100)
+ description = TextField(_('description'), blank=True)
+ url = URLField(_("link"), verify_exists=False, blank=True, null=True)
+ objects = TermManager()
+
+ def __unicode__(self):
+ return self.name
+
+ def get_absolute_url(self):
+ if self.url:
+ return self.url
+ return reverse('term', kwargs={'pk': self.pk})
@@ -0,0 +1,2 @@
+<h2>{{ term }}</h2>
+<p>{{ term.description }}</p>
@@ -0,0 +1 @@
+<a href="{{ term.get_absolute_url }}">{{ term.name }}</a>
View
@@ -0,0 +1,7 @@
+from django.conf.urls.defaults import patterns, url
+from .views import TermDetail
+
+urlpatterns = patterns('',
+ url(r'^(?P<pk>\d+)/$', TermDetail.as_view(), name='term'),
+)
+
View
@@ -0,0 +1,44 @@
+# coding: utf-8
+
+from HTMLParser import HTMLParser
+
+
+class NeutralHTMLReconstructor(HTMLParser):
+ def reset(self):
+ HTMLParser.reset(self)
+ self.out = []
+
+ def concat_attrs(self, attrs):
+ return ''.join(' %s="%s"' % (attr[0], attr[1]) for attr in attrs)
+
+ def handle_startendtag(self, tag, attrs):
+ attrs = self.concat_attrs(attrs)
+ self.out.append('<%s%s />' % (tag, attrs))
+
+ def handle_starttag(self, tag, attrs):
+ attrs = self.concat_attrs(attrs)
+ self.out.append('<%s%s>' % (tag, attrs))
+
+ def handle_endtag(self, tag):
+ self.out.append('</%s>' % tag)
+
+ def handle_charref(self, name):
+ self.out.append('&#%s;' % name)
+
+ def handle_entityref(self, name):
+ self.out.append('&%s;' % name)
+
+ def handle_data(self, data):
+ self.out.append(data)
+
+ def handle_comment(self, data):
+ self.out.append('<!--%s-->' % data)
+
+ def handle_decl(self, decl):
+ self.out.append('<!%s>' % decl)
+
+ def handle_pi(self, data):
+ self.out.append('<?%s>' % data)
+
+ def unknown_decl(self, data):
+ self.out.append('<![%s]>' % decl)
View
@@ -0,0 +1,7 @@
+from django.views.generic import DetailView
+from .models import Term
+
+
+class TermDetail(DetailView):
+ model = Term
+ context_object_name = 'term'

0 comments on commit aad12a6

Please sign in to comment.