summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--chimere/admin.py35
-rw-r--r--chimere/forms.py253
-rw-r--r--chimere/search_indexes.py4
-rw-r--r--chimere/templates/search/indexes/chimere/marker_text.txt2
-rw-r--r--chimere/tests.py38
5 files changed, 248 insertions, 84 deletions
diff --git a/chimere/admin.py b/chimere/admin.py
index fb3b15c..686a656 100644
--- a/chimere/admin.py
+++ b/chimere/admin.py
@@ -186,12 +186,14 @@ class PictureInline(admin.TabularInline):
readonly_fields = ('height', 'width')
exclude = ('thumbnailfile', 'thumbnailfile_height', 'thumbnailfile_width')
+
class MultimediaInline(admin.TabularInline):
model = MultimediaFile
extra = 1
ordering = ('order',)
form = MultimediaFileAdminForm
+
class AreaMarkerListFilter(admin.SimpleListFilter):
title = _('area')
parameter_name = 'area'
@@ -206,6 +208,7 @@ class AreaMarkerListFilter(admin.SimpleListFilter):
return queryset
return queryset.filter(area.getIncludeMarker())
+
class AreaRouteListFilter(AreaMarkerListFilter):
def queryset(self, request, queryset):
try:
@@ -214,6 +217,7 @@ class AreaRouteListFilter(AreaMarkerListFilter):
return queryset
return queryset.filter(area.getIncludeRoute())
+
class HasCategoriesListFilter(SimpleListFilter):
title = _('Has categories')
parameter_name = 'has_category'
@@ -232,6 +236,24 @@ class HasCategoriesListFilter(SimpleListFilter):
return queryset
+class CategoriesListFilter(SimpleListFilter):
+ title = _('categories')
+ parameter_name = 'category'
+
+ def lookups(self, request, model_admin):
+ if request.user.subcategory_limit_to.count():
+ q = request.user.subcategory_limit_to
+ return [(l.subcategory.pk, unicode(l.subcategory))
+ for l in q.all()]
+ q = SubCategory.objects
+ return [(cat.pk, unicode(cat)) for cat in q.all()]
+
+ def queryset(self, request, queryset):
+ if self.value():
+ return queryset.filter(categories__pk=self.value())
+ return queryset
+
+
def moderator_right(user, qs, geo_type='marker'):
if user.is_superuser:
return qs
@@ -256,7 +278,7 @@ class MarkerAdmin(admin.ModelAdmin):
"""
search_fields = ("name",)
list_display = ('name', 'status', 'start_date', 'end_date')
- list_filter = ('status', AreaMarkerListFilter, 'categories',
+ list_filter = ('status', AreaMarkerListFilter, CategoriesListFilter,
HasCategoriesListFilter, 'start_date', 'end_date')
actions = [validate, disable, managed_modified, export_to_kml,
export_to_shapefile, export_to_csv]
@@ -325,6 +347,17 @@ class MarkerAdmin(admin.ModelAdmin):
)
return my_urls + urls
+ def get_form(self, request, obj=None, **kwargs):
+ form = super(MarkerAdmin, self).get_form(request, obj, **kwargs)
+ q = request.user.subcategory_limit_to
+ if not q.count():
+ return form
+ form = type('MarkerAdminLimit', (form,),
+ {'categories_choices': [
+ (l.subcategory.pk, unicode(l.subcategory))
+ for l in q.all()]})
+ return form
+
class RouteAdmin(MarkerAdmin):
"""
diff --git a/chimere/forms.py b/chimere/forms.py
index c8d7d45..2cfa0ed 100644
--- a/chimere/forms.py
+++ b/chimere/forms.py
@@ -23,30 +23,31 @@ Forms
from django import forms
from django.conf import settings
-from django.contrib.gis.db import models
from django.core.exceptions import ImproperlyConfigured
from django.core.urlresolvers import reverse
+from django.db.models import Q
from django.forms.formsets import formset_factory
from django.utils.translation import ugettext as _
from django.contrib.auth.models import User, Permission, ContentType
-from django.contrib.admin.widgets import AdminDateWidget
from django.core.mail import EmailMessage, BadHeaderError
-if hasattr(settings, 'CHIMERE_SEARCH_ENGINE') and settings.CHIMERE_SEARCH_ENGINE:
+if hasattr(settings, 'CHIMERE_SEARCH_ENGINE') and \
+ settings.CHIMERE_SEARCH_ENGINE:
from haystack.forms import SearchForm as HaystackSearchForm
-from chimere.models import Marker, Route, PropertyModel, Property, Area,\
- News, Category, SubCategory, RouteFile, MultimediaFile, MultimediaType, \
- PictureFile, Importer, PropertyModelChoice, IFRAME_LINKS, \
- MultimediaExtension, Page, IMPORTER_CHOICES
+from chimere.models import Marker, Route, PropertyModel, Area,\
+ News, Category, RouteFile, MultimediaFile, MultimediaType, \
+ PictureFile, Importer, PropertyModelChoice, Page, IMPORTER_CHOICES, \
+ get_areas_for_user, SubCategoryUserLimit
from chimere.widgets import AreaField, PointField, TextareaWidget, \
- FullTextareaWidget, DatePickerWidget, ButtonSelectWidget, NominatimWidget, \
+ FullTextareaWidget, DatePickerWidget, ButtonSelectWidget, NominatimWidget,\
TextareaAdminWidget, ImportFiltrWidget, ImporterChoicesWidget, RE_XAPI
from datetime import timedelta, datetime, tzinfo
ZERO = timedelta(0)
+
class UTC(tzinfo):
"""UTC time zone"""
@@ -59,15 +60,51 @@ class UTC(tzinfo):
def dst(self, dt):
return ZERO
+
def getStaffEmails():
- return [u.email for u in
- User.objects.filter(is_staff=True).exclude(email="").order_by('id')]
+ return [u.email for u in User.objects.filter(
+ is_superuser=True).exclude(email="").order_by('id')]
+
+
+def getRelevantModeratorEmails(geo_object):
+ categories = list(geo_object.categories.all())
+ # q = Q(is_staff=True) & (
+ # Q(subcategory_limit_to__count=0) |
+ # Q(subcategory_limit_to__subcategory__in=categories))
+ q1 = Q(is_staff=True) & (
+ Q(subcategory_limit_to__subcategory__in=categories))
+ qusers = list(User.objects.filter(q1).exclude(email="").all())
+ q2 = Q(is_staff=True)
+ qusers += list(User.objects.filter(q2).exclude(
+ email="").exclude(pk__in=[
+ sl.user.pk for sl in SubCategoryUserLimit.objects.all()]).all())
+ users = []
+ for user in qusers:
+ areas = get_areas_for_user(user)
+ if not areas:
+ users.append(user)
+ continue
+ contained = Q()
+ qs = geo_object.__class__.objects.filter(pk=geo_object.pk)
+ for area in areas:
+ if hasattr(geo_object, 'point'):
+ contained = contained | area.getIncludeMarker()
+ elif hasattr(geo_object, 'route'):
+ contained = contained | area.getIncludeRoute()
+ qs = qs.filter(contained)
+ if qs.count():
+ users.append(user)
+ lst = [u.email for u in users]
+ return lst
+
def notifyStaff(subject, body, sender=None):
- if not settings.EMAIL_HOST:
- return
user_list = getStaffEmails()
- if not user_list:
+ notifyByEmail(subject, body, user_list, sender)
+
+
+def notifyByEmail(subject, body, user_list, sender=None):
+ if not settings.EMAIL_HOST or not user_list:
return
if settings.PROJECT_NAME:
subject = u'[%s] %s' % (settings.PROJECT_NAME, subject)
@@ -82,16 +119,23 @@ def notifyStaff(subject, body, sender=None):
return False
return True
+
def notifySubmission(absolute_uri, geo_object):
- category = u" - ".join([unicode(cat) for cat in geo_object.categories.all()])
+ category = u" - ".join([unicode(cat)
+ for cat in geo_object.categories.all()])
subject = u'%s %s' % (_(u"New submission for"), category)
message = _(u'The new item "%s" has been submited in the category: ') % \
- geo_object.name + category
+ geo_object.name + category
message += "\n\n" + _(u"To valid, precise or unvalid this item: ")
- named_url = 'admin:chimere_%s_change'% geo_object.__class__.__name__.lower()
+ named_url = 'admin:chimere_%s_change' % \
+ geo_object.__class__.__name__.lower()
message += absolute_uri + reverse(named_url, args=(geo_object.pk,))
message += u"\n\n--\nChimère"
- return notifyStaff(subject, message)
+
+ user_list = getStaffEmails() + getRelevantModeratorEmails(geo_object)
+ user_list = list(set(user_list))
+ return notifyByEmail(subject, message, user_list)
+
class ContactForm(forms.Form):
"""
@@ -100,20 +144,24 @@ class ContactForm(forms.Form):
email = forms.EmailField(label=_("Email (optional)"), required=False)
content = forms.CharField(label=_("Object"), widget=forms.Textarea)
+
class SubCategoryAdminForm(forms.ModelForm):
'''
Add a tinyMCE widget to fill description
'''
description = forms.CharField(widget=FullTextareaWidget, required=False)
+
class PageAdminForm(forms.ModelForm):
"""
Main form for extra pages
"""
content = forms.CharField(widget=FullTextareaWidget)
+
class Meta:
model = Page
+
class OSMForm(forms.Form):
"""
OSM export form
@@ -123,28 +171,34 @@ class OSMForm(forms.Form):
widget=forms.PasswordInput(render_value=False))
# API URL are hardcoded: the day the API change Chimère will need
# adaptations not only on this portion...
- api = forms.ChoiceField(label=_(u"API"),
- choices=(('', '--'),
- ('api06.dev.openstreetmap.org',
- _(u"Test API - %s") % 'api06.dev.openstreetmap.org'),
- ('api.openstreetmap.org/api',
- _(u"Main API - %s") % 'api.openstreetmap.org/api'),
- ))
+ api = forms.ChoiceField(
+ label=_(u"API"),
+ choices=(('', '--'),
+ ('api06.dev.openstreetmap.org',
+ _(u"Test API - %s") % 'api06.dev.openstreetmap.org'),
+ ('api.openstreetmap.org/api',
+ _(u"Main API - %s") % 'api.openstreetmap.org/api'),
+ ))
+
class NewsAdminForm(forms.ModelForm):
"""
Main form for news
"""
content = forms.CharField(widget=TextareaAdminWidget)
+
class Meta:
model = News
+
class ImporterAdminForm(forms.ModelForm):
filtr = forms.CharField(widget=ImportFiltrWidget, required=False)
- importer_type = forms.ChoiceField(widget=ImporterChoicesWidget,
- choices=[('', '--')]+list(IMPORTER_CHOICES))
+ importer_type = forms.ChoiceField(
+ widget=ImporterChoicesWidget,
+ choices=[('', '--')] + list(IMPORTER_CHOICES))
default_description = forms.CharField(widget=TextareaAdminWidget,
required=False)
+
class Meta:
model = Importer
widgets = {
@@ -159,15 +213,17 @@ class ImporterAdminForm(forms.ModelForm):
'''
if self.cleaned_data.get('importer_type') == 'OSM' and \
not self.cleaned_data.get('filtr'):
- raise forms.ValidationError(_(u"For OSM import you must be "\
- u"provide a filter. Select an area and node/way filter."))
+ raise forms.ValidationError(
+ _(u"For OSM import you must be provide a filter. Select an "
+ u"area and node/way filter."))
if self.cleaned_data.get('importer_type') == 'OSM' and \
not RE_XAPI.match(self.cleaned_data.get('filtr')):
- raise forms.ValidationError(_(u"For OSM import you must be "\
- u"provide a filter. Select an area and node/way filter."))
+ raise forms.ValidationError(
+ _(u"For OSM import you must be provide a filter. Select an "
+ u"area and node/way filter."))
if self.cleaned_data.get('importer_type') == 'SHP' and \
not self.cleaned_data.get('zipped'):
- raise forms.ValidationError(_(u"Shapefiles must be provided in a "\
+ raise forms.ValidationError(_(u"Shapefiles must be provided in a "
u"zipped archive."))
if self.cleaned_data.get('importer_type') not in ('XSLT', 'XXLT') and \
self.cleaned_data.get('source') and \
@@ -181,26 +237,31 @@ class ImporterAdminForm(forms.ModelForm):
u"\"source file\"."))
return self.cleaned_data
+
class CategoryAdminForm(forms.ModelForm):
"""
Main form for categories
"""
description = forms.CharField(widget=TextareaAdminWidget, required=False)
+
class Media:
js = list(settings.JQUERY_JS_URLS) + [
'%schimere/js/menu-sort.js' % settings.STATIC_URL,
]
css = {
- 'all': ('chimere/css/admin.css',)
+ 'all': ('chimere/css/admin.css',)
}
+
class Meta:
model = Category
+
class MarkerAdminFormBase(forms.ModelForm):
"""
Main form for marker
"""
description = forms.CharField(widget=TextareaAdminWidget, required=False)
+
class Meta:
model = Marker
@@ -213,7 +274,7 @@ class MarkerAdminFormBase(forms.ModelForm):
instance = keys['instance']
property_dct = {}
for pm in self.pms:
- property = instance.getProperty(pm)
+ property = instance.getProperty(pm)
if property:
property_dct[pm.getNamedId()] = property.value
if 'initial' in keys:
@@ -221,13 +282,15 @@ class MarkerAdminFormBase(forms.ModelForm):
else:
keys['initial'] = property_dct
subcategories = keys.pop('subcategories') \
- if 'subcategories' in keys else []
+ if 'subcategories' in keys else []
super(MarkerAdminFormBase, self).__init__(*args, **keys)
if settings.CHIMERE_DAYS_BEFORE_EVENT:
self.fields['start_date'].widget = DatePickerWidget()
self.fields['end_date'].widget = DatePickerWidget()
if subcategories:
self.fields['categories'].choices = subcategories
+ elif hasattr(self, 'categories_choices'):
+ self.fields['categories'].choices = self.categories_choices
def clean(self):
'''
@@ -250,11 +313,12 @@ class MarkerAdminFormBase(forms.ModelForm):
continue
pm_cats = pm.subcategories.all()
if not pm_cats or \
- [submited_cat for submited_cat in self.cleaned_data['categories']
- if submited_cat in pm_cats]:
+ [submited_cat for submited_cat in
+ self.cleaned_data['categories']
+ if submited_cat in pm_cats]:
msg = _(u"This field is mandatory for the selected categories")
self._errors[pm.getNamedId()] = self.error_class([msg])
- #raise forms.ValidationError()
+ # raise forms.ValidationError()
return self.cleaned_data
def save(self, *args, **keys):
@@ -270,13 +334,15 @@ class MarkerAdminFormBase(forms.ModelForm):
tzinfo=tz)
new_marker.save()
# save properties
- properties = dict([(k.split('_')[-1], self.cleaned_data[k]) \
- for k in self.cleaned_data.keys() if k.startswith('property_')])
+ properties = dict(
+ [(k.split('_')[-1], self.cleaned_data[k])
+ for k in self.cleaned_data.keys() if k.startswith('property_')])
new_marker.saveProperties(properties)
return new_marker
-# As we have dynamic fields, it's cleaner to make the class dynamic too
+
def get_properties(queryset):
+ # As we have dynamic fields, it's cleaner to make the class dynamic too
fields = {}
for prop in queryset:
key = "property_%d_%d" % (prop.order, prop.id)
@@ -284,22 +350,24 @@ def get_properties(queryset):
choices = PropertyModelChoice.objects.filter(propertymodel=prop,
available=True
).order_by('value')
- fields[key] = forms.ChoiceField(label=prop.name,
- choices=[('', '--')] + \
- [(choice.pk, unicode(choice))
- for choice in choices],
- required=False)
+ fields[key] = forms.ChoiceField(
+ label=prop.name, choices=[('', '--')] +
+ [(choice.pk, unicode(choice)) for choice in choices],
+ required=False)
else:
- fields[key] = forms.CharField(label=prop.name,
- widget=PropertyModel.TYPE_WIDGET[prop.type],
- required=False)
+ fields[key] = forms.CharField(
+ label=prop.name, widget=PropertyModel.TYPE_WIDGET[prop.type],
+ required=False)
return fields
# in admin all fields are displayed
-MarkerAdminForm = type("MarkerAdminForm", (MarkerAdminFormBase,),
- get_properties(PropertyModel.objects.all()))
-MarkerBaseForm = type("MarkerBaseForm", (MarkerAdminFormBase,),
- get_properties(PropertyModel.objects.filter(available=True)))
+MarkerAdminForm = type(
+ "MarkerAdminForm", (MarkerAdminFormBase,),
+ get_properties(PropertyModel.objects.all()))
+MarkerBaseForm = type(
+ "MarkerBaseForm", (MarkerAdminFormBase,),
+ get_properties(PropertyModel.objects.filter(available=True)))
+
class MarkerForm(MarkerBaseForm):
"""
@@ -309,6 +377,7 @@ class MarkerForm(MarkerBaseForm):
required=False)
description = forms.CharField(widget=TextareaWidget, required=False)
keywords = forms.CharField(max_length=200, required=False)
+
class Meta:
model = Marker
exclude = ('status',)
@@ -316,6 +385,7 @@ class MarkerForm(MarkerBaseForm):
'description': TextareaWidget(),
}
+
class RouteAdminForm(forms.ModelForm):
"""
Main form for route
@@ -331,7 +401,7 @@ class RouteAdminForm(forms.ModelForm):
instance = keys['instance']
property_dct = {}
for pm in PropertyModel.objects.filter(available=True):
- property = instance.getProperty(pm)
+ property = instance.getProperty(pm)
if property:
property_dct[pm.getNamedId()] = property.value
if 'initial' in keys:
@@ -339,7 +409,7 @@ class RouteAdminForm(forms.ModelForm):
else:
keys['initial'] = property_dct
subcategories = keys.pop('subcategories') \
- if 'subcategories' in keys else []
+ if 'subcategories' in keys else []
super(RouteAdminForm, self).__init__(*args, **keys)
if settings.CHIMERE_DAYS_BEFORE_EVENT:
self.fields['start_date'].widget = DatePickerWidget()
@@ -357,14 +427,17 @@ class RouteAdminForm(forms.ModelForm):
new_route.save()
return new_route
+
class RouteForm(RouteAdminForm):
"""
Form for the edit page
"""
description = forms.CharField(widget=TextareaWidget, required=False)
- point = forms.CharField(label=" ", required=False, widget=forms.HiddenInput)
- associated_file_id = forms.CharField(label=" ", required=False,
- widget=forms.HiddenInput)
+ point = forms.CharField(label=" ", required=False,
+ widget=forms.HiddenInput)
+ associated_file_id = forms.CharField(
+ label=" ", required=False, widget=forms.HiddenInput)
+
class Meta:
model = Route
exclude = ('status',)
@@ -374,11 +447,11 @@ class RouteForm(RouteAdminForm):
try:
marker = Marker.objects.get(route=kwargs['instance'])
kwargs['initial'] = {
- 'point':marker.point,
- 'description':marker.description}
+ 'point': marker.point,
+ 'description': marker.description}
property_dct = {}
for pm in PropertyModel.objects.filter(available=True):
- property = marker.getProperty(pm)
+ property = marker.getProperty(pm)
if property:
property_dct[pm.getNamedId()] = property.value
if 'initial' in kwargs:
@@ -413,11 +486,13 @@ class RouteForm(RouteAdminForm):
new_marker.description = self.cleaned_data['description']
new_marker.save()
# save properties
- properties = dict([(k.split('_')[-1], self.cleaned_data[k]) \
- for k in self.cleaned_data.keys() if k.startswith('property_')])
+ properties = dict(
+ [(k.split('_')[-1], self.cleaned_data[k])
+ for k in self.cleaned_data.keys() if k.startswith('property_')])
new_marker.saveProperties(properties)
return new_route
+
class BaseFileForm(forms.ModelForm):
id = forms.IntegerField(label=u"", widget=forms.HiddenInput(),
required=False)
@@ -435,7 +510,7 @@ class BaseFileForm(forms.ModelForm):
if self.cleaned_data.get('id'):
try:
instance = self._meta.model.objects.get(
- pk=self.cleaned_data['id'])
+ pk=self.cleaned_data['id'])
except:
pass
self.cleaned_data.pop('id')
@@ -452,9 +527,11 @@ class BaseFileForm(forms.ModelForm):
else:
instance = self._meta.model.objects.create(**self.cleaned_data)
+
class MultimediaFileAdminForm(forms.ModelForm):
class Meta:
model = MultimediaFile
+
class Media:
js = list(settings.JQUERY_JS_URLS) + [
'%schimere/js/menu-sort.js' % settings.STATIC_URL,
@@ -463,13 +540,15 @@ class MultimediaFileAdminForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(MultimediaFileAdminForm, self).__init__(*args, **kwargs)
self.fields['multimedia_type'].widget.choices = \
- MultimediaType.get_tuples()
+ MultimediaType.get_tuples()
+
class MultimediaFileForm(BaseFileForm):
"""
Form for a multimedia file
"""
_related_name = 'multimedia_files'
+
class Meta:
model = MultimediaFile
exclude = ('order',)
@@ -477,25 +556,29 @@ class MultimediaFileForm(BaseFileForm):
def __init__(self, *args, **kwargs):
super(MultimediaFileForm, self).__init__(*args, **kwargs)
self.fields['multimedia_type'].widget.choices = \
- MultimediaType.get_tuples()
+ MultimediaType.get_tuples()
# this can be auto detect
self.fields['multimedia_type'].required = False
MultimediaFileFormSet = formset_factory(MultimediaFileForm, can_delete=True)
+
class PictureFileAdminForm(forms.ModelForm):
class Meta:
model = PictureFile
+
class Media:
js = list(settings.JQUERY_JS_URLS) + [
'%schimere/js/menu-sort.js' % settings.STATIC_URL,
]
+
class PictureFileForm(BaseFileForm):
"""
Form for a picture file
"""
_related_name = 'pictures'
+
class Meta:
model = PictureFile
exclude = ('order', 'height', 'width', 'thumbnailfile',
@@ -503,23 +586,27 @@ class PictureFileForm(BaseFileForm):
PictureFileFormSet = formset_factory(PictureFileForm, can_delete=True)
+
class FileForm(forms.Form):
- raw_file = forms.FileField(label=_(u"File"))
+ raw_file = forms.FileField(label=_(u"File"))
def clean_raw_file(self):
data = self.cleaned_data['raw_file']
if '.' not in data.name or \
data.name.split('.')[-1].lower() not in ('kml', 'gpx'):
- raise forms.ValidationError(_(u"Bad file format: this must be a "\
+ raise forms.ValidationError(_(u"Bad file format: this must be a "
u"GPX or KML file"))
return data
+
class FullFileForm(FileForm):
name = forms.CharField(label=_(u"Name"), max_length=150)
+
def __init__(self, *args, **kwargs):
super(FullFileForm, self).__init__(*args, **kwargs)
self.fields.keyOrder = ['name', 'raw_file']
+
class AreaAdminForm(forms.ModelForm):
"""
Admin page to create an area
@@ -527,6 +614,7 @@ class AreaAdminForm(forms.ModelForm):
area = AreaField(label=_("Area"), fields=(PointField(), PointField()))
welcome_message = forms.CharField(widget=TextareaAdminWidget,
required=False)
+
class Meta:
model = Area
@@ -547,8 +635,8 @@ class AreaAdminForm(forms.ModelForm):
args[0][k] = None
if 'instance' in keys and keys['instance']:
instance = keys['instance']
- dct = {'area':(instance.upper_left_corner,
- instance.lower_right_corner)}
+ dct = {'area': (instance.upper_left_corner,
+ instance.lower_right_corner)}
if 'initial' in keys:
keys['initial'].update(dct)
else:
@@ -571,8 +659,8 @@ class AreaAdminForm(forms.ModelForm):
if self.instance:
q = q.exclude(pk=self.instance.pk)
if q.count():
- msg= _(u"The area \"%s\" has the same order, you need to "
- u" choose another one.") % unicode(q.all()[0])
+ msg = _(u"The area \"%s\" has the same order, you need to"
+ u" choose another one.") % unicode(q.all()[0])
raise forms.ValidationError(msg)
return self.cleaned_data
@@ -584,15 +672,16 @@ class AreaAdminForm(forms.ModelForm):
area = self.cleaned_data['area']
new_area.upper_left_corner = 'POINT(%s %s)' % (area[0][0], area[0][1])
new_area.lower_right_corner = 'POINT(%s %s)' % (area[1][0],
- area[1][1])
+ area[1][1])
content_type = ContentType.objects.get(app_label="chimere",
model="area")
if new_area.urn:
mnemo = 'change_area_' + new_area.urn
perm = Permission.objects.filter(codename=mnemo)
if not perm:
- perm = Permission(name='Can change ' + new_area.name,
- content_type_id=content_type.id, codename=mnemo)
+ perm = Permission(
+ name='Can change ' + new_area.name,
+ content_type_id=content_type.id, codename=mnemo)
perm.save()
else:
if 'urn' in self.initial:
@@ -602,6 +691,7 @@ class AreaAdminForm(forms.ModelForm):
perm[0].delete()
return new_area
+
class AreaForm(AreaAdminForm):
"""
Form for the edit page
@@ -612,16 +702,16 @@ class AreaForm(AreaAdminForm):
CHIMERE_ROUTING_TRANSPORT = []
ROUTING_INIT = None
if hasattr(settings, 'CHIMERE_ROUTING_TRANSPORT'):
- CHIMERE_ROUTING_TRANSPORT = [(idx, _(lbl))
- for idx, lbl in settings.CHIMERE_ROUTING_TRANSPORT]
+ CHIMERE_ROUTING_TRANSPORT = [
+ (idx, _(lbl)) for idx, lbl in settings.CHIMERE_ROUTING_TRANSPORT]
if CHIMERE_ROUTING_TRANSPORT:
ROUTING_INIT = CHIMERE_ROUTING_TRANSPORT[0][0]
class RoutingForm(forms.Form):
transport = forms.ChoiceField(label='', widget=ButtonSelectWidget,
- choices=CHIMERE_ROUTING_TRANSPORT,
- initial=ROUTING_INIT)
+ choices=CHIMERE_ROUTING_TRANSPORT,
+ initial=ROUTING_INIT)
start = forms.CharField(label=_(u"Start"), widget=NominatimWidget)
end = forms.CharField(label=_(u"Finish"), widget=NominatimWidget)
speed = forms.ChoiceField(label=_(u"Speed"), choices=[],
@@ -635,9 +725,12 @@ class RoutingForm(forms.Form):
for transport in settings.CHIMERE_ROUTING_SPEEDS:
for speed, lbl in settings.CHIMERE_ROUTING_SPEEDS[transport]:
self.fields['speed'].widget.choices.append(
- ("%s_%d" % (transport, speed), _(lbl)))
+ ("%s_%d" % (transport, speed), _(lbl)))
SearchForm = None
-if hasattr(settings, 'CHIMERE_SEARCH_ENGINE') and settings.CHIMERE_SEARCH_ENGINE:
+
+
+if hasattr(settings, 'CHIMERE_SEARCH_ENGINE') \
+ and settings.CHIMERE_SEARCH_ENGINE:
class SearchForm(HaystackSearchForm):
pass
diff --git a/chimere/search_indexes.py b/chimere/search_indexes.py
index edf9bd1..f65f966 100644
--- a/chimere/search_indexes.py
+++ b/chimere/search_indexes.py
@@ -18,13 +18,13 @@
# See the file COPYING for details.
-import datetime
from haystack import indexes
from django.db.models import Q
from chimere import models
from chimere.views import checkDate
+
class GeographicItemIndex(indexes.SearchIndex):
text = indexes.CharField(document=True, use_template=True)
categories = indexes.MultiValueField()
@@ -42,8 +42,10 @@ class GeographicItemIndex(indexes.SearchIndex):
cats.append(cat.name)
return cats
+
class MarkerIndex(GeographicItemIndex, indexes.Indexable):
location = indexes.LocationField(model_attr='point')
+
def get_model(self):
return models.Marker
diff --git a/chimere/templates/search/indexes/chimere/marker_text.txt b/chimere/templates/search/indexes/chimere/marker_text.txt
index d089654..fd25c96 100644
--- a/chimere/templates/search/indexes/chimere/marker_text.txt
+++ b/chimere/templates/search/indexes/chimere/marker_text.txt
@@ -4,3 +4,5 @@
{{object.keywords}}
{% for category in object.categories.all %}{{category.keywords}}
{% endfor %}
+{% for property in object.getProperties %}{{property}}
+{% endfor %}
diff --git a/chimere/tests.py b/chimere/tests.py
index 1c950fc..ca93546 100644
--- a/chimere/tests.py
+++ b/chimere/tests.py
@@ -10,6 +10,7 @@ test_dir_path = os.path.dirname(test_path) + os.sep
from django.contrib.auth.models import User, Group
from django.contrib.gis.geos import GEOSGeometry
+from django.core import mail
from django.core.files import File
from django.core.urlresolvers import reverse
from django.template import Context
@@ -17,7 +18,7 @@ from django.test import TestCase
from chimere.models import Area, Icon, Importer, Category, SubCategory, \
Marker, Route, News, SubCategoryUserLimit
-from chimere.forms import MarkerForm, AreaAdminForm
+from chimere.forms import MarkerForm, AreaAdminForm, notifySubmission
from chimere.templatetags.chimere_tags import display_news
from chimere.utils import ShapefileManager
@@ -367,7 +368,7 @@ class FeedsTest(TestCase):
self.assertEqual(int(doc.xpath('count(//item)')), 2)
-class AdminTest(TestCase):
+class AdministratorsTest(TestCase):
def setUp(self):
self.areas = areas_setup()
self.subcategories = subcategory_setup()
@@ -389,6 +390,8 @@ class AdminTest(TestCase):
g.user_set.add(self.moderation_user)
g.user_set.add(self.moderation_user2)
+
+class AdminTest(AdministratorsTest):
def test_actions(self):
self.client.login(username='admin', password='pass')
q_markers = Marker.objects.filter(pk__in=[m.pk for m in self.markers])
@@ -413,20 +416,51 @@ class AdminTest(TestCase):
m_ok = self.markers[0]
m_nok = self.markers[2]
self.client.login(username='mod_1', password='pass')
+ response = self.client.get('/admin/chimere/marker/')
+ self.assertTrue(str(self.subcategories[1]) in response.content)
response = self.client.get('/admin/chimere/marker/{}/'.format(m_ok.pk))
self.assertEqual(200, response.status_code)
+ self.assertTrue(str(self.subcategories[1]) in response.content)
response = self.client.get(
'/admin/chimere/marker/{}/'.format(m_nok.pk))
self.assertEqual(200, response.status_code)
self.client.logout()
self.client.login(username='mod_2', password='pass')
+ response = self.client.get('/admin/chimere/marker/')
+ self.assertFalse(str(self.subcategories[1]) in response.content)
response = self.client.get('/admin/chimere/marker/{}/'.format(m_ok.pk))
self.assertEqual(200, response.status_code)
+ self.assertFalse(str(self.subcategories[1]) in response.content)
response = self.client.get(
'/admin/chimere/marker/{}/'.format(m_nok.pk))
self.assertEqual(404, response.status_code)
+class NotifyTest(AdministratorsTest):
+ def test_notify_email(self):
+ # OK for all: two moderators and superuser
+ m1 = self.markers[0]
+ notifySubmission('dont-care-about-uri-for-tests', m1)
+ out = mail.outbox.pop()
+ self.assertEqual(sorted(out.to),
+ sorted([self.adminuser.email,
+ self.moderation_user.email,
+ self.moderation_user2.email]))
+ # not in the area for both moderators
+ m2 = self.markers[1]
+ notifySubmission('dont-care-about-uri-for-tests', m2)
+ out = mail.outbox.pop()
+ self.assertEqual(out.to, [self.adminuser.email])
+ # not a category followed by moderator2
+ m3 = self.markers[2]
+ notifySubmission('dont-care-about-uri-for-tests', m3)
+ out = mail.outbox.pop()
+ self.assertEqual(sorted(out.to),
+ sorted([self.adminuser.email,
+ self.moderation_user.email]))
+ self.assertEqual(len(out.to), 2)
+
+
class MarkerFormTest(TestCase):
def setUp(self):
self.subcategories = subcategory_setup()