Choosing a random item from a tagged library

100 views Asked by At

Gradding a random image causes the title, url (etc) attributes on the tag.rand_img to vanish, meaning I can't display anything more than the object name.

view.py:

def locations_gallery(request):
  queryset = Photo.objects.all()
  tags = Tag.objects.usage_for_queryset(queryset, counts=True)
  tags.sort(key=operator.attrgetter('count'), reverse=True)
  for tag in tags:
    image_tag = Tag.objects.get(name=tag)
    tag.rand_img = TaggedItem.objects.get_union_by_model(Photo, image_tag).order_by('?')[:1]
  ctxt['tags'] = tags
  return render_to_response('locations_gallery.html', ctxt, RequestContext(request))

Template (simplified):

{% for tag in tags %}
{{ tag.name }}
<img src="{{ tag.rand_img.url }}">
{% endfor %}
3

There are 3 answers

0
Daniel Roseman On BEST ANSWER

This line:

tag.rand_img = TaggedItem.objects.get_union_by_model(Photo, image_tag).order_by('?')[:1]

is returning a Queryset, not a model instance. The queryset doesn't have your custom methods, they exist only on the instance within that queryset.

Replace the [:1] with [0] to get the actual model instance (you'll need to catch IndexError in case there isn't a matching item).

5
Laur Ivan On

I'd first get the tags:

tags = Tag.objects.usage_for_queryset(queryset, counts=True)
tags.sort(key=operator.attrgetter('count'), reverse=True)

and then iterate through them and add the image as an extra field. Then you could do something like you've outlined in your template.

1
Burhan Khalid On

You can add attributes like that, Python will allow it but then you are no longer working on a QuerySet.

Try this:

def get_rand_img(tag):
   return TaggedItem.objects.get_union_by_model(Photo, tag).order_by('?')[:1]

display_tags = [(Tag.objects.get(name=tag),
                 get_rand_img(Tag.objects.get(name=tag))) for tag in tags]
ctxt['tags'] = display_tags

Then in your view

{% for tag, rand_img in tags %}
   {{ tag.name }}
   <img src="{{ rand_img.url }}">
{% endfor %}