web/hdalab/views/ajax.py
author ymh <ymh.work@gmail.com>
Fri, 02 Mar 2012 10:48:26 +0100
changeset 133 e821a1ae9773
parent 132 e6483309fa52
child 134 75f8f05f9a60
permissions -rw-r--r--
small query optimisation in filter

# -*- coding: utf-8 -*-
'''
Created on Jan 31, 2012

@author: ymh
'''
from django.conf import settings
from django.db import connection
from django.db.models import Q, Count, Sum
from django.http import HttpResponse
from hdabo.models import Tag, Datasheet, TaggedSheet
from hdalab.models import TagLinks, HdaSession, Country, TagYears, DatasheetExtras
import django.utils.simplejson as json
import hmac
import uuid

def taginfo(request):
    label = request.GET.get('label', None)
    
    resobj = {'requested_label' : label}
        
    resobj["content_count"] = Datasheet.objects.filter(taggedsheet__tag__label__iexact = label).distinct().count()
    
    res = Tag.objects.select_related('dbpedia_fields').filter(label__iexact = label).order_by('-dbpedia_uri')[0:1]
    if len(res) == 1:
        restag = res.get()
        resobj["dbpedia_uri"] = restag.dbpedia_uri
        if resobj["dbpedia_uri"] is not None and restag.dbpedia_fields is not None:
            dbfield = restag.dbpedia_fields
            resobj["abstract"] = dbfield.abstract
            resobj["dbpedia_label"] = dbfield.label
            resobj["thumbnail"] = dbfield.thumbnail
    res = Tag.objects.filter(label__iexact = label).order_by('-wikipedia_url')[0:1]
    if len(res) == 1:
        resobj["wikipedia_url"] = res.get().wikipedia_url
        
    resobj["links"] = [{'subject':tl.subject.label, 'object':tl.object.label} for tl in TagLinks.objects.select_related().filter(Q(subject__label__iexact = label) | Q(object__label__iexact = label))]

    return HttpResponse(content=json.dumps(resobj), mimetype='application/json')


def sessioninfo(request):
    
    data = json.loads(request.GET.get('data', "{}"))
    write = False
    
    if 'sessionid' in request.GET:
        request.session['sessionid'] = request.GET['sessionid']
    if 'sessionkey' in request.GET:
        request.session['sessionkey'] = request.GET['sessionkey']
        
    if 'sessionid' in request.session:
        sessionid = request.session['sessionid']
        
        if HdaSession.objects.filter(sessionid=sessionid).count() == 1:
            sessionkey = request.session.get('sessionkey',None)
            hm = hmac.new(settings.SECRET_KEY, sessionid)
            if hm.hexdigest() == sessionkey:
                write = True            
        else:
            del request.session['sessionid']
        
    if 'sessionid' not in request.session:
        sessionid = unicode(uuid.uuid1())
        HdaSession.objects.create(sessionid=sessionid, data=json.dumps({}))
        write = True
        request.session['sessionid'] = sessionid
        request.session['sessionkey'] = hmac.new(settings.SECRET_KEY, sessionid).hexdigest()
        
    if write and data:
        HdaSession.objects.filter(sessionid=sessionid).update(data=json.dumps(data))
    else:
        data = HdaSession.objects.get(sessionid=sessionid).data
        data = json.loads(data) if data else {}           
         
    resobj = {'data': data, "write_allowed" : write, "sessionid": sessionid }
    if write:
        resobj['sessionkey'] = request.session['sessionkey']
        
    return HttpResponse(content=json.dumps(resobj), mimetype='application/json')


def tagsearch(request):
    
    q = request.GET.get('term',None)
    qs = Tag.objects.filter(label__icontains = q) if q else Tag.objects.all()        
    res = qs.annotate(nb=Count('datasheet')).order_by('-nb')[:20]
    
    return HttpResponse(content=json.dumps([{'label':t.label,'nb':t.nb} for t in res]), mimetype='application/json')


