This file is indexed.

/usr/lib/python2.7/dist-packages/treebeard/templatetags/admin_tree.py is in python-django-treebeard 2.0~beta1-4.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
# -*- coding: utf-8 -*-
"""
Templatetags for django-treebeard to add drag and drop capabilities to the
nodes change list - @jjdelc

"""

import sys

from django.db import models
from django.conf import settings
from django.contrib.admin.templatetags.admin_list import (
    _boolean_icon, result_headers, result_hidden_fields)
from django.contrib.admin.util import display_for_field, lookup_field
from django.contrib.admin.views.main import EMPTY_CHANGELIST_VALUE
from django.core.exceptions import ObjectDoesNotExist
from django.template import Library
from django.utils.html import conditional_escape, escape
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _


register = Library()

if sys.version_info >= (3, 0):
    from django.utils.encoding import force_str, smart_str
    from urllib.parse import urljoin
else:
    from django.utils.encoding import force_unicode as force_str
    from django.utils.encoding import smart_unicode as smart_str
    from urlparse import urljoin

from treebeard.templatetags import needs_checkboxes


def items_for_result(cl, result, form):
    """
    Generates the actual list of data.

    @jjdelc:
    This has been shamelessly copied from original
    django.contrib.admin.templatetags.admin_list.items_for_result
    in order to alter the dispay for the first element
    """
    first = True
    pk = cl.lookup_opts.pk.attname
    for field_name in cl.list_display:
        row_class = ''
        try:
            f, attr, value = lookup_field(field_name, result, cl.model_admin)
        except (AttributeError, ObjectDoesNotExist):
            result_repr = EMPTY_CHANGELIST_VALUE
        else:
            if f is None:
                if getattr(attr, 'boolean', False):
                    allow_tags = True
                    result_repr = _boolean_icon(value)
                else:
                    allow_tags = getattr(attr, 'allow_tags', False)
                    result_repr = smart_str(value)
                if allow_tags:
                    result_repr = mark_safe(result_repr)
                else:
                    # strip HTML tags
                    result_repr = escape(result_repr)
            else:
                if isinstance(f.rel, models.ManyToOneRel):
                    result_repr = escape(getattr(result, f.name))
                else:
                    result_repr = display_for_field(value, f)
                if isinstance(f, (models.DateField, models.TimeField)):
                    row_class = ' class="nowrap"'
        if force_str(result_repr) == '':
            result_repr = mark_safe(' ')
        # If list_display_links not defined, add the link tag to the
        # first field
        if (
            (first and not cl.list_display_links) or
            field_name in cl.list_display_links
        ):
            table_tag = {True: 'th', False: 'td'}[first]

            # This spacer indents the nodes based on their depth
            if first:
                spacer = '<span class="spacer">&nbsp;</span>' * (
                    result.get_depth() - 1)
            else:
                spacer = ''

            # This shows a collapse or expand link for nodes with childs
            if result.get_children_count():
                collapse = ('<a href="#" title="" class="collapse expanded">'
                            '-</a>')
            else:
                collapse = '<span class="collapse">&nbsp;</span>'

            # Add a <td/> before the first col to show the drag handler
            drag_handler = ''

            if first:
                drag_handler = ('<td class="drag-handler">'
                                '<span>&nbsp;</span></td>')

            first = False
            url = cl.url_for_result(result)
            # Convert the pk to something that can be used in Javascript.
            # Problem cases are long ints (23L) and non-ASCII strings.
            if cl.to_field:
                attr = str(cl.to_field)
            else:
                attr = pk
            value = result.serializable_value(attr)
            result_id = repr(force_str(value))[1:]
            onclickstr = (
                ' onclick="opener.dismissRelatedLookupPopup(window, %s);'
                ' return false;"')
            yield mark_safe(
                '%s<%s%s>%s %s <a href="%s"%s>%s</a></%s>' % (
                    drag_handler, table_tag, row_class, spacer, collapse, url,
                    (cl.is_popup and onclickstr % result_id or ''),
                    conditional_escape(result_repr), table_tag))
        else:
            # By default the fields come from ModelAdmin.list_editable, but
            # if we pull the fields out of the form instead of
            # list_editable custom admins can provide fields on a per
            # request basis
            if form and field_name in form.fields:
                bf = form[field_name]
                result_repr = mark_safe(
                    force_str(bf.errors) + force_str(bf))
            else:
                result_repr = conditional_escape(result_repr)
            yield mark_safe('<td%s>%s</td>' % (row_class, result_repr))
    if form and not form[cl.model._meta.pk.name].is_hidden:
        yield mark_safe(
            '<td>%s</td>' % force_str(form[cl.model._meta.pk.name]))


def get_parent_id(node):
    """Return the node's parent id or 0 if node is a root node."""
    if node.is_root():
        return 0
    return node.get_parent().pk


def results(cl):
    if cl.formset:
        for res, form in zip(cl.result_list, cl.formset.forms):
            yield (res.pk, get_parent_id(res), res.get_depth(),
                   res.get_children_count(),
                   list(items_for_result(cl, res, form)))
    else:
        for res in cl.result_list:
            yield (res.pk, get_parent_id(res), res.get_depth(),
                   res.get_children_count(),
                   list(items_for_result(cl, res, None)))


def check_empty_dict(GET_dict):
    """
    Returns True if the GET querstring contains on values, but it can contain
    empty keys.
    This is better than doing not bool(request.GET) as an empty key will return
    True
    """
    empty = True
    for k, v in GET_dict.items():
        # Don't disable on p(age) or 'all' GET param
        if v and k != 'p' and k != 'all':
            empty = False
    return empty


@register.inclusion_tag(
    'admin/tree_change_list_results.html', takes_context=True)
def result_tree(context, cl, request):
    """
    Added 'filtered' param, so the template's js knows whether the results have
    been affected by a GET param or not. Only when the results are not filtered
    you can drag and sort the tree
    """

    # Here I'm adding an extra col on pos 2 for the drag handlers
    headers = list(result_headers(cl))
    headers.insert(1 if needs_checkboxes(context) else 0, {
        'text': '+',
        'sortable': True,
        'url': request.path,
        'tooltip': _('Return to ordered tree'),
        'class_attrib': mark_safe(' class="oder-grabber"')
    })
    return {
        'filtered': not check_empty_dict(request.GET),
        'result_hidden_fields': list(result_hidden_fields(cl)),
        'result_headers': headers,
        'results': list(results(cl)),
    }


def get_static_url():
    """Return a base static url, always ending with a /"""
    path = getattr(settings, 'STATIC_URL', None)
    if not path:
        path = getattr(settings, 'MEDIA_URL', None)
    if not path:
        path = '/'
    if not path.endswith('/'):
        path += '/'
    return path


@register.simple_tag
def treebeard_css():
    """
    Template tag to print out the proper <link/> tag to include a custom .css
    """
    LINK_HTML = """<link rel="stylesheet" type="text/css" href="%s"/>"""
    css_file = urljoin(get_static_url(), 'treebeard/treebeard-admin.css')
    return LINK_HTML % css_file


@register.simple_tag
def treebeard_js():
    """
    Template tag to print out the proper <script/> tag to include a custom .js
    """
    path = get_static_url()
    SCRIPT_HTML = """<script type="text/javascript" src="%s"></script>"""
    js_file = '/'.join([path.rstrip('/'), 'treebeard', 'treebeard-admin.js'])

    # Jquery UI is needed to call disableSelection() on drag and drop so
    # text selections arent marked while dragging a table row
    # http://www.lokkju.com/blog/archives/143
    JQUERY_UI = """
    <script>
      (function($){jQuery = $.noConflict(true);})(django.jQuery);
    </script>
    <script type="text/javascript" src="%s"></script>
    """
    jquery_ui = urljoin(path, 'treebeard/jquery-ui-1.8.5.custom.min.js')

    scripts = [SCRIPT_HTML % 'jsi18n',
               SCRIPT_HTML % js_file,
               JQUERY_UI % jquery_ui]
    return ''.join(scripts)