Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

initial buggy commit

  • Loading branch information...
commit a9afcddc6fd4b52a49db086a41aa33d4ac175604 0 parents
Julian authored
1  CHANGES.txt
@@ -0,0 +1 @@
+v0.1, 2010-07-09 - Initial release with README, for tags and tests.
119 README.rst
@@ -0,0 +1,119 @@
+============
+Instructions
+============
+
+This is a reusable django app which adds some templatetags to django-taggit_.
+
+Installation
+============
+
+Just install ``django-taggit-templatetags`` via ``pip``::
+
+ $ pip install django-taggit-templatetags
+
+After installing and configuring django-taggit_, just add ``taggit_templatetags`` to your INSTALLED_APPS in your ``settings.py``::
+
+ INSTALLED_APPS = (
+ ...
+ 'taggit_templatetags',
+ ...
+ )
+
+Usage
+=====
+
+Now there are some templatetags enabled. At the moment mainly to create lists of tags and tag-clouds.
+
+In your templates, you need to load ``taggit_extras``::
+
+ ...
+ {% load taggit_extras %}
+ ...
+
+--------
+Taglists
+--------
+
+After loading ``taggit_extras`` you can create a list of tags for the whole project (in the sense of djangoproject), for an app (in the sense of djangoapp), for a model-class (to get a list for an instance of a model, just use its tag-field).
+
+For the tags of a project, just do::
+
+ {% get_taglist as tags %}
+
+For the tags of an app, just do::
+
+ {% get_taglist as tags for 'yourapp' %}
+
+For the tags of an model, just do::
+
+ {% get_taglist as tags for 'yourapp.yourmodel' %}
+
+No matter what you do, you have a list of tags in the ``tags`` template variable. You can now iterate over it::
+
+ <ul>
+ {% for tag in tags %}
+ <li>{{tag}} ({{tag.num_times}})</li>
+ {% endfor %}
+ <ul>
+
+As you can see, each tag has an attribute ``num_times`` which declares how many times it was used. The list of tags is sorted descending by ``num_times``.
+
+Inclusion-Tag
+-------------
+
+For convenience, there's a inclusion-tag. It's used analogue. For example, for a taglist of a model, just do::
+
+ {% include_taglist 'yourapp.yourmodel' %}
+
+---------
+Tagclouds
+---------
+
+A very popular way to navigate through tags is a tagcloud_. This app provides some tags for that::
+
+ {% get_tagcloud as tags %}
+
+or::
+
+ {% get_tagcloud as tags for 'yourapp' %}
+
+or::
+
+ {% get_tagcloud as tags for 'yourapp.yourmodel' %}
+
+respectivly. The resulting list of tags is ordered by their ``name`` attribute. Besides the ``num_items`` attribute, there's a ``weight`` attribute. Its maximum and minimum may be specified as the settings_ section reads.
+
+Inclusion-Tag
+-------------
+
+Even for the tagcloud there's an inclusion-tag. For example, for a tagcloud of a model, just do::
+
+{% include_tagcloud 'yourapp.yourmodel' %}
+
+.. _settings:
+
+Settings
+========
+
+There are a few settings to be set:
+
+TAGGIT_TAGCLOUD_MIN (default: 1.0)
+ This specifies the minimum of the weight attribute of a tagcloud's tags.
+
+TAGGIT_TAGCLOUD_MAX (default: 6.0)
+ This specifies the maximum of the weight attribute of a tagcloud's tags.
+
+If you want to use the weight as font-sizes, you can it do as follows::
+
+ <font size={{tag.weight|floatformat:0}}>{{tag}}</font>
+
+So the weights are converted to integer values.
+
+Thanks
+======
+
+Thanks to the python- and django-community, in particular to `Alex Gaynor`_, the inventor of django-taggit_ and a wonderful guy to argue with.
+
+.. _django-taggit: http://github.com/alex/django-taggit
+.. _tagcloud: http://www.wikipedia.org/wiki/Tagcloud
+.. _Alex Gaynor: http://alexgaynor.net/
11 django_taggit_templatetags.egg-info/PKG-INFO
@@ -0,0 +1,11 @@
+Metadata-Version: 1.0
+Name: django-taggit-templatetags
+Version: 0.1dev
+Summary: Templatetags for django-taggit.
+Home-page: UNKNOWN
+Author: Julian Moritz
+Author-email: jumo@gmx.de
+License: BSD
+Description: ...
+Keywords: django taggit tags tagcloud taglist
+Platform: UNKNOWN
9 django_taggit_templatetags.egg-info/SOURCES.txt
@@ -0,0 +1,9 @@
+setup.cfg
+setup.py
+django_taggit_templatetags.egg-info/PKG-INFO
+django_taggit_templatetags.egg-info/SOURCES.txt
+django_taggit_templatetags.egg-info/dependency_links.txt
+django_taggit_templatetags.egg-info/entry_points.txt
+django_taggit_templatetags.egg-info/not-zip-safe
+django_taggit_templatetags.egg-info/top_level.txt
+djangotaggittemplatetags/__init__.py
1  django_taggit_templatetags.egg-info/dependency_links.txt
@@ -0,0 +1 @@
+
3  django_taggit_templatetags.egg-info/entry_points.txt
@@ -0,0 +1,3 @@
+
+ # -*- Entry points: -*-
+
1  django_taggit_templatetags.egg-info/not-zip-safe
@@ -0,0 +1 @@
+
1  django_taggit_templatetags.egg-info/top_level.txt
@@ -0,0 +1 @@
+djangotaggittemplatetags
3  setup.cfg
@@ -0,0 +1,3 @@
+[egg_info]
+tag_build = dev
+tag_svn_revision = true
35 setup.py
@@ -0,0 +1,35 @@
+from setuptools import setup, find_packages
+import sys, os
+
+from taggit_templatetags import VERSION
+
+setup(name='django-taggit-templatetags',
+ version=".".join(map(str, VERSION)),
+ description="Templatetags for django-taggit.",
+ long_description=open("README.rst", "r").read(),
+ classifiers=[
+ 'Development Status :: 3 - Alpha',
+ 'Environment :: Web Environment',
+ 'Intended Audience :: Developers',
+ 'License :: OSI Approved :: BSD License',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python',
+ 'Framework :: Django',
+ ], # Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers
+ keywords='django taggit tags tagcloud taglist',
+ author='Julian Moritz',
+ author_email='jumo@gmx.de',
+ url='http://github.com/feuervogel/django-taggit-templatetags',
+ license='BSD',
+ packages=find_packages(exclude=['ez_setup', 'examples', 'tests']),
+ include_package_data=True,
+ zip_safe=False,
+ install_requires=[
+ 'django>=1.1',
+ 'django-taggit>=0.8',
+ 'django-templatetag-sugar=>0.1'
+ ],
+ entry_points="""
+ # -*- Entry points: -*-
+ """,
+ )
2  taggit_templatetags/__init__.py
@@ -0,0 +1,2 @@
+#
+VERSION = (0, 1, 0)
7 taggit_templatetags/settings.py
@@ -0,0 +1,7 @@
+from django.conf import settings
+
+# define the minimal weight of a tag in the tagcloud
+TAGCLOUD_MIN = getattr(settings, 'TAGGIT_TAGCLOUD_MIN', 1.0)
+
+# define the maximum weight of a tag in the tagcloud
+TAGCLOUD_MAX = getattr(settings, 'TAGGIT_TAGCLOUD_MAX', 6.0)
7 taggit_templatetags/templates/taggit_templatetags/tagcloud_include.html
@@ -0,0 +1,7 @@
+{% load taggit_extras %}
+{% get_tagcloud as tags for forvar %}
+<div>
+{% for tag in tags %}
+<font size={{tag.weight|floatformat:0}}>{{tag}}</font>
+{% endfor %}
+</div>
7 taggit_templatetags/templates/taggit_templatetags/taglist_include.html
@@ -0,0 +1,7 @@
+{% load taggit_extras %}
+{% get_taglist as tags for forvar %}
+<ul>
+{% for tag in tags %}
+<li>{{tag}}</li>
+{% endfor %}
+</ul>
0  taggit_templatetags/templatetags/__init__.py
No changes.
69 taggit_templatetags/templatetags/taggit_extras.py
@@ -0,0 +1,69 @@
+from django import template
+from django.db import models
+from django.db.models import Count
+
+from templatetag_sugar.register import tag
+from templatetag_sugar.parser import Name, Variable, Constant, Optional, Model
+
+from taggit.managers import TaggableManager
+from taggit.models import TaggedItem, Tag
+from taggit import settings
+
+T_MAX = getattr(settings, 'TAGCLOUD_MAX', 6.0)
+T_MIN = getattr(settings, 'TAGCLOUD_MIN', 1.0)
+
+register = template.Library()
+
+def get_queryset(forvar=None):
+ if None == forvar:
+ # get all tags
+ queryset = Tag.objects.all()
+ else:
+ # extract app label and model name
+ beginning, applabel, model = None, None, None
+ try:
+ beginning, applabel, model = forvar.rsplit('.', 2)
+ except ValueError:
+ try:
+ applabel, model = forvar.rsplit('.', 1)
+ except ValueError:
+ applabel = forvar
+
+ # filter tagged items
+ if applabel:
+ queryset = TaggedItem.objects.filter(content_type__app_label=applabel)
+ if model:
+ queryset = queryset.filter(content_type__model=model)
+
+ # get tags
+ tag_ids = queryset.values_list('tag_id', flat=True)
+ queryset = Tag.objects.filter(id__in=tag_ids)
+ return queryset.annotate(num_times=Count('taggit_taggeditem_items'))
+
+def get_weight_fun(t_min, t_max, f_min, f_max):
+ def weight_fun(t_i, t_min=t_min, t_max=t_max, f_min=f_min, f_max=f_max):
+ return f_max * ((t_i-t_min)/(t_max-t_min))
+ return weight_fun
+
+@tag(register, [Constant('as'), Name(), Optional([Constant('for'), Variable()])])
+def get_taglist(context, asvar, forvar=None):
+ queryset = get_queryset(forvar)
+ queryset = queryset.order_by('-num_times')
+ context[asvar] = queryset
+ return ''
+
+@tag(register, [Constant('as'), Name(), Optional([Constant('for'), Variable()])])
+def get_tagcloud(context, asvar, forvar=None):
+ queryset = get_queryset(forvar)
+ num_times = queryset.values_list('num_times', flat=True)
+ weight_fun = get_weight_fun(T_MIN, T_MAX, min(num_times), max(num_times))
+ for tag in queryset:
+ tag.weight = weight_fun(tag.num_times)
+ context[asvar] = queryset.order_by('name')
+ return ''
+
+def tag_include(forvar):
+ return {'forvar': forvar}
+
+register.inclusion_tag('taggit_templatetags/taglist_include.html')(tag_include)
+register.inclusion_tag('taggit_templatetags/tagcloud_include.html')(tag_include)
1  taggit_templatetags/tests/__init__.py
@@ -0,0 +1 @@
+from taggit_templatetags.tests.tests import TemplateTagListTestCase, TemplateTagCloudTestCase
19 taggit_templatetags/tests/models.py
@@ -0,0 +1,19 @@
+from django.db import models
+
+from taggit.managers import TaggableManager
+
+class BaseModel(models.Model):
+ name = models.CharField(max_length=50, unique=True)
+ tags = TaggableManager()
+
+ def __unicode__(self):
+ return self.name
+
+ class Meta(object):
+ abstract = True
+
+class AlphaModel(BaseModel):
+ pass
+
+class BetaModel(BaseModel):
+ pass
265 taggit_templatetags/tests/tests.py
@@ -0,0 +1,265 @@
+from django.test import TestCase
+from django.template import Context, Template
+
+from taggit_templatetags.tests.models import AlphaModel, BetaModel
+from taggit.tests.tests import BaseTaggingTest
+
+class TemplateTagListTestCase(BaseTaggingTest):
+ a_model = AlphaModel
+ b_model = BetaModel
+
+ def setUp(self):
+ a1 = self.a_model.objects.create(name="apple")
+ a2 = self.a_model.objects.create(name="pear")
+ b1 = self.b_model.objects.create(name="dog")
+ b2 = self.b_model.objects.create(name="kitty")
+
+ a1.tags.add("green")
+ a1.tags.add("sweet")
+ a1.tags.add("fresh")
+
+ a2.tags.add("yellow")
+ a2.tags.add("sour")
+
+ b1.tags.add("sweet")
+ b1.tags.add("yellow")
+
+ b2.tags.add("sweet")
+ b2.tags.add("green")
+
+ def get_template(self, argument):
+ return """ {%% load taggit_extras %%}
+ {%% get_taglist %s %%}
+ """ % argument
+
+ def test_project(self):
+ t = Template(self.get_template("as taglist"))
+ c = Context({})
+ t.render(c)
+ self.assert_tags_equal(c.get("taglist"), ["sweet", "green", "yellow", "fresh", "sour"], False)
+
+ def test_app(self):
+ t = Template(self.get_template("as taglist for 'tests'"))
+ c = Context({})
+ t.render(c)
+ self.assert_tags_equal(c.get("taglist"), ["sweet", "green", "yellow", "fresh", "sour"], False)
+
+ def test_model(self):
+ t = Template(self.get_template("as taglist for 'tests.pet'"))
+ c = Context({})
+ t.render(c)
+ self.assert_tags_equal(c.get("taglist"), ["sweet", "green", "yellow"], False)
+
+class TemplateTagCloudTestCase(BaseTaggingTest):
+ a_model = AlphaModel
+ b_model = BetaModel
+
+ def setUp(self):
+ a1 = self.a_model.objects.create(name="apple")
+ a2 = self.a_model.objects.create(name="pear")
+ b1 = self.b_model.objects.create(name="dog")
+ b2 = self.b_model.objects.create(name="kitty")
+
+ a1.tags.add("green")
+ a1.tags.add("sweet")
+ a1.tags.add("fresh")
+
+ a2.tags.add("yellow")
+ a2.tags.add("sour")
+
+ b1.tags.add("sweet")
+ b1.tags.add("yellow")
+
+ b2.tags.add("sweet")
+ b2.tags.add("green")
+
+ def get_template(self, argument):
+ return """ {%% load taggit_extras %%}
+ {%% get_tagcloud %s %%}
+ """ % argument
+
+ def test_project(self):
+ t = Template(self.get_template("as taglist"))
+ c = Context({})
+ t.render(c)
+ self.assert_tags_equal(c.get("taglist"), ["fresh", "green", "sour", "sweet", "yellow"], False)
+ self.assert_equal(c.get("taglist")[3].name, "sweet")
+ self.assert_equal(c.get("taglist")[3].weight, 6.0)
+ self.assert_equal(c.get("taglist")[1].name, "green")
+ self.assert_equal(c.get("taglist")[1].weight, 5.0)
+ self.assert_equal(c.get("taglist")[2].name, "sour")
+ self.assert_equal(c.get("taglist")[2].weight, 1.0)
+
+ def test_app(self):
+ t = Template(self.get_template("as taglist for 'tests'"))
+ c = Context({})
+ t.render(c)
+ self.assert_tags_equal(c.get("taglist"), ["fresh", "green", "sour", "sweet", "yellow"], False)
+ self.assert_equal(c.get("taglist")[3].name, "sweet")
+ self.assert_equal(c.get("taglist")[3].weight, 6.0)
+ self.assert_equal(c.get("taglist")[1].name, "green")
+ self.assert_equal(c.get("taglist")[1].weight, 5.0)
+ self.assert_equal(c.get("taglist")[2].name, "sour")
+ self.assert_equal(c.get("taglist")[2].weight, 1.0)
+
+
+ def test_model(self):
+ t = Template(self.get_template("as taglist for 'tests.pet'"))
+ c = Context({})
+ t.render(c)
+ self.assert_tags_equal(c.get("taglist"), ["green", "sweet", "yellow"], False)
+ self.assert_equal(c.get("taglist")[0].name, "green")
+ self.assert_equal(c.get("taglist")[0].weight, 6.0)
+ self.assert_equal(c.get("taglist")[1].name, "sweet")
+ self.assert_equal(c.get("taglist")[1].weight, 2.5)
+ self.assert_equal(c.get("taglist")[2].name, "yellow")
+ self.assert_equal(c.get("taglist")[2].weight, 1.0)
+
+
+class TaggableManagerTestCase(BaseTaggingTest):
+ food_model = Food
+ pet_model = Pet
+ housepet_model = HousePet
+
+ def test_add_tag(self):
+ apple = self.food_model.objects.create(name="apple")
+ self.assertEqual(list(apple.tags.all()), [])
+ self.assertEqual(list(self.food_model.tags.all()), [])
+
+ apple.tags.add('green')
+ self.assert_tags_equal(apple.tags.all(), ['green'])
+ self.assert_tags_equal(self.food_model.tags.all(), ['green'])
+
+ pear = self.food_model.objects.create(name="pear")
+ pear.tags.add('green')
+ self.assert_tags_equal(pear.tags.all(), ['green'])
+ self.assert_tags_equal(self.food_model.tags.all(), ['green'])
+
+ apple.tags.add('red')
+ self.assert_tags_equal(apple.tags.all(), ['green', 'red'])
+ self.assert_tags_equal(self.food_model.tags.all(), ['green', 'red'])
+
+ self.assert_tags_equal(
+ self.food_model.tags.most_common(),
+ ['green', 'red'],
+ sort=False
+ )
+
+ apple.tags.remove('green')
+ self.assert_tags_equal(apple.tags.all(), ['red'])
+ self.assert_tags_equal(self.food_model.tags.all(), ['green', 'red'])
+ tag = Tag.objects.create(name="delicious")
+ apple.tags.add(tag)
+ self.assert_tags_equal(apple.tags.all(), ["red", "delicious"])
+
+ apple.delete()
+ self.assert_tags_equal(self.food_model.tags.all(), ["green"])
+
+ f = self.food_model()
+ with self.assert_raises(ValueError):
+ f.tags.all()
+
+ def test_unique_slug(self):
+ apple = self.food_model.objects.create(name="apple")
+ apple.tags.add("Red", "red")
+
+ def test_delete_obj(self):
+ apple = self.food_model.objects.create(name="apple")
+ apple.tags.add("red")
+ self.assert_tags_equal(apple.tags.all(), ["red"])
+ strawberry = self.food_model.objects.create(name="strawberry")
+ strawberry.tags.add("red")
+ apple.delete()
+ self.assert_tags_equal(strawberry.tags.all(), ["red"])
+
+ def test_lookup_by_tag(self):
+ apple = self.food_model.objects.create(name="apple")
+ apple.tags.add("red", "green")
+ pear = self.food_model.objects.create(name="pear")
+ pear.tags.add("green")
+
+ self.assertEqual(
+ list(self.food_model.objects.filter(tags__in=["red"])),
+ [apple]
+ )
+ self.assertEqual(
+ list(self.food_model.objects.filter(tags__in=["green"])),
+ [apple, pear]
+ )
+
+ kitty = self.pet_model.objects.create(name="kitty")
+ kitty.tags.add("fuzzy", "red")
+ dog = self.pet_model.objects.create(name="dog")
+ dog.tags.add("woof", "red")
+ self.assertEqual(
+ list(self.food_model.objects.filter(tags__in=["red"]).distinct()),
+ [apple]
+ )
+
+ tag = Tag.objects.get(name="woof")
+ self.assertEqual(list(self.pet_model.objects.filter(tags__in=[tag])), [dog])
+
+ cat = self.housepet_model.objects.create(name="cat", trained=True)
+ cat.tags.add("fuzzy")
+
+ self.assertEqual(
+ map(lambda o: o.pk, self.pet_model.objects.filter(tags__in=["fuzzy"])),
+ [kitty.pk, cat.pk]
+ )
+
+ def test_similarity_by_tag(self):
+ """Test that pears are more similar to apples than watermelons"""
+ apple = self.food_model.objects.create(name="apple")
+ apple.tags.add("green", "juicy", "small", "sour")
+
+ pear = self.food_model.objects.create(name="pear")
+ pear.tags.add("green", "juicy", "small", "sweet")
+
+ watermelon = self.food_model.objects.create(name="watermelon")
+ watermelon.tags.add("green", "juicy", "large", "sweet")
+
+ similar_objs = apple.tags.similar_objects()
+ self.assertEqual(similar_objs, [pear, watermelon])
+ self.assertEqual(map(lambda x: x.similar_tags, similar_objs), [3, 2])
+
+ def test_tag_reuse(self):
+ apple = self.food_model.objects.create(name="apple")
+ apple.tags.add("juicy", "juicy")
+ self.assert_tags_equal(apple.tags.all(), ['juicy'])
+
+
+class TaggableManagerDirectTestCase(TaggableManagerTestCase):
+ food_model = DirectFood
+ pet_model = DirectPet
+ housepet_model = DirectHousePet
+
+
+class TaggableFormTestCase(BaseTaggingTest):
+ form_class = FoodForm
+ food_model = Food
+
+ def test_form(self):
+ self.assertEqual(self.form_class.base_fields.keys(), ['name', 'tags'])
+
+ f = self.form_class({'name': 'apple', 'tags': 'green, red, yummy'})
+ self.assertEqual(str(f), """<tr><th><label for="id_name">Name:</label></th><td><input id="id_name" type="text" name="name" value="apple" maxlength="50" /></td></tr>\n<tr><th><label for="id_tags">Tags:</label></th><td><input type="text" name="tags" value="green, red, yummy" id="id_tags" /></td></tr>""")
+ f.save()
+ apple = self.food_model.objects.get(name='apple')
+ self.assert_tags_equal(apple.tags.all(), ['green', 'red', 'yummy'])
+
+ f = self.form_class({'name': 'apple', 'tags': 'green, red, yummy, delicious'}, instance=apple)
+ f.save()
+ apple = self.food_model.objects.get(name='apple')
+ self.assert_tags_equal(apple.tags.all(), ['green', 'red', 'yummy', 'delicious'])
+ self.assertEqual(self.food_model.objects.count(), 1)
+
+ f = self.form_class({"name": "raspberry"})
+ raspberry = f.save()
+ self.assert_tags_equal(raspberry.tags.all(), [])
+
+ f = self.form_class(instance=apple)
+ self.assertEqual(str(f), """<tr><th><label for="id_name">Name:</label></th><td><input id="id_name" type="text" name="name" value="apple" maxlength="50" /></td></tr>\n<tr><th><label for="id_tags">Tags:</label></th><td><input type="text" name="tags" value="green, red, yummy, delicious" id="id_tags" /></td></tr>""")
+
+class TaggableFormDirectTestCase(TaggableFormTestCase):
+ form_class = DirectFoodForm
+ food_model = DirectFood
Please sign in to comment.
Something went wrong with that request. Please try again.