def filter(request):
    periode = request.GET.get('period',None)
    label = request.GET.get('label', None)
    country = request.GET.get('country', None)
    contentlist = request.GET.get('contentlist', None)
    max_tag_order = request.GET.get('mto', 12)
    content_count = request.GET.get('contentcount', 12)
    tag_count = request.GET.get('tagcount', 30)
    
    matchtagids = []
    
    tagqs = Tag.objects.exclude(category__label__in = ['Datation', 'Localisation', 'Discipline artistique'])
    countryqs = Country.objects
    discqs = Tag.objects.filter(category__label = u'Discipline artistique')
    yearqs = TagYears.objects
    
    contentqs = Datasheet.objects.filter(validated=True)

    if label or periode or country or contentlist :
        
        if periode:
            years = periode.split(",")
            start_year = int(years[0])
            end_year = int(years[0:2][-1])
            delta = max(1, (end_year-start_year)/2)
            minstart = start_year - delta
            maxend = end_year + delta
            matchtagqs = Tag.objects.filter(years__end_year__gte = start_year, 
                                       years__start_year__lte = end_year,
                                       years__end_year__lte = maxend,
                                       years__start_year__gte = minstart)
            matchtagids += [t.id for t in matchtagqs]
            contentqs = contentqs.filter(taggedsheet__tag__in = matchtagqs,
                           taggedsheet__order__lte = max_tag_order)
            
        if label:
            for txtlbl in label.split(","):
                matchtagqs = Tag.objects.filter(label__iexact = txtlbl)
                matchtagids += [t.id for t in matchtagqs if t.id not in matchtagids]
                contentqs = contentqs.filter(taggedsheet__tag__in = matchtagqs,
                               taggedsheet__order__lte = max_tag_order)
                    
        if country:
            for country_uri in country.split(","):
                matchtagqs = Tag.objects.filter(locatedin__country__dbpedia_uri = country_uri)
                matchtagids += [t.id for t in matchtagqs if t.id not in matchtagids]
                contentqs = contentqs.filter(taggedsheet__tag__in = matchtagqs,
                               taggedsheet__order__lte = max_tag_order)
        if contentlist:
            contentqs = contentqs.filter(id__in = contentlist.split(","))
            
        tagqs = tagqs.filter(datasheet__in = contentqs)
        countryqs = countryqs.filter(includes__tag__taggedsheet__datasheet__in = contentqs)
        discqs = discqs.filter(datasheet__in = contentqs)
        yearqs = yearqs.filter(tag__taggedsheet__datasheet__in = contentqs)
        
    if contentlist is None:
        contentqs.order_by('?')
            
    cont_count = contentqs.count()
    
    contenus = dict([(content.id, {'score' : 0, 'tags' : [], 'id':content.id, 'title': content.title, 'description': content.description, 'url': content.url}) for content in contentqs[0:content_count]])
    contentids = contenus.keys()
    
    qs = DatasheetExtras.objects.select_related('insee').filter(datasheet__in = contentids)
    for dse in qs:
        contenus[dse.datasheet_id]['coords'] = {'city_name': dse.insee.city_name, 'latitude': dse.insee.latitude, 'longitude': dse.insee.longitude}
    
    qs = TaggedSheet.objects.select_related('tag').filter(datasheet__in = contentids, order__lte = max_tag_order).order_by('order')
    for ts in qs:
        match_tag = ts.tag.id in matchtagids
        contenus[ts.datasheet_id]['tags'].append({'id': ts.tag.id, 'label':ts.tag.label, 'order':ts.order, 'match': match_tag })
        
        if match_tag:
            contenus[ts.datasheet_id]['score'] += 2*max_tag_order - ts.order
        
    if contentlist is None:
        contenus = sorted(contenus.values(),key=lambda e: -e['score'])
    else:
        contenus = contenus.values()

    tagqs = tagqs.annotate(nb=Count('datasheet')).order_by('-nb')[:tag_count]

    tags = [{'id': tag.id, 'label': tag.label, 'score': tag.nb} for tag in tagqs]

    countryqs = countryqs.annotate(nb=Count('includes__tag__taggedsheet'))
    countries = dict([(country.dbpedia_uri, country.nb) for country in countryqs])

    discqs = discqs.annotate(nb=Count('taggedsheet')).order_by('-nb')[:10]
    disciplines = [{'label':tag.label,'score':tag.nb} for tag in discqs]
    
    years = {}
    yearqs = yearqs.annotate(nb=Count('tag__taggedsheet'))
    for ty in yearqs:
        for year in range(ty.start_year, ty.end_year):
            years[year] = ty.nb + (years[year] if year in years else 0)
            
    yearchange = []
    for year in sorted(years.keys()):
        score = years[year]
        if year < 2011:
            if (year-1 not in years and score != 0) or (year-1 in years and years[year-1] != score):
                yearchange.append({'year': year, 'score': score})
            if year+1 not in years and year != -1 and score != 0:
                yearchange.append({'year': year+1, 'score': 0})

    output = {'count': cont_count, 'contents': contenus, 'tags':tags, 'sparkline':yearchange, 'countries':countries, 'disciplines':disciplines}
    
    return HttpResponse(content=json.dumps(output), mimetype='application/json')