aboutsummaryrefslogtreecommitdiff
path: root/tagging/templatetags/tagging_tags.py
blob: fb4347ff7d306130b92e6ef25056232f2081463c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
from django.db.models import get_model
from django.template import Library, Node, TemplateSyntaxError, resolve_variable
from tagging.models import Tag, TaggedItem

register = Library()

class TagsForModelNode(Node):
    def __init__(self, model, context_var, counts):
        self.model = model
        self.context_var = context_var
        self.counts = counts

    def render(self, context):
        model = get_model(*self.model.split('.'))
        context[self.context_var] = Tag.objects.usage_for_model(model, counts=self.counts)
        return ''

class TagsForObjectNode(Node):
    def __init__(self, obj, context_var):
        self.obj = obj
        self.context_var = context_var

    def render(self, context):
        obj = resolve_variable(self.obj, context)
        context[self.context_var] = Tag.objects.get_for_object(obj)
        return ''

class TaggedObjectsNode(Node):
    def __init__(self, tag, model, context_var):
        self.tag = tag
        self.context_var = context_var
        self.model = model

    def render(self, context):
        tag = resolve_variable(self.tag, context)
        model = get_model(*self.model.split('.'))
        context[self.context_var] = TaggedItem.objects.get_by_model(model,
                                                                    tag)
        return ''

def do_tags_for_model(parser, token):
    """
    Retrieves a list of ``Tag`` objects associated with a given model
    and stores them in a context variable.

    The model is specified in ``[appname].[modelname]`` format.

    If specified - by providing extra ``with counts`` arguments - adds
    a ``count`` attribute to each tag containing the number of
    instances of the given model which have been tagged with it.

    Example usage::

        {% tags_for_model products.Widget as widget_tags %}

        {% tags_for_model products.Widget as widget_tags with counts %}
    """
    bits = token.contents.split()
    len_bits = len(bits)
    if len_bits not in (4, 6):
        raise TemplateSyntaxError('%s tag requires either three or five arguments' % bits[0])
    if bits[2] != 'as':
        raise TemplateSyntaxError("second argument to %s tag must be 'as'" % bits[0])
    if len_bits == 6:
        if bits[4] != 'with':
            raise TemplateSyntaxError("if given, fourth argument to %s tag must be 'with'" % bits[0])
        if bits[5] != 'counts':
            raise TemplateSyntaxError("if given, fifth argument to %s tag must be 'counts'" % bits[0])
    if len_bits == 4:
        return TagsForModelNode(bits[1], bits[3], counts=False)
    else:
        return TagsForModelNode(bits[1], bits[3], counts=True)

def do_tags_for_object(parser, token):
    """
    Retrieves a list of ``Tag`` objects associated with an object and
    stores them in a context variable.

    Example usage::

        {% tags_for_object foo_object as tag_list %}
    """
    bits = token.contents.split()
    if len(bits) != 4:
        raise TemplateSyntaxError('%s tag requires exactly three arguments' % bits[0])
    if bits[2] != 'as':
        raise TemplateSyntaxError("second argument to %s tag must be 'as'" % bits[0])
    return TagsForObjectNode(bits[1], bits[3])

def do_tagged_objects(parser, token):
    """
    Retrieves a list of objects for a given Model which are tagged with
    a given Tag and stores them in a context variable.

    The tag must be an instance of a ``Tag``, not the name of a tag.

    The model is specified in ``[appname].[modelname]`` format.

    Example usage::

        {% tagged_objects foo_tag in tv.Model as object_list %}
    """
    bits = token.contents.split()
    if len(bits) != 6:
        raise TemplateSyntaxError('%s tag requires exactly five arguments' % bits[0])
    if bits[2] != 'in':
        raise TemplateSyntaxError("second argument to %s tag must be 'in'" % bits[0])
    if bits[4] != 'as':
        raise TemplateSyntaxError("fourth argument to %s tag must be 'as'" % bits[0])
    return TaggedObjectsNode(bits[1], bits[3], bits[5])

register.tag('tags_for_model', do_tags_for_model)
register.tag('tags_for_object', do_tags_for_object)
register.tag('tagged_objects', do_tagged_objects)