Skip to content

Commit

Permalink
add themes; renamed 'term' template tag to 'term_tag'; add 'load_term…
Browse files Browse the repository at this point in the history
…s' template tag; add configurable text field; add django-modeltranslation integration
  • Loading branch information
joke2k committed Jun 21, 2014
1 parent 85652ea commit dccb33f
Show file tree
Hide file tree
Showing 15 changed files with 259 additions and 48 deletions.
2 changes: 1 addition & 1 deletion HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
History
-------

0.1.0 (2014-01-01)
0.1.0 (2014-06-??)
++++++++++++++++++

* First release on PyPI.
44 changes: 27 additions & 17 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@ Quickstart

Install django-idioticon::

pip install idioticon
pip install django-idioticon

Add ``idioticon`` to ``settings.INSTALLED_APPS``, then use it in a project::

Add ``idioticon`` to ``settings.INSTALLED_APPS`` and execute `syncdb` to create Term table::

>>> import idioticon
>>> idioticon.get_term(key='not-existing-term', soft_error=True)
Expand All @@ -48,21 +49,7 @@ Add ``idioticon`` to ``settings.INSTALLED_APPS``, then use it in a project::

>>> alias = idioticon.add_alias('my-term', 'my-alias', 'My alias', 'description')
>>> alias.main_term == idioticon.get_term('my-term')

Template tags
-------------
::

{% load idioticon %}
{% term 'my-term' %}

<script>
$(document).ready(function(){
// activate popover
$('a[rel=info-popover]').popover();
});
</script>

True

Features
--------
Expand All @@ -71,3 +58,26 @@ Features
* Idioticon administration
* Shortcuts ( get_term, )
* Tests for Django >= 1.5 and Python >= 2.6
* django-modeltranslation integration for multi language site
* Configurable definition field


Settings
--------

Option | Description
-------|------------
IDIOTICON_THEME = 'span' | {% term_tag .. %} loads idioticon/term_THEME.html
IDIOTICON_TEXT_FIELD = '' | Override the default TextField with your custom one.

Template tags
-------------
::

{% load idioticon %}
{% term_tag 'my-term' %}

