diff options
| -rw-r--r-- | chimere/admin.py | 42 | ||||
| -rw-r--r-- | chimere/fixtures/initial_data.json | 44 | ||||
| -rw-r--r-- | chimere/forms.py | 3 | ||||
| -rw-r--r-- | chimere/models.py | 111 | ||||
| -rw-r--r-- | chimere/templates/chimere/detail.html | 17 | ||||
| -rw-r--r-- | chimere/views.py | 3 | 
6 files changed, 168 insertions, 52 deletions
| diff --git a/chimere/admin.py b/chimere/admin.py index 42835a2..7663bd5 100644 --- a/chimere/admin.py +++ b/chimere/admin.py @@ -25,6 +25,7 @@ import datetime  from django import forms  from django.conf import settings  from django.contrib import admin +from django.db.models import Q  from django.http import HttpResponse  from django.shortcuts import render_to_response  from django.utils.translation import ugettext_lazy as _ @@ -38,25 +39,13 @@ from chimere.forms import MarkerAdminForm, RouteAdminForm, AreaAdminForm,\                            NewsAdminForm, CategoryAdminForm, ImporterAdminForm, \                            PictureFileAdminForm, MultimediaFileAdminForm  from chimere.models import Category, Icon, SubCategory, Marker, \ -     PropertyModel, News, Route, Area, ColorTheme, Color, MultimediaType, \ -     MultimediaFile, PictureFile, Importer, Layer, AreaLayers +     PropertyModel, News, Route, Area, ColorTheme, Color, \ +     MultimediaFile, PictureFile, Importer, Layer, AreaLayers,\ +     get_areas_for_user, get_users_by_area  from chimere.utils import unicode_normalize, ShapefileManager, KMLManager,\                            CSVManager  from chimere.widgets import TextareaWidget -def get_areas_for_user(user): -    """ -    Getting subcats for a specific user -    """ -    perms = user.get_all_permissions() -    areas = set() -    prefix = 'chimere.change_area_' -    for perm in perms: -        if perm.startswith(prefix): -            area = Area.objects.get(urn=perm[len(prefix):]) -            areas.add(area) -    return areas -  def validate(modeladmin, request, queryset):      for item in queryset:          item.status = 'A' @@ -131,13 +120,14 @@ class MarkerAdmin(admin.ModelAdmin):          qs = self.model._default_manager.get_query_set()          if not request.user.is_superuser:              areas = get_areas_for_user(request.user) -            if areas: -                in_areas = " or ".join([area.getIncludeSql() for area in areas]) -                qs = qs.extra(where=[in_areas]) +            contained = Q() +            for area in areas: +                contained = contained | area.getIncludeMarker() +            qs = qs.filter(contained)          ordering = self.ordering or ()          if ordering:              qs = qs.order_by(*ordering) -        return qs +        return qs.distinct()  class RouteAdmin(admin.ModelAdmin):      """ @@ -155,10 +145,10 @@ class RouteAdmin(admin.ModelAdmin):          qs = self.model._default_manager.get_query_set()          if not request.user.is_superuser:              areas = get_areas_for_user(request.user) -            if areas: -                in_areas = " or ".join([area.getIncludeSql( -                           geometry='"chimere_route".route') for area in areas]) -                qs = qs.extra(where=[in_areas]) +            contained = Q() +            for area in areas: +                contained = contained | area.getIncludeRoute() +            qs = qs.filter(contained)          ordering = self.ordering or ()          if ordering:              qs = qs.order_by(*ordering) @@ -240,11 +230,6 @@ class ColorThemeAdmin(admin.ModelAdmin):  class IconAdmin(admin.ModelAdmin):      exclude = ['height', 'width'] -class MultimediaTypeAdmin(admin.ModelAdmin): -    search_fields = ("name",) -    list_display = ('name', 'media_type', 'mime_type', 'iframe', 'available') -    list_filter = ('media_type', 'available') -  # register of differents database fields  admin.site.register(News, NewsAdmin)  admin.site.register(Category, CategoryAdmin) @@ -254,5 +239,4 @@ admin.site.register(Route, RouteAdmin)  admin.site.register(PropertyModel)  admin.site.register(Area, AreaAdmin)  admin.site.register(ColorTheme, ColorThemeAdmin) -admin.site.register(MultimediaType, MultimediaTypeAdmin)  admin.site.register(Layer) diff --git a/chimere/fixtures/initial_data.json b/chimere/fixtures/initial_data.json index 473640c..21ba13c 100644 --- a/chimere/fixtures/initial_data.json +++ b/chimere/fixtures/initial_data.json @@ -195,5 +195,49 @@              "layer_code": "new OpenLayers.Layer.MapQuestOSM()",              "name": "OSM - MapQuest"          } +    }, +    { +        "pk": 1, +        "model": "auth.group", +        "fields": { +            "name": "Application administrator", +            "permissions": [ +                67, +                68, +                40, +                41, +                42, +                37, +                38, +                39, +                34, +                35, +                36, +                43, +                44, +                45, +                49, +                50, +                51, +                55, +                56, +                57, +                28, +                29, +                30, +                58, +                59, +                60, +                64, +                65, +                66, +                61, +                62, +                63, +                46, +                47, +                48 +            ] +        }      }  ] diff --git a/chimere/forms.py b/chimere/forms.py index ea08474..bb31ffe 100644 --- a/chimere/forms.py +++ b/chimere/forms.py @@ -433,7 +433,8 @@ class AreaAdminForm(forms.ModelForm):      Admin page to create an area      """      area = AreaField(label=_("Area"), fields=(PointField(), PointField())) -    welcome_message = forms.CharField(widget=TextareaAdminWidget) +    welcome_message = forms.CharField(widget=TextareaAdminWidget, +                                      required=False)      class Meta:          model = Area diff --git a/chimere/models.py b/chimere/models.py index 593d712..88c1f0c 100644 --- a/chimere/models.py +++ b/chimere/models.py @@ -25,16 +25,16 @@ import simplejson as json  from lxml import etree  from PIL import Image  from subprocess import Popen, PIPE -  from django import forms  from django.conf import settings  from django.contrib import admin -from django.contrib.auth.models import Permission, ContentType +from django.contrib.auth.models import User, Permission, ContentType, Group  from django.contrib.gis.db import models  from django.contrib.gis.gdal import SpatialReference  from django.core.files import File  from django.core.exceptions import ValidationError, ObjectDoesNotExist  from django.core.urlresolvers import reverse +from django.db.models import Q  from django.db.models.signals import post_save, pre_save, m2m_changed  from django.template import defaultfilters  from django.utils.translation import ugettext_lazy as _ @@ -513,6 +513,12 @@ class Marker(GeographicItem):          url = reverse('chimere:tiny', args=[area_name, urn])          return url + +PRE_ATTRS = { +    'Marker':('name', 'geometry', 'import_version'), +    'Route':('name', 'geometry', 'import_version'), +    'Area':('urn', 'name'), +    }  def geometry_pre_save(cls, pre_save_geom_values):      def geom_pre_save(sender, **kwargs):          if not kwargs['instance'] or not kwargs['instance'].pk: @@ -520,8 +526,8 @@ def geometry_pre_save(cls, pre_save_geom_values):          instance = kwargs['instance']          try:              instance = cls.objects.get(pk=instance.pk) -            pre_save_geom_values[instance.pk] = (instance.name, -                              instance.geometry, instance.import_version) +            pre_save_geom_values[instance.pk] = [getattr(instance, attr) +                                            for attr in PRE_ATTRS[cls.__name__]]          except ObjectDoesNotExist:              pass      return geom_pre_save @@ -836,7 +842,7 @@ class Route(GeographicItem):                            null=True, height_field='height', width_field='width')      height = models.IntegerField(_(u"Height"), blank=True, null=True)      width = models.IntegerField(_(u"Width"), blank=True, null=True) -    objects = BaseGeoManager() +    objects = models.GeoManager()      def __unicode__(self):          return self.name @@ -1139,20 +1145,34 @@ class Area(models.Model, SimpleArea):          '''          return cls.objects.filter(available=True) -    def getIncludeSql(self, geometry='"chimere_marker".point'): -        """ -        Get the sql statement for the test if the point is included in the area -        """ -        area = "ST_GeometryFromText('POLYGON((%f %f,%f %f,%f %f,%f %f, %f %f"\ -               "))', %d)" % (self.upper_left_corner.x, self.upper_left_corner.y, +    def getWkt(self): +        return "SRID=%d;POLYGON((%f %f,%f %f,%f %f,%f %f, %f %f))" % ( +          settings.CHIMERE_EPSG_DISPLAY_PROJECTION, +          self.upper_left_corner.x, self.upper_left_corner.y,            self.lower_right_corner.x, self.upper_left_corner.y,            self.lower_right_corner.x, self.lower_right_corner.y,            self.upper_left_corner.x, self.lower_right_corner.y,            self.upper_left_corner.x, self.upper_left_corner.y, -          settings.CHIMERE_EPSG_DISPLAY_PROJECTION            ) -        sql = "ST_Contains(" + area + ", " + geometry + ")" -        return sql + +    def getIncludeMarker(self): +        """ +        Get the sql statement for the test if the point is included in the area +        """ +        return Q(point__contained=self.getWkt()) + +    def getIncludeRoute(self): +        """ +        Get the sql statement for the test if the route is included in the area +        """ +        return Q(route__contained=self.getWkt()) + +pre_save_area_values = {} +def area_pre_save(sender, **kwargs): +    if not kwargs['instance']: +        return +    geometry_pre_save(Area, pre_save_area_values)(sender, **kwargs) +pre_save.connect(area_pre_save, sender=Area)  def area_post_save(sender, **kwargs):      if not kwargs['instance']: @@ -1163,21 +1183,82 @@ def area_post_save(sender, **kwargs):          for default in defaults:              default.default = False              default.save() +    # manage permissions +    old_urn, old_name = area.urn, area.name +    if area.pk in pre_save_area_values: +        old_urn, old_name = pre_save_area_values[area.pk] +    perm, old_groups, old_users = None, [], [] +    if area.urn != old_urn: +        oldmnemo = 'change_area_' + old_urn +        old_perm = Permission.objects.filter(codename=oldmnemo) +        if old_perm.count(): +            perm = old_perm.all()[0] +            perm.codename = 'change_area_' + area.urn +            perm.save()      if not area.urn:          area.urn = defaultfilters.slugify(area.name)          area.save()      mnemo = 'change_area_' + area.urn      perm = Permission.objects.filter(codename=mnemo) +    lbl = "Can change " + area.name      if not perm.count(): -        lbl = "Can change " + area.name          content_type = ContentType.objects.get(app_label="chimere",                                                 model="area")          perm = Permission(name=lbl, content_type_id=content_type.id,                            codename=mnemo)          perm.save() +    else: +        perm = perm.all()[0] +        if old_name != area.name: +            perm.name = lbl +            perm.save() +    # manage moderation group +    groupname = area.name + " moderation" +    if old_name != area.name: +        old_groupname = old_name + " moderation" +        old_gp = Group.objects.filter(name=old_groupname) +        if old_gp.count(): +            old_gp = old_gp.all()[0] +            old_gp.name = groupname +            old_gp.save() +    group = Group.objects.filter(name=groupname) +    if not group.count(): +        group = Group.objects.create(name=groupname) +        group.permissions.add(perm) +        for app_label, model in (('chimere', 'marker'), +                                 ('chimere', 'route'), +                                 ('chimere', 'multimediafile'), +                                 ('chimere', 'picturefile'), +                                 ('chimere', 'routefile')): +            ct = ContentType.objects.get(app_label=app_label, model=model) +            for p in Permission.objects.filter(content_type=ct).all(): +                group.permissions.add(p)  post_save.connect(area_post_save, sender=Area) +def get_areas_for_user(user): +    """ +    Getting subcats for a specific user +    """ +    perms = user.get_all_permissions() +    areas = set() +    prefix = 'chimere.change_area_' +    for perm in perms: +        if perm.startswith(prefix): +            try: +                area = Area.objects.get(urn=perm[len(prefix):]) +                areas.add(area) +            except ObjectDoesNotExist: +                pass +    return areas + +def get_users_by_area(area): +    if not area: +        return [] +    perm = 'change_area_'+area.urn +    return User.objects.filter(Q(groups__permissions__codename=perm)| +                                Q(user_permissions__codename=perm)).all() +  class AreaLayers(models.Model):      area = models.ForeignKey(Area)      layer = models.ForeignKey(Layer) diff --git a/chimere/templates/chimere/detail.html b/chimere/templates/chimere/detail.html index 7cf678e..c195fbe 100644 --- a/chimere/templates/chimere/detail.html +++ b/chimere/templates/chimere/detail.html @@ -27,7 +27,17 @@      {% if marker.multimedia_items %}      <a href='#' id='show_gallery_link'>{% trans "Show multimedia gallery" %}</a>      {% endif %} -    </div>{% if share_networks %} +    </div> +    {% comment %} +    <a href='{% if marker.route %}{% url chimere:editroute-item area_name_slash|default_if_none:"" marker.route.pk "" %}{%else%}{% url chimere:edit-item area_name_slash|default_if_none:"" marker.pk "" %}{%endif%}'> +        {% trans "Submit a modification" %} +    </a> +    {% endcomment %} +    {% if moderator_emails %} +    <a href="mailto:?from={{moderator_emails}}&subject={% trans "Propose amendment" %}&body={% trans "I would like to propose an amendment for this item:"%} {{share_url}}"> +        {% trans "Propose amendment" %} +    </a>{%endif%} +    {% if share_networks %}      {% if simple %}{% trans "Share on"%}{% for share_network in share_networks %}      <a href='{{share_network.1}}'>{{share_network.0}}</a>      {% endfor %}{%else%} @@ -35,11 +45,6 @@          <li>{% trans "Share"%}</li>{% for share_network in share_networks %}          <li><a href='{{share_network.1}}'><img src="{{share_network.2}}" alt="{{share_network.0}}"/></a></li>      {% endfor %}</ul>{% endif %} -    {% comment %} -    <a href='{% if marker.route %}{% url chimere:editroute-item area_name_slash|default_if_none:"" marker.route.pk "" %}{%else%}{% url chimere:edit-item area_name_slash|default_if_none:"" marker.pk "" %}{%endif%}'> -        {% trans "Submit a modification" %} -    </a> -    {% endcomment %}  {% endif %}  </div>  {% if marker.multimedia_items %} diff --git a/chimere/views.py b/chimere/views.py index f96a66b..567840e 100644 --- a/chimere/views.py +++ b/chimere/views.py @@ -42,7 +42,8 @@ from django.utils.translation import ugettext as _  from chimere.actions import actions  from chimere.models import Category, SubCategory, PropertyModel, \ -              Marker, Route, News, SimpleArea, Area, Color, TinyUrl, RouteFile +     Marker, Route, News, SimpleArea, Area, Color, TinyUrl, RouteFile, \ +     get_users_by_area  from chimere.widgets import getMapJS, PointChooserWidget, \                              RouteChooserWidget, AreaWidget | 
