Login

View to retrieve objects meeting a complex tag query

Author:
nathangeffen
Posted:
December 22, 2010
Language:
Python
Version:
1.2
Score:
0 (after 0 ratings)

This view parses complex tag queries. It generates a list of model instances matching an expression of tags. The expression currently supports intersection, union and subtraction. Expressions can also be put in parenthesis and then combined with other expressions.

The expression must be passed to this view in the tag_expression argument. In my application this is simply passed from the URL querystring.

This snippet uses the django-tagging app.

It assumes that tags are composed of alphanumeric characters, underscores, hyphens and spaces, but the django-tagging application allows tags with other characters, so you might either want to restrict users to using tags that only contain the above characters, or you might prefer to improve this snippet.

Example: This URL

http://example.com/people/?(deceased&parrot)|"Monty Python"

will retrieve all people who are either deceased parrots or members of Monty Python.

In the tag_expression argument:

  • ALL is treated as a keyword. If you happen (by some sad chance) to have a tag called ALL and want to use it in the expression, surround it in quotation marks. E.g. "ALL"

  • Examples:

  • famous -returns all instances of the model tagged with famous

  • famous&deceased -returns all instances of the model tagged both famous and deceased.

  • famous|deceased -returns all instances of the model tagged famous or deceased.

  • parrot-deceased -returns all alive parrots in the model.

  • ALL-deceased -returns all instances of the model that are not tagged deceased.

  • ALL -returns all instances of the model

  • "ALL" -returns all instances of the model that are tagged ALL

  • "great author"&deceased -returns all models tagged as great authors and deceased.

Arguments:

  • request -- HTTP Request object

  • tag_expression -- a set expression of tags, supporting intersection, union, parenthesis and difference

  • app_name -- App for the model we're working on (defaults to pubman)

  • model_name -- Model on which to apply the set operations (defaults to Article)

  • view -- view to redirect to after the model instance list has been constructed

  • html_template -- HTML template to redirect (defaults to 'pubman/tag.html')

 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
import re
from tagging.models import Tag, TaggedItem
from django.db.models import Q, get_model

def tag_view(request, 
             tag_expression, 
             app_name = 'pubman',
             model_name='article', 
             view=article_list_view,
             html_template='pubman/tag.html'):


    model_filter = TaggedItem.objects.all().filter(content_type__model=model_name)
    
    search_string = '\'[\w\s]+\'|\"[\w\s]+\"|[\w\s]+|&|\||\(|\)|-'    
    parse_string = re.findall(search_string, tag_expression)
    
    print parse_string
    
    querystring = ""
     
    for token in parse_string:
        if token in ['&', '|','-', '(',')']:
            querystring +=  ' ' + token + ' '
        elif token == 'ALL':
            querystring += ' set([i.id for i in get_model("' +\
                app_name + '", "' +\
                model_name + '")'+ '.objects.all()])'            
        else:
            token = token.replace('"','')
            token = token.replace("'","")            
            querystring += ' set([i.object_id for i in '+\
                'model_filter.filter(tag__name="' + token + '")])'

    print 'Query: ', querystring

    try:                
        instances = eval(querystring)
    except:
        # This is the fallback when there's an error in the expression.
        # A better way might be to raise Http404.
        instances = model_filter.filter(tag__name=tag_expression)

    object_list = get_model(app_name, model_name).\
        objects.all().filter(id__in=instances)
        
    return view(request, object_list, html_template)

More like this

  1. Template tag - list punctuation for a list of items by shapiromatron 11 months, 2 weeks ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 11 months, 3 weeks ago
  3. Serializer factory with Django Rest Framework by julio 1 year, 6 months ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 7 months ago
  5. Help text hyperlinks by sa2812 1 year, 7 months ago

Comments

nathangeffen (on December 22, 2010):

Apologies, the first version I uploaded was not generic. But I've corrected it and now it should be. I've also improved the description.

#

Please login first before commenting.