{% load_terms 'my-term' as term %}
{{ term.get_name %}
{{ term.get_definition %}

37 changes: 33 additions & 4 deletions docs/usage.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,36 @@
========
=====
Usage
========
=====

To use django-idioticon in a project::
Using bootstrap (with pophover plugin) we can build a tooltip system.

First create a template for terms in `idioticon/term_pophover.html`::

<a href="#" rel="info-popover" data-toggle="popover"
title="{{ term.get_name|safe|force_escape }}"
data-content="{{ term.get_definition|safe|force_escape }}"
data-html="true"
data-width="300px"
data-container="body"
data-placement="auto">{{ term.get_name }}</a>

Then in your templates::

<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">

...

{% load idioticon %}
{% term_tag 'my-term' theme='pophover' %}

...

<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.js"></script>
<script src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
<script>
$(document).ready(function(){
// activate popover
$('a[rel=info-popover]').popover();
});
</script>

import idioticon
8 changes: 8 additions & 0 deletions idioticon/conf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from django.conf import settings

TEXT_FIELD = getattr(settings, 'IDIOTICON_TEXT_FIELD', '')
THEME = getattr(settings, 'IDIOTICON_THEME', 'span')

setattr(settings, 'IDIOTICON_TEXT_FIELD', TEXT_FIELD)
setattr(settings, 'IDIOTICON_THEME', THEME)

79 changes: 79 additions & 0 deletions idioticon/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import sys
from xml.etree.ElementTree import Element
from django.core.exceptions import ImproperlyConfigured


PY3 = sys.version_info[0] == 3

if PY3:
string_types = str,
unicode = str
else:
string_types = basestring,

# Setup default configurations
IDIOTICON_DEFAULTS = {
'TEXT_FIELD': 'django.db.models.TextField',
'KEY_LENGTH': 255,
'TITLE_LENGTH': 255,
'CACHE': 'default',
'CACHE_KEY_PREFIX': 'term-',
'THEME': 'plain',
'CONTEXT_LOADER': '',
}

class Theme(object):

icon = None
symbol = ''
wrapper = 'span'

def render(self, symbol=None, wrapper=None, icon=None):
wrapper = self.wrapper if wrapper is None else wrapper
if isinstance(wrapper, string_types):
wrapper = Element(wrapper)
symbol = self.symbol if symbol is None else symbol
if symbol:
wrapper.text = symbol
icon = self.icon if icon is None else icon
if icon:
wrapper.append(icon)
return unicode(wrapper)


# plain theme configuration (default)
IDIOTICON_PLAIN = {
'ICON_TAG': 'abbr',
'ICON_CLASS': '',
'SYMBOL': '*',
}

# bootstrap theme configuration
IDIOTICON_BOOTSTRAP = {
'ICON_TAG': 'span',
'ICON_CLASS': 'fa fa-fw fa-question-circle',
'SYMBOL': '',
}

# all themes
THEMES = {
'plain': IDIOTICON_PLAIN,
'bootstrap': IDIOTICON_BOOTSTRAP,
}

def get_config(values):

config = IDIOTICON_DEFAULTS.copy()

# Merge defaults with settings
config.update(values)

# Check the theme
try:
theme = values['THEME']
config['THEME'] = THEMES[values['THEME']].copy()
config['THEME']['NAME'] = theme
except KeyError:
raise ImproperlyConfigured("The IDIOTICON theme is not valid: %s" % values['THEME'])

return config
18 changes: 14 additions & 4 deletions idioticon/models.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,27 @@
# -*- coding: utf-8 -*-
from django.db import models
from django.utils.translation import ugettext_lazy as _
from idioticon.conf import settings

try:
# Deprecated in Django 1.7
from django.utils.module_loading import import_by_path as import_string

except ImportError:
# For Django 1.7
from django.utils.module_loading import import_string

# Definition Field type
TermDefinitionField = import_string(settings.IDIOTICON_TEXT_FIELD) if settings.IDIOTICON_TEXT_FIELD else models.TextField

class TermManager(models.Manager):

def get_term(self, key, soft_error=False):
"""This method tries to return a term by key.
Can raise Term.DoesNotExist if soft_error is False (as in default).
:param key: term
:type key: str
:param resolve_alias: default True
:type resolve_alias: bool
:returns: then matching Term
:rtype Term:
:raises Term.DoesNotExist
Expand Down Expand Up @@ -46,8 +54,9 @@ def add_alias(self, term, alias, name='', definition=''):
:returns: a Term alias
:rtype: Term
"""
term = self.get_term(term)
if not isinstance(alias, Term):
return Term.objects.create(
return self.get_queryset().create(
key=alias,
name=name,
definition=definition,
Expand All @@ -56,6 +65,7 @@ def add_alias(self, term, alias, name='', definition=''):
alias.save()
return alias


class Term(models.Model):
"""
An idioticon is a glossary.
Expand All @@ -68,7 +78,7 @@ class Term(models.Model):
key = models.SlugField(max_length=255, unique=True,
help_text=_("A single word, to use as key in popovers' inclusion tags"))
name = models.CharField(_("Term"), blank=True, max_length=255, help_text=_("The term"))
definition = models.TextField(_("Definition"), blank=True, help_text=_("The definition of the term"))
definition = TermDefinitionField(_("Definition"), blank=True, help_text=_("The definition of the term"))

main_term = models.ForeignKey('self', null=True, blank=True, related_name='aliases',
help_text=_("Main definition"))
Expand Down
1 change: 1 addition & 0 deletions idioticon/templates/idioticon/term_abbr.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<abbr title="{{ term.get_definition }}">{{ term.get_name }}</abbr>
1 change: 1 addition & 0 deletions idioticon/templates/idioticon/term_dt.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<dt>{{ term.get_name }}</dt><dd>{{ term.get_definition }}</dd>
7 changes: 0 additions & 7 deletions idioticon/templates/idioticon/term_icon.html

This file was deleted.

1 change: 1 addition & 0 deletions idioticon/templates/idioticon/term_span.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<span title="{{ term.get_definition }}">{{ term.get_name }}</span>
63 changes: 55 additions & 8 deletions idioticon/templatetags/idioticon.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,64 @@
from __future__ import absolute_import
from django import template
from idioticon import log
from django.conf import settings
from django.template import (Node, TemplateSyntaxError, Context)
from django.template.loader import get_template
from idioticon import shortcuts


register = template.Library()

@register.inclusion_tag('idioticon/term_icon.html')
def term(term_key, **kwargs):
class LoadTermsNode(Node):
def __init__(self, variables, terms):
self.variables = variables
self.terms = terms

def render(self, context):
for variable, term in zip(self.variables, self.terms):
context[variable] = shortcuts.get_term(term)
return ''


@register.simple_tag(name="term_tag")
def do_term_tag(term_key, **kwargs):

# get the term context
context = {}
theme = kwargs.pop('theme', settings.IDIOTICON_THEME)

context = Context()
context.update(kwargs)
context['term'] = shortcuts.get_term(term_key)
log.info('TAG for term: %s' % context['term'])

return context
try:
context['term'] = shortcuts.get_term(term_key)
template_name = 'idioticon/term_%s.html' % theme
template = get_template(template_name)
return template.render(context)
except:
if settings.TEMPLATE_DEBUG:
raise
return ''


@register.tag("load_terms")
def do_load_terms(parser, token):
"""
This will store a list of terms in the context.
Usage::
{% load_terms 'my-term' 'other-term' as my_term other_term %}
{{ my_term.get_title }}: {{ my_term.get_definition }}
"""
# token.split_contents() isn't useful here because this tag doesn't accept variable as arguments
args = token.contents.split()

try:
as_index = args.index('as')
except ValueError:
raise TemplateSyntaxError("'load_terms' requires '*terms as *variable' (got %r)" % args)

names, terms = args[as_index+1:], args[1:as_index]

if len(names) != len(terms):
raise TemplateSyntaxError("'load_terms' requires '*terms as *variable' (got %r)" % args)
return LoadTermsNode(names, terms)
7 changes: 7 additions & 0 deletions idioticon/translation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from modeltranslation.translator import translator, TranslationOptions
from idioticon.models import Term

class TermTranslationOptions(TranslationOptions):
fields = ('name', 'definition',)

translator.register(Term, TermTranslationOptions)
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
'Development Status :: 2 - Pre-Alpha',
'Framework :: Django',
'Intended Audience :: Developers',
'License :: OSI Approved :: BSD License',
'License :: OSI Approved :: MIT License'
'Natural Language :: English',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.6',
Expand Down
Loading

0 comments on commit dccb33f

Please sign in to comment.