diff options
| author | Étienne Loks <etienne.loks@proxience.com> | 2016-01-05 22:17:44 +0100 | 
|---|---|---|
| committer | Étienne Loks <etienne.loks@proxience.com> | 2016-01-05 22:17:44 +0100 | 
| commit | 9ce61bc6de5e98397e84c24a00d30002d4e04de5 (patch) | |
| tree | 8ab9d19530ca3026fb21aff1993982f487dc7a28 /chimere/views.py | |
| parent | 2ca084384e6bf0596822938a607a189b507f60ed (diff) | |
| parent | 89c4baf537a590dbe80c5f6a4c20f202c63ebb15 (diff) | |
| download | Chimère-9ce61bc6de5e98397e84c24a00d30002d4e04de5.tar.bz2 Chimère-9ce61bc6de5e98397e84c24a00d30002d4e04de5.zip  | |
Merge branch 'v2.2'
Conflicts:
	chimere/actions.py
	chimere/admin.py
	chimere/locale/fr/LC_MESSAGES/django.po
	chimere/models.py
	chimere/urls.py
	chimere/utils.py
	chimere/views.py
Diffstat (limited to 'chimere/views.py')
| -rw-r--r-- | chimere/views.py | 474 | 
1 files changed, 260 insertions, 214 deletions
diff --git a/chimere/views.py b/chimere/views.py index be9d816..88619ce 100644 --- a/chimere/views.py +++ b/chimere/views.py @@ -1,6 +1,6 @@  #!/usr/bin/env python  # -*- coding: utf-8 -*- -# Copyright (C) 2008-2014  Étienne Loks  <etienne.loks_AT_peacefrogsDOTnet> +# Copyright (C) 2008-2015  Étienne Loks  <etienne.loks_AT_peacefrogsDOTnet>  #  # RSS : Copyright (C) 2010 Pierre Clarenc <pierre.crc_AT_gmailDOTcom>,  #                          Samuel Renard <renard.samuel_AT_gmailDOTcom>, @@ -24,15 +24,12 @@  Views of the project  """ -import copy  import datetime  from itertools import groupby  import re  import simplejson as json  from django.conf import settings -from django.contrib.auth import authenticate, login, logout -from django.contrib.auth.forms import AuthenticationForm  from django.contrib.gis.geos import GEOSGeometry  from django.contrib.gis.gdal.error import OGRException  from django.contrib.gis.measure import D @@ -41,23 +38,24 @@ from django.core import serializers  from django.core.exceptions import ObjectDoesNotExist  from django.core.urlresolvers import reverse  from django.db.models import Q -from django.http import HttpResponseRedirect, HttpResponse -from django.shortcuts import redirect, render_to_response +from django.http import HttpResponseRedirect, HttpResponse, Http404 +from django.shortcuts import get_object_or_404, redirect, render_to_response  from django.template import loader, RequestContext, defaultfilters  from django.utils import simplejson as json  from django.utils.http import urlquote  from django.utils.translation import ugettext as _ +from django.views.generic import TemplateView, ListView -from chimere.actions import actions as default_actions +from chimere.actions import actions  from chimere.models import Category, SubCategory, PropertyModel, Page,\ -     Marker, Route, News, SimpleArea, Map, Color, TinyUrl, RouteFile,\ +     Marker, Route, News, SimpleArea, Area, Color, TinyUrl, RouteFile,\       AggregatedRoute -from chimere.widgets import getMapJS, PointChooserWidget, NominatimWidget,\ +from chimere.widgets import getMapJS, PointChooserWidget, \                              RouteChooserWidget, AreaWidget  from chimere.forms import MarkerForm, RouteForm, ContactForm, FileForm, \       FullFileForm, MultimediaFileFormSet, PictureFileFormSet, notifySubmission,\ -     notifyStaff, MapForm, RoutingForm, getStaffEmails +     notifyStaff, AreaForm, RoutingForm, getStaffEmails  from chimere.route import router @@ -74,41 +72,43 @@ def get_base_uri(request):      return base_uri  #TODO: convert to requestcontext -def get_base_response(request, map_name="", propose=False): +def get_base_response(request, area_name=""):      """      Get the base url      """ -    base_response_dct = {'media_path':settings.MEDIA_URL, -                         'is_authenticated':request.user.is_authenticated()} +    base_response_dct = {'media_path':settings.MEDIA_URL,}      base_response_dct['MOBILE'] = settings.MOBILE_TEST or \                      get_current_site(request).domain in settings.MOBILE_DOMAINS      base_url = reverse("chimere:index")      if not base_url.startswith('/'):          base_url = '/' + base_url -    if map_name and map_name.endswith('/'): -        map_name = map_name[:-1] -    if map_name: -        base_response_dct['map_name_slash'] = map_name + "/" +    if area_name and area_name.endswith('/'): +        area_name = area_name[:-1] +    if area_name: +        base_response_dct['area_name_slash'] = area_name + "/"          if base_url[-1] != '/':              base_url += '/' -        base_url += map_name + '/' +        base_url += area_name + '/'      base_response_dct['extra_url'] = base_url -    map = Map.getAvailable(user=request.user, urn=map_name, propose=propose, -                           single=True) -    if map: -        map_name = map.urn -    elif map_name: -        return None, redirect(reverse('chimere:index')) -    if map: -        base_response_dct['can_write'] = map.can_write(user=request.user) -        base_response_dct['can_propose'] = map.can_propose(user=request.user) - -    base_response_dct['map'] = map -    base_response_dct['map_name'] = map_name -    if map and map.external_css: -        base_response_dct['css_map'] = map.external_css +    area = None +    if area_name: +        try: +            area = Area.objects.get(urn=area_name, available=True) +        except ObjectDoesNotExist: +            return None, redirect(reverse('chimere:index')) +    else: +        try: +            area = Area.objects.get(default=True) +            area_name = area.urn +        except ObjectDoesNotExist: +            pass + +    base_response_dct['area'] = area +    base_response_dct['area_name'] = area_name +    if area and area.external_css: +        base_response_dct['css_area'] = area.external_css      base_response_dct['dynamic_categories'] = True \ -            if map and map.dynamic_categories else False +            if area and area.dynamic_categories else False      base_response_dct['JQUERY_JS_URLS'] = settings.JQUERY_JS_URLS      base_response_dct['JQUERY_CSS_URLS'] = settings.JQUERY_CSS_URLS      base_response_dct['PROJECT_NAME'] = settings.PROJECT_NAME @@ -116,17 +116,17 @@ def get_base_response(request, map_name="", propose=False):          base_response_dct['EXTRA_CSS'] = settings.EXTRA_CSS      return base_response_dct, None -def getShareUrl(request, map_name='', network=''): +def getShareUrl(request, area_name='', network=''):      """      Get a share url      """ -    data = getTinyfiedUrl(request, request.GET.urlencode(), map_name) +    data = getTinyfiedUrl(request, request.GET.urlencode(), area_name)      for name, url, img in settings.CHIMERE_SHARE_NETWORKS:          if defaultfilters.slugify(name) == network:              return HttpResponse(url % {'text':data['text'], 'url':data['url']})      return HttpResponse('') -def getShareNetwork(request, map_name='', marker=None): +def getShareNetwork(request, area_name='', marker=None):      """      Get URLs to share items      """ @@ -135,19 +135,14 @@ def getShareNetwork(request, map_name='', marker=None):          parameters = u'current_feature=%d' % marker.pk          parameters += u"&checked_categories=%s" % "_".join([str(m.id) \                                                for m in marker.categories.all()]) -    net_dct = getTinyfiedUrl(request, parameters, map_name) +    net_dct = getTinyfiedUrl(request, parameters, area_name)      share_networks = []      for network in settings.CHIMERE_SHARE_NETWORKS:          share_networks.append((network[0], network[1] % net_dct, network[2]))      return share_networks, net_dct - -def logout_view(request): -    logout(request) -    return redirect(reverse('chimere:index')) - -def index(request, map_name=None, default_map=None, simple=False, -          get_response=False, actions=default_actions): +def index(request, area_name=None, default_area=None, simple=False, +          get_response=False):      """      Main page      """ @@ -159,28 +154,9 @@ def index(request, map_name=None, default_map=None, simple=False,         request.session['last_visit'] != today:          request.session['last_visit'] = today          news_visible = True -    response_dct, redir = get_base_response(request, map_name) +    response_dct, redir = get_base_response(request, area_name)      if redir:          return redir - -    if request.POST: -        auth_form = AuthenticationForm(None, request.POST) -        invalid_msg = _(u"Invalid user or password.") -        if auth_form.is_valid(): -            user = authenticate( -                    username=auth_form.cleaned_data['username'], -                    password=auth_form.cleaned_data['password']) -            if user is not None and user.is_active: -                login(request, user) -                return redirect(reverse('chimere:index')) -        else: -            response_dct['auth_form'] = auth_form -    else: -        response_dct['auth_form'] = AuthenticationForm() - -    if not response_dct['map']: -        return render_to_response('chimere/no_map.html', response_dct, -                              context_instance=RequestContext(request))      # don't mess with permalink      zoomout = True      if request.GET and 'lat' in request.GET \ @@ -198,24 +174,24 @@ def index(request, map_name=None, default_map=None, simple=False,          except:              pass      response_dct.update({ -         'actions':actions(request.user, response_dct['map_name']), +         'actions':actions(response_dct['area_name']),           'action_selected':('view',),           'error_message':'',           'is_map':True,           'news_visible': news_visible, -         'maps_visible': settings.CHIMERE_DISPLAY_MAPS, +         'areas_visible': settings.CHIMERE_DISPLAY_AREAS,           'map_layer':settings.CHIMERE_DEFAULT_MAP_LAYER,           'dynamic_categories':response_dct['dynamic_categories'],           'zoomout':zoomout, -         'has_default_map':Map.objects.filter(default=True).count(), -         'zoomout':zoomout, -         'has_search':settings.CHIMERE_SEARCH_ENGINE, +         'has_default_area':Area.objects.filter(default=True).count(),           'zoomout':zoomout, +         'has_search':hasattr(settings, 'CHIMERE_SEARCH_ENGINE') and \ +                      settings.CHIMERE_SEARCH_ENGINE          })      if hasattr(settings, 'CONTACT_EMAIL') and settings.CONTACT_EMAIL:          response_dct['contact_email'] = settings.CONTACT_EMAIL      response_dct['share_networks'], net_dct = \ -                   getShareNetwork(request, response_dct['map_name']) +                   getShareNetwork(request, response_dct['area_name'])      tpl = 'chimere/main_map.html'      response_dct['simple'] = simple      if simple: @@ -231,13 +207,13 @@ def get_edit_page(redirect_url, item_cls, item_form,      """      Edition page      """ -    def func(request, map_name="", item_id=None, cat_type=['M']): -        response_dct, redir = get_base_response(request, map_name, propose=True) +    def func(request, area_name="", item_id=None, cat_type=['M']): +        response_dct, redir = get_base_response(request, area_name)          if redir:              return redir, None, None -        if 'map_name' in response_dct: -            map_name = response_dct['map_name'] -        subcategories = SubCategory.getAvailable(cat_type, map_name, +        if 'area_name' in response_dct: +            area_name = response_dct['area_name'] +        subcategories = SubCategory.getAvailable(cat_type, area_name,                                                   public=True)          listed_subcats = []          if subcategories: @@ -250,7 +226,7 @@ def get_edit_page(redirect_url, item_cls, item_form,              try:                  init_item = item_cls.objects.get(pk=item_id)              except: -                return redirect(redirect_url, map_name + '/' if map_name \ +                return redirect(redirect_url, area_name + '/' if area_name \                                  else ''), None, None              ref_item = init_item              modified_item = item_cls.objects.filter(ref_item=init_item, @@ -261,17 +237,18 @@ def get_edit_page(redirect_url, item_cls, item_form,          init_multi = init_item.get_init_multi() if init_item else None          init_picture = init_item.get_init_picture() if init_item else None -        if init_item and not response_dct['can_write'] and \ +        if init_item and not request.user.is_superuser and \                           not init_item.submiter_session_key == \                                          request.session.session_key:              # hide personal information              for k in ('submiter_name', 'submiter_email', 'submiter_comment'):                  setattr(init_item, k, '') +        response_dct['is_superuser'] = request.user.is_superuser          # If the form has been submited          if request.method == 'POST':              inst = None -            # allow to directly modify only if owner or has can_write permission -            if init_item and (response_dct['can_write'] or \ +            # allow to directly modify only if owner or superuser +            if init_item and (request.user.is_superuser or \                             init_item.submiter_session_key == \                                          request.session.session_key):                  inst = init_item @@ -284,7 +261,7 @@ def get_edit_page(redirect_url, item_cls, item_form,              # All validation rules pass              if form.is_valid() and formset_multi.is_valid() and \                 formset_picture.is_valid(): -                item = form.save(can_write=response_dct.get('can_write')) +                item = form.save()                  # set the session key (to permit modifications)                  item.submiter_session_key = request.session.session_key @@ -302,7 +279,7 @@ def get_edit_page(redirect_url, item_cls, item_form,                  # just submited                  if not item.status: -                    item.status = 'A' if response_dct.get('can_write') else 'S' +                    item.status = 'S'                  item.save()                  marker = item @@ -318,9 +295,9 @@ def get_edit_page(redirect_url, item_cls, item_form,                          f.save(marker)                  base_uri = get_base_uri(request)                  notifySubmission(base_uri, item) -                response_dct = get_base_response(request, map_name) +                response_dct = get_base_response(request, area_name)                  return redirect(redirect_url + '-item', -                            map_name + '/' if map_name else '', +                            area_name + '/' if area_name else '',                              item.ref_item.pk, 'submited'), None, subcategories              else:                  response_dct['error_message'] = _(u"There are missing field(s)" @@ -337,12 +314,11 @@ def get_edit_page(redirect_url, item_cls, item_form,  get_edit_marker = get_edit_page('chimere:edit', Marker, MarkerForm) -def edit(request, map_name="", item_id=None, submited=False, -         actions=default_actions): +def edit(request, area_name="", item_id=None, submited=False):      """      Edition page      """ -    response, values, sub_categories = get_edit_marker(request, map_name, +    response, values, sub_categories = get_edit_marker(request, area_name,                                                         item_id, ['M', 'B'])      if response:          return response @@ -356,24 +332,20 @@ def edit(request, map_name="", item_id=None, submited=False,      point_value = init_item.point if init_item else None      if request.POST and request.POST.get('point'):          point_value = request.POST.get('point') -    has_dated_items = settings.CHIMERE_DAYS_BEFORE_EVENT and [ -                    True for cat, subcats in sub_categories -                        if [True for subcat in subcats if subcat.dated]]      response_dct.update({ -        'actions':actions(request.user, response_dct['map_name']), +        'actions':actions(response_dct['area_name']),          'action_selected':('contribute', 'edit'),          'map_layer':settings.CHIMERE_DEFAULT_MAP_LAYER,          'form':form,          'formset_multi':formset_multi,          'formset_picture':formset_picture, -        'dated':has_dated_items, -        'extra_head':form.media + NominatimWidget().media, +        'dated':settings.CHIMERE_DAYS_BEFORE_EVENT, +        'extra_head':form.media,          'marker_id':item_id,          'sub_categories':sub_categories,          'point_widget':PointChooserWidget().render('point',                point_value, -              map_name=response_dct['map_name']), -        'nominatim_widget':NominatimWidget().render('point'), +              area_name=response_dct['area_name']),          'properties':declared_fields,          'filtered_properties':filtered_properties,          'submited':submited @@ -384,8 +356,8 @@ def edit(request, map_name="", item_id=None, submited=False,      return render_to_response('chimere/edit.html', response_dct,                                context_instance=RequestContext(request)) -def uploadFile(request, category_id='', map_name=''): -    response_dct, redir = get_base_response(request, map_name) +def uploadFile(request, category_id='', area_name=''): +    response_dct, redir = get_base_response(request, area_name)      if redir:          return redir      Form = FileForm if not category_id else FullFileForm @@ -432,7 +404,7 @@ def uploadFile(request, category_id='', map_name=''):      return render_to_response('chimere/upload_file.html', response_dct,                                context_instance=RequestContext(request)) -def processRouteFile(request, map_name='', file_id=None): +def processRouteFile(request, area_name='', file_id=None):      if file_id:          try:              route_file = RouteFile.objects.get(pk=file_id) @@ -450,12 +422,11 @@ def processRouteFile(request, map_name='', file_id=None):  get_edit_route = get_edit_page('chimere:editroute', Route, RouteForm) -def editRoute(request, map_name="", item_id=None, submited=False, -              actions=default_actions): +def editRoute(request, area_name="", item_id=None, submited=False):      """      Route edition page      """ -    response, values, sub_categories = get_edit_route(request, map_name, +    response, values, sub_categories = get_edit_route(request, area_name,                                                         item_id, ['R', 'B'])      if response:          return response @@ -469,22 +440,19 @@ def editRoute(request, map_name="", item_id=None, submited=False,      route_value = init_item.route if init_item else None      if request.POST and request.POST.get('route'):          route_value = request.POST.get('route') -    has_dated_items = settings.CHIMERE_DAYS_BEFORE_EVENT and [ -                    True for cat, subcats in sub_categories -                        if [True for subcat in subcats if subcat.dated]]      response_dct.update({ -        'actions':actions(request.user, response_dct['map_name']), +        'actions':actions(response_dct['area_name']),          'action_selected':('contribute', 'edit-route'),          'error_message':'',          'map_layer':settings.CHIMERE_DEFAULT_MAP_LAYER,          'form':form,          'formset_multi':formset_multi,          'formset_picture':formset_picture, -        'dated':has_dated_items, +        'dated':settings.CHIMERE_DAYS_BEFORE_EVENT,          'extra_head':form.media,          'sub_categories':sub_categories,          'route_widget':RouteChooserWidget().render('route', route_value, -                       map_name=response_dct['map_name'], routefile_id='',), +                       area_name=response_dct['area_name'], routefile_id='',),          'properties':declared_fields,          'submited':submited      }) @@ -494,33 +462,34 @@ def editRoute(request, map_name="", item_id=None, submited=False,      return render_to_response('chimere/edit_route.html', response_dct,                                context_instance=RequestContext(request)) -def submited(request, map_name="", action="", actions=default_actions): +def submited(request, area_name="", action=""):      """      Successful submission page      """ -    response_dct, redir = get_base_response(request, map_name) +    response_dct, redir = get_base_response(request, area_name)      if redir:          return redir -    response_dct.update({'actions':actions(request.user, response_dct['map_name']), -                         'action_selected':action,}) +    dct = {'actions':actions(response_dct['area_name']), +           'action_selected':action,}      if hasattr(settings, 'CONTACT_EMAIL') and settings.CONTACT_EMAIL:          response_dct['contact_email'] = settings.CONTACT_EMAIL +    response_dct.update(dct)      return render_to_response('chimere/submited.html', response_dct,                                context_instance=RequestContext(request)) -def charte(request, map_name="", actions=default_actions): +def charte(request, area_name=""):      """      Affichage de la charte      """ -    response_dct, redir = get_base_response(request, map_name) +    response_dct, redir = get_base_response(request, area_name)      if redir:          return redir -    response_dct.update({'actions':actions(request.user, response_dct['map_name']), +    response_dct.update({'actions':actions(response_dct['area_name']),                           'action_selected':('charte',)})      return render_to_response('chimere/charte.html', response_dct,                                context_instance=RequestContext(request)) -def contactus(request, map_name="", actions=default_actions): +def contactus(request, area_name=""):      """      Contact page      """ @@ -541,16 +510,16 @@ def contactus(request, map_name="", actions=default_actions):                  msg = _(u"Temporary error. Renew your message later.")      else:          form = ContactForm() -    response_dct, redir = get_base_response(request, map_name) +    response_dct, redir = get_base_response(request, area_name)      if redir:          return redir -    response_dct.update({'actions':actions(request.user, response_dct['map_name']), +    response_dct.update({'actions':actions(response_dct['area_name']),                           'action_selected':('contact',),                           'contact_form':form, 'message':msg})      return render_to_response('chimere/contactus.html', response_dct,                                context_instance=RequestContext(request)) -def extraPage(request, map_name="", page_id="", actions=default_actions): +def extraPage(request, area_name="", page_id=""):      """      Extra dynamic pages      """ @@ -558,10 +527,10 @@ def extraPage(request, map_name="", page_id="", actions=default_actions):          page = Page.objects.get(available=True, mnemonic=page_id)      except ObjectDoesNotExist:          return redirect(reverse('chimere:index')) -    response_dct, redir = get_base_response(request, map_name) +    response_dct, redir = get_base_response(request, area_name)      if redir:          return redir -    response_dct.update({'actions':actions(request.user, response_dct['map_name']), +    response_dct.update({'actions':actions(response_dct['area_name']),                           'action_selected':(page_id,),                           'content':page.content,                           'title':page.title}) @@ -570,7 +539,7 @@ def extraPage(request, map_name="", page_id="", actions=default_actions):      return render_to_response(tpl, response_dct,                                context_instance=RequestContext(request)) -def getDetail(request, map_name, marker_id): +def getDetail(request, area_name, marker_id):      '''      Get the detail for a marker      ''' @@ -579,7 +548,7 @@ def getDetail(request, map_name, marker_id):                                         status__in=['A', 'S'])[0]      except (ValueError, IndexError):          return HttpResponse('no results') -    response_dct, redir = get_base_response(request, map_name) +    response_dct, redir = get_base_response(request, area_name)      if redir:          return redir      response_dct['marker'] = marker @@ -587,7 +556,7 @@ def getDetail(request, map_name, marker_id):          if 'simple' in request.GET and request.GET['simple']:              response_dct['simple'] = True      response_dct['share_networks'], net_dct = \ -                   getShareNetwork(request, response_dct['map_name'], marker) +                   getShareNetwork(request, response_dct['area_name'], marker)      response_dct['share_url'] = net_dct['url']      net_dct['to'] = settings.CONTACT_EMAIL      if net_dct['to']: @@ -602,7 +571,7 @@ def getDetail(request, map_name, marker_id):      return render_to_response('chimere/detail.html', response_dct,                                context_instance=RequestContext(request)) -def getDescriptionDetail(request, map_name, category_id): +def getDescriptionDetail(request, area_name, category_id):      '''      Get the description for a category      ''' @@ -610,7 +579,7 @@ def getDescriptionDetail(request, map_name, category_id):          category = Category.objects.filter(id=int(category_id))[0]      except (ValueError, IndexError):          return HttpResponse('no results') -    response_dct, redir = get_base_response(request, map_name) +    response_dct, redir = get_base_response(request, area_name)      if redir:          return redir      response_dct['category'] = category @@ -632,82 +601,87 @@ def checkDate(q):              )      return q -def getGeoObjects(request, map_name, category_ids, status): +def _getGeoObjects(area_name, category_ids, status='A', getjson=True, +                   item_types=('Marker', 'Route')): +    ''' +    Get markers and routes +    ''' +    items = [] +    current_cat, colors, idx = None, None, 0 +    empty = [] if not getjson else {} + +    # marker +    if 'Marker' in item_types: +        try: +            q = checkDate(Q(status__in=status, categories__in=category_ids)) +            query = Marker.objects.filter(q).distinct('pk').order_by('-pk') +        except: +            return empty + +        category_ids = [int(cat_id) for cat_id in category_ids] +        if getjson: +            for geo_object in list(query): +                items += json.loads(geo_object.getGeoJSON(category_ids)) +        else: +            items += list(query) + +    # routes +    if 'Route' in item_types: +        query = AggregatedRoute.objects.filter(status__in=status, +                      subcategory__in=category_ids).order_by('subcategory', '-pk') +        if getjson: +            for route in query.all(): +                c_cat = route.subcategory +                if not current_cat or current_cat != c_cat: +                    idx = 0 +                    current_cat = c_cat +                    colors = list(Color.objects.filter( +                                            color_theme=c_cat.color_theme)) +                if colors: +                    items.append(json.loads( +                        route.getGeoJSON(color=colors[idx % len(colors)].code))) +                else: +                    items.append(json.loads(route.getGeoJSON(color='000'))) +                idx += 1 +        else: +            items += list(query) + +    if not items: +        return empty +    return items + +def getGeoObjects(request, area_name, category_ids, status):      '''      Get the JSON for markers and routes      '''      if not status:          status = 'A'      status = status.split('_') -    category_ids = category_ids.split('_') -    query = AggregatedRoute.objects.filter(status__in=status, -                  subcategory__in=category_ids).order_by('subcategory') -    jsons = [] -    current_cat, colors, idx = None, None, 0 -    for route in query.all(): -        c_cat = route.subcategory -        if not current_cat or current_cat != c_cat: -            idx = 0 -            current_cat = c_cat -            colors = list(Color.objects.filter(color_theme = c_cat.color_theme)) -        color = '000' -        if colors: -            color = colors[idx % len(colors)].code -        if '#' not in color: -            color  = '#' + color -        base_dct = {"type":"Feature", -                    "properties":{ -                        "color":color -                    } -                   } -        jsons.append(route._getItems(base_dct)) -        idx += 1 -    try: -        q = checkDate(Q(status__in=status, categories__in=category_ids)) -        query = Marker.objects.filter(q).distinct('pk').order_by('pk') -    except: -        return HttpResponse('no results') -    category_ids = [int(cat_id) for cat_id in category_ids] -    for category_id in category_ids: -        if not category_id: -            continue -        cat = SubCategory.objects.get(pk=category_id) -        base_dct = {"type":"Feature", -                    "properties":{ -                        "icon_path":unicode(cat.icon.image), -                        "icon_hover_path":cat.hover_icon.image \ -                                       if cat.hover_icon else '', -                        "icon_width":cat.icon.image.width, -                        'icon_height':cat.icon.image.height, -                        'category_name':cat.name} -                    } -        for values in query.filter(categories__pk=category_id).values( -                                   'point', 'pk', 'name', 'weight'): -            jsons.append(Marker._getJson(values, copy.deepcopy(base_dct))) +    category_ids = unicode(category_ids).split('_') + +    jsons = _getGeoObjects(area_name, category_ids, status)      if not jsons:          return HttpResponse('no results') -    data = {"type": "FeatureCollection", "features":jsons} -    data = json.dumps(data) - +    data = json.dumps({"type": "FeatureCollection", "features":jsons})      return HttpResponse(data, content_type="application/json") -def getMarker(request, map_name, pk): +def getMarker(request, area_name, pk):      q = Marker.objects.filter(pk=pk, status='A')      if not q.count():          return HttpResponse('{}')      data = q.all()[0].getGeoJSON()      return HttpResponse(data, content_type="application/json") -def get_all_categories(request, map_name=None): +def get_all_categories(request, area_name=None):      '''      Get all available categories in JSON      ''' -    context_data, redir = get_base_response(request, map_name) -    map = context_data["map"] +    context_data, redir = get_base_response(request, area_name) +    area = context_data["area"]      subcategories = [] -    if map: -        subcategories = list(map.getCategories('A', -                                   map_name=context_data['map_name'])) +    if area: +        subcategories = list(area.getCategories('A', +                                   area_name=context_data['area_name']))      else:          categories = SubCategory.getAvailable()          for cat, subcats in categories: @@ -716,25 +690,25 @@ def get_all_categories(request, map_name=None):      jsons = json.dumps({'categories':subcats})      return HttpResponse(jsons) -def get_available_categories(request, map_name=None, map=None, status='A', +def get_available_categories(request, area_name=None, area=None, status='A',                               force=None):      ''' -    Get category menu for a designed map +    Get category menu for a designed area      ''' -    context_data, redir = get_base_response(request, map_name) -    map = context_data["map"] +    context_data, redir = get_base_response(request, area_name) +    area = context_data["area"]      if redir:          return redir -    if map and map.dynamic_categories and \ +    if area and area.dynamic_categories and \         not "current_extent" in request.GET:          context_data['sub_categories'] = []          return render_to_response('chimere/blocks/categories.html', context_data,                                         context_instance=RequestContext(request)) -    if not map or not map.dynamic_categories: +    if not area or not area.dynamic_categories:          # Categories are not updated dynamicaly when the user move the map          # so we return ALL the categories          subcategories = SubCategory.getAvailable( -                                            map_name=context_data['map_name']) +                                            area_name=context_data['area_name'])          context_data['sub_categories'] = subcategories          return render_to_response('chimere/blocks/categories.html', context_data,                                         context_instance=RequestContext(request)) @@ -746,12 +720,12 @@ def get_available_categories(request, map_name=None, map=None, status='A',          status = status.split('_')          current_extent = request.GET["current_extent"].replace('M', '-')\                                                        .replace('D', '.') -        map = SimpleArea([float(pt) for pt in current_extent.split('_')]) +        area = SimpleArea([float(pt) for pt in current_extent.split('_')])      except:          # bad extent format          return HttpResponse(default_message) -    # if not force and map.isIn(SimpleArea(cookie.AREA):return -    categories = map.getCategories(status, map_name=context_data['map_name']) +    # if not force and area.isIn(SimpleArea(cookie.AREA):return +    categories = area.getCategories(status, area_name=context_data['area_name'])      if not categories:          return HttpResponse(default_message)      get_cat = lambda subcat: subcat.category @@ -764,7 +738,7 @@ def get_available_categories(request, map_name=None, map=None, status='A',      return render_to_response('chimere/blocks/categories.html', context_data,                                         context_instance=RequestContext(request)) -def getCategory(request, map_name='', category_id=0): +def getCategory(request, area_name='', category_id=0):      '''      Get the JSON for a category (mainly in order to get the description)      ''' @@ -774,7 +748,7 @@ def getCategory(request, map_name='', category_id=0):          return HttpResponse('no results')      return HttpResponse(category.getJSON()) -def getTinyfiedUrl(request, parameters, map_name=''): +def getTinyfiedUrl(request, parameters, area_name=''):      '''      Get the tinyfied version of parameters      ''' @@ -783,11 +757,11 @@ def getTinyfiedUrl(request, parameters, map_name=''):          urn = TinyUrl.getUrnByParameters(parameters)      except:          return {} -    response_dct, redir = get_base_response(request, map_name) +    response_dct, redir = get_base_response(request, area_name)      if redir:          return redir -    url = reverse('chimere:tiny', args=[(response_dct['map_name'] \ -                         if response_dct['map_name'] else '') + '/', urn]) +    url = reverse('chimere:tiny', args=[(response_dct['area_name'] \ +                         if response_dct['area_name'] else '') + '/', urn])      if not url.startswith('http'):          url = get_base_uri(request) + url      url = re.sub("([^:])\/\/", "\g<1>/", url) @@ -804,17 +778,89 @@ def getTinyfiedUrl(request, parameters, map_name=''):      data["text"] = urlquote(text)      return data -def redirectFromTinyURN(request, map_name='', tiny_urn=''): +def redirectFromTinyURN(request, area_name='', tiny_urn=''):      """      Redirect from a tiny Urn      """      parameters = '?' + TinyUrl.getParametersByUrn(tiny_urn) -    response_dct, redir = get_base_response(request, map_name) +    response_dct, redir = get_base_response(request, area_name)      if redir:          return redir      return HttpResponseRedirect(response_dct['extra_url'] + parameters) -def route(request, map_name, lon1, lat1, lonlat_steps, lon2, lat2, +class CategoryDirectoryView(ListView): +    template_name = "chimere/category_directory.html" + +    def get_queryset(self): +        self.area_name = self.kwargs.get('area_name', None) +        if self.area_name: +            self.area_name = self.area_name.split('/')[0] +            area = get_object_or_404(Area, urn=self.area_name, available=True) +            q = area.subcategories.filter(available=True, +                                             category__available=True +                         ).order_by('category__order', 'category__id', 'order') +            if q.count(): +                return q +        return SubCategory.objects.filter(available=True, +                                              category__available=True +                         ).order_by('category__order', 'category__id', 'order') + +    def get_context_data(self, *args, **kwargs): +        context = super(CategoryDirectoryView, self).get_context_data( +                                                        *args, **kwargs) +        new_context, redirect = get_base_response(self.request, self.area_name) +        context.update(new_context) +        context.update({ +            'actions':actions(self.area_name), +            'action_selected':('categories',), +        }) +        return context + +class CategoryView(TemplateView): +    template_name = "chimere/category_directory_detail.html" + +    def get_geo_items(self): +        # TODO: simplify on v2.3 when slug are available +        category_slug = self.kwargs.get('category_slug') +        self.area_name = self.kwargs.get('area_name', None) +        q = None +        if self.area_name: +            self.area_name = self.area_name.split('/')[0] +            area = get_object_or_404(Area, urn=self.area_name, available=True) +            q = area.subcategories.filter(available=True, +                                          category__available=True) +            if not q.count(): +                q = None +        if not q: +            q = SubCategory.objects.filter(available=True, +                                           category__available=True) +        self.category = None +        for subcat in q: +            if defaultfilters.slugify(subcat.name) == category_slug: +                self.category = subcat +                break +        if not self.category: +            raise Http404(_("Category does not exist")) + +        items = _getGeoObjects(self.area_name, [unicode(self.category.pk)], +                               getjson=False, item_types=('Marker',)) +        return items + +    def get_context_data(self, *args, **kwargs): +        context = super(CategoryView, self).get_context_data( +                                                        *args, **kwargs) +        self.items = self.get_geo_items() +        new_context, redirect = get_base_response(self.request, self.area_name) +        context.update(new_context) +        context.update({ +            'actions':actions(self.area_name), +            'action_selected':('categories',), +            'category':self.category, +            'items':self.items +        }) +        return context + +def route(request, area_name, lon1, lat1, lonlat_steps, lon2, lat2,            transport='foot', speed=''):      '''      Get the JSON for a route @@ -893,18 +939,14 @@ def route(request, map_name, lon1, lat1, lonlat_steps, lon2, lat2,              message)      return HttpResponse(data) -def get_json(request, map_name='', app_name='', filename=''): -    return HttpResponse(open(settings.STATIC_ROOT+app_name+'/json/'+filename+'.json'), -                        'application/javascript', status=200) - -def rss(request, map_name='', actions=default_actions): +def rss(request, area_name=''):      '''      Redirect to RSS subscription page      ''' -    response_dct, redir = get_base_response(request, map_name) +    response_dct, redir = get_base_response(request, area_name)      if redir:          return redir -    response_dct.update({'actions':actions(request.user, response_dct['map_name']), +    response_dct.update({'actions':actions(response_dct['area_name']),                           'action_selected':('rss',),                           'category_rss_feed':'',})      # If the form has been submited @@ -926,14 +968,14 @@ def rss(request, map_name='', actions=default_actions):              # User wants to follow all the new POI situated in a defined area              elif request.POST['rss_category'] == 'area':                  # An unbound form -                form = MapForm() +                form = AreaForm()                  area_widget = AreaWidget().render('area', None)                  response_dct.update({                      'map_layer':settings.CHIMERE_DEFAULT_MAP_LAYER,                      'extra_head':form.media,                      'form':form,                      'category_rss_feed':'area', -                    'map_id':Map.getAvailable(), +                    'area_id':Area.getAvailable(),                      'area_widget':area_widget                  })                  return render_to_response('chimere/feeds/rss.html', @@ -964,10 +1006,10 @@ def rss(request, map_name='', actions=default_actions):                                       kwargs={'category_id':cat_id})                  return redirect(feeds_link) -        # User has specified the ID of the map he wants to follow -        if 'id_map' in request.POST and request.POST['id_map'] != '': -            feeds_link = reverse('chimere:feeds-mapid', -                                 kwargs={'map_id':request.POST['id_map']}) +        # User has specified the ID of the area he wants to follow +        if 'id_area' in request.POST and request.POST['id_area'] != '': +            feeds_link = reverse('chimere:feeds-areaid', +                                 kwargs={'area_id':request.POST['id_area']})              return redirect(feeds_link)          # User has specified the area  he wants to follow => we redirect him @@ -1002,12 +1044,12 @@ def rss(request, map_name='', actions=default_actions):                                        context_instance=RequestContext(request))          if request.GET['rss_category'] == 'area':              # An unbound form -            form = MapForm() +            form = AreaForm()              response_dct.update({'map_layer':settings.MAP_LAYER,                              'extra_head':form.media,                              'form':form,                              'category_rss_feed':'area', -                            'map_id':Map.getAvailable(), +                            'area_id':Area.getAvailable(),                              'area_widget':AreaWidget().render('area', None)})              return render_to_response('chimere/feeds/rss.html', response_dct,                                        context_instance=RequestContext(request)) @@ -1026,7 +1068,11 @@ if hasattr(settings, 'CHIMERE_SEARCH_ENGINE') \      from haystack.views import SearchView as HaystackSearchView      from haystack.query import SearchQuerySet      class SearchView(HaystackSearchView): -        pass +        def extra_context(self, *args, **kwargs): +            context = super(SearchView, self).extra_context(*args, **kwargs) +            context["autocomplete"] = settings.HAYSTACK_AUTOCOMPLETE \ +                    if hasattr(settings, 'HAYSTACK_AUTOCOMPLETE') else False +            return context      def autocomplete(request):          sqs = SearchQuerySet().autocomplete(                                  content_auto=request.GET.get('q', ''))[:5]  | 
