开发者

Looping problem with dictionary in Django templates

I'm not sure why this template is not rendering anything to the page. Is there anything开发者_StackOverflow社区 obvious I am missing here?

View:

@user_passes_test(is_staff)
def details_activity_log(request, project_id, template='projects/details_activity_log.html'):

    project = get_object_or_404(Project.objects.select_related(), pk=project_id)
    action_log = project.projectactionlog_set.all()

    log_group = defaultdict(list)

    for log in action_log:
        log_group[log.action_time.strftime('%y%m%d')].append(log)


    #import pdb; pdb.set_trace()

    return render_to_response(template, {
        'log_group'  : log_group,
        'project'    : project,
        'action_log' : action_log,
        'tab_5'      : 'active',
    }, context_instance=RequestContext(request))

log_group contains a dict of model objects like so:

defaultdict(<type 'list'>, {'110614': [<ProjectActionLog: ProjectActionLog object>, ...]}) 

Template:

   {% for key, log in log_group %}
      {% for action in log %}
        {{ action }}
        {{ action.action_time }}                    
        {{ action.user.first_name }}
        {{ action.message }}
        {{ action.object_name }}
      {% endfor %}
    {% endfor %}

Edit If only I had looked in the docs I would have seen the answer. https://docs.djangoproject.com/en/dev/ref/templates/builtins/?from=olddocs#for

However it's a tricky situation since the templates don't throw any runtime errors when the loop can't unpack the iterator items.


Change

{% for key, log in log_group %}

to

{% for key, log in log_group.items %}


Update your for loop to:

{% for log in log_group.itervalues %}

Or, if you actually need key (your example template doesn't show you using it):

{% for key, log in log_group.iteritems %}


Also be very careful with defaultdicts in a django template, and I see in your code that you are indeed using a defaultdict.

They plainly don't work as expected inside a template because of the way django attempts to access properties/attributes/etc. and the only solution is to convert them to dicts:

context['dictstructure'] = dict(mydefaultdict)

The template documentation was patched following ticket #16335, changeset to include a special notice on this issue.

Technically, when the template system encounters a dot, it tries the following lookups, in this order:

  • Dictionary lookup
  • Attribute lookup
  • Method call
  • List-index lookup

This can cause some unexpected behavior with objects that override dictionary lookup. For example, consider the following code snippet that attempts to loop over a collections.defaultdict:

{% for k, v in defaultdict.iteritems %}
    Do something with k and v here... 
{% endfor %} 

Because dictionary lookup happens first, that behavior kicks in and provides a default value instead of using the intended .iteritems() method. In this case, consider converting to a dictionary first.

Please also see question Django template can't loop defaultdict

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