]> git.parisson.com Git - mezzo.git/commitdiff
Network : list geocoded organization
authorEmilie <zawadzki@ircam.fr>
Wed, 5 Oct 2016 14:07:19 +0000 (16:07 +0200)
committerEmilie <zawadzki@ircam.fr>
Wed, 5 Oct 2016 14:07:19 +0000 (16:07 +0200)
app/organization/network/migrations/0031_auto_20161005_1403.py [new file with mode: 0644]
app/organization/network/migrations/0032_auto_20161005_1412.py [new file with mode: 0644]
app/organization/network/migrations/0033_auto_20161005_1427.py [new file with mode: 0644]
app/organization/network/migrations/0034_organization_city.py [new file with mode: 0644]
app/organization/network/migrations/0035_auto_20161005_1457.py [new file with mode: 0644]
app/organization/network/migrations/0036_auto_20161005_1509.py [new file with mode: 0644]
app/organization/network/models.py
app/organization/network/urls.py
app/organization/network/views.py
app/templates/network/organization_list.html [new file with mode: 0644]

diff --git a/app/organization/network/migrations/0031_auto_20161005_1403.py b/app/organization/network/migrations/0031_auto_20161005_1403.py
new file mode 100644 (file)
index 0000000..09945c1
--- /dev/null
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.9.7 on 2016-10-05 12:03
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('organization-network', '0030_team_parent'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='organization',
+            name='is_on_map',
+            field=models.BooleanField(default=False, verbose_name='is on map'),
+        ),
+    ]
diff --git a/app/organization/network/migrations/0032_auto_20161005_1412.py b/app/organization/network/migrations/0032_auto_20161005_1412.py
new file mode 100644 (file)
index 0000000..6f0f357
--- /dev/null
@@ -0,0 +1,25 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.9.7 on 2016-10-05 12:12
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('organization-network', '0031_auto_20161005_1403'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='organization',
+            name='latitude',
+            field=models.CharField(blank=True, max_length=40, verbose_name='latitude'),
+        ),
+        migrations.AddField(
+            model_name='organization',
+            name='longitude',
+            field=models.CharField(blank=True, max_length=40, verbose_name='longitude'),
+        ),
+    ]
diff --git a/app/organization/network/migrations/0033_auto_20161005_1427.py b/app/organization/network/migrations/0033_auto_20161005_1427.py
new file mode 100644 (file)
index 0000000..7a0fb06
--- /dev/null
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.9.7 on 2016-10-05 12:27
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('organization-network', '0032_auto_20161005_1412'),
+    ]
+
+    operations = [
+        migrations.RemoveField(
+            model_name='organization',
+            name='latitude',
+        ),
+        migrations.RemoveField(
+            model_name='organization',
+            name='longitude',
+        ),
+        migrations.AddField(
+            model_name='organization',
+            name='lat',
+            field=models.DecimalField(blank=True, decimal_places=7, help_text='Calculated automatically if mappable location is set.', max_digits=10, null=True, verbose_name='Latitude'),
+        ),
+        migrations.AddField(
+            model_name='organization',
+            name='lon',
+            field=models.DecimalField(blank=True, decimal_places=7, help_text='Calculated automatically if mappable location is set.', max_digits=10, null=True, verbose_name='Longitude'),
+        ),
+        migrations.AddField(
+            model_name='organization',
+            name='mappable_location',
+            field=models.CharField(blank=True, help_text='This address will be used to calculate latitude and longitude. Leave blank and set Latitude and Longitude to specify the location yourself, or leave all three blank to auto-fill from the Location field.', max_length=128),
+        ),
+    ]
diff --git a/app/organization/network/migrations/0034_organization_city.py b/app/organization/network/migrations/0034_organization_city.py
new file mode 100644 (file)
index 0000000..b773c3b
--- /dev/null
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.9.7 on 2016-10-05 12:43
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('organization-network', '0033_auto_20161005_1427'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='organization',
+            name='city',
+            field=models.CharField(blank=True, max_length=255, verbose_name='city'),
+        ),
+    ]
diff --git a/app/organization/network/migrations/0035_auto_20161005_1457.py b/app/organization/network/migrations/0035_auto_20161005_1457.py
new file mode 100644 (file)
index 0000000..5fe10c2
--- /dev/null
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.9.7 on 2016-10-05 12:57
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('organization-network', '0034_organization_city'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='organization',
+            name='address',
+            field=models.TextField(verbose_name='address'),
+        ),
+    ]
diff --git a/app/organization/network/migrations/0036_auto_20161005_1509.py b/app/organization/network/migrations/0036_auto_20161005_1509.py
new file mode 100644 (file)
index 0000000..7ad0e2b
--- /dev/null
@@ -0,0 +1,25 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.9.7 on 2016-10-05 13:09
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('organization-network', '0035_auto_20161005_1457'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='organization',
+            name='city',
+            field=models.CharField(max_length=255, verbose_name='city'),
+        ),
+        migrations.AlterField(
+            model_name='organization',
+            name='postal_code',
+            field=models.CharField(max_length=16, verbose_name='postal code'),
+        ),
+    ]
index 30d834324c3a1e4af9b55caa5972b723636868f0..95e8732fc4ff0b32db1a6c7d6bd23b08ce238c33 100644 (file)
@@ -9,11 +9,15 @@ import string
 import datetime
 import mimetypes
 
+from geopy.geocoders import GoogleV3 as GoogleMaps
+from geopy.exc import GeocoderQueryError
+
 from django.db import models
 from django.utils.translation import ugettext_lazy as _
 from django.core.urlresolvers import reverse, reverse_lazy
 from django.conf import settings
 from django.contrib.auth.models import User
+from django.core.exceptions import ValidationError
 
 from mezzanine.pages.models import Page
 from mezzanine.core.models import RichText, Displayable, Slugged
@@ -60,8 +64,9 @@ ALIGNMENT_CHOICES = (('left', _('left')), ('left', _('left')), ('right', _('righ
 class Address(models.Model):
     """(Address description)"""
 
-    address = models.TextField(_('address'), blank=True)
-    postal_code = models.CharField(_('postal code'), max_length=16, blank=True)
+    address = models.TextField(_('address'))
+    postal_code = models.CharField(_('postal code'), max_length=16)
+    city = models.CharField(_('city'), max_length=255)
     country = CountryField(_('country'))
 
     def __str__(self):
@@ -74,8 +79,11 @@ class Address(models.Model):
 class Organization(Named, Address, URL, AdminThumbRelatedMixin):
     """(Organization description)"""
 
+    mappable_location = models.CharField(max_length=128, blank=True, help_text="This address will be used to calculate latitude and longitude. Leave blank and set Latitude and Longitude to specify the location yourself, or leave all three blank to auto-fill from the Location field.")
+    lat = models.DecimalField(max_digits=10, decimal_places=7, blank=True, null=True, verbose_name="Latitude", help_text="Calculated automatically if mappable location is set.")
+    lon = models.DecimalField(max_digits=10, decimal_places=7, blank=True, null=True, verbose_name="Longitude", help_text="Calculated automatically if mappable location is set.")
     type = models.ForeignKey('OrganizationType', verbose_name=_('organization type'), blank=True, null=True, on_delete=models.SET_NULL)
-    is_on_map = models.BooleanField(_('is on map'), default=True)
+    is_on_map = models.BooleanField(_('is on map'), default=False)
 
     admin_thumb_type = 'logo'
 
@@ -83,6 +91,39 @@ class Organization(Named, Address, URL, AdminThumbRelatedMixin):
         verbose_name = _('organization')
         ordering = ['name',]
 
+    def clean(self):
+        """
+        Validate set/validate mappable_location, longitude and latitude.
+        """
+        super(Organization, self).clean()
+
+        if self.lat and not self.lon:
+            raise ValidationError("Longitude required if specifying latitude.")
+
+        if self.lon and not self.lat:
+            raise ValidationError("Latitude required if specifying longitude.")
+
+        if not (self.lat and self.lon) and not self.mappable_location:
+            self.mappable_location = self.address.replace("\n"," ").replace('\r', ' ') + ", " + self.postal_code + " " + self.city
+
+        if self.mappable_location and not (self.lat and self.lon): #location should always override lat/long if set
+            g = GoogleMaps(domain=settings.EVENT_GOOGLE_MAPS_DOMAIN)
+            try:
+                mappable_location, (lat, lon) = g.geocode(self.mappable_location)
+            except GeocoderQueryError as e:
+                raise ValidationError("The mappable location you specified could not be found on {service}: \"{error}\" Try changing the mappable location, removing any business names, or leaving mappable location blank and using coordinates from getlatlon.com.".format(service="Google Maps", error=e.message))
+            except ValueError as e:
+                raise ValidationError("The mappable location you specified could not be found on {service}: \"{error}\" Try changing the mappable location, removing any business names, or leaving mappable location blank and using coordinates from getlatlon.com.".format(service="Google Maps", error=e.message))
+            except TypeError as e:
+                raise ValidationError("The mappable location you specified could not be found. Try changing the mappable location, removing any business names, or leaving mappable location blank and using coordinates from getlatlon.com.")
+            self.mappable_location = mappable_location
+            self.lat = lat
+            self.lon = lon
+
+    def save(self):
+        self.clean()
+        super(Organization, self).save()
+
 
 class OrganizationAudio(Audio):
 
index f390050355b95f4052f25f28f25435bbc4c2fbe6..fcdf16603fac13f1593e5a8fa2e599b4b468639f 100644 (file)
@@ -13,4 +13,5 @@ urlpatterns = [
     url(r'^person/(?P<slug>.*)/$', PersonDetailView.as_view(), name="organization-network-person-detail"),
     url("^person-list-block-autocomplete/$", permission_required('person.can_edit')(PersonListBlockAutocompleteView.as_view()), name='person-list-block-autocomplete'),
     url("^person-autocomplete/$", permission_required('person.can_edit')(PersonListView.as_view()), name='person-autocomplete'),
+    url("^network/$", OrganizationListView.as_view(), name='network'),
     ]
index 13a4d465721905c286eb0c79b28a3295375206ea..acdedca548306c6c088b536a93fb496f58c70bb9 100644 (file)
@@ -52,3 +52,12 @@ class PersonListView(autocomplete.Select2QuerySetView):
             qs = qs.filter(person_title__istartswith=self.q)
 
         return qs
+
+class OrganizationListView(ListView):
+
+    model = Organization
+    context_object_name = 'organizations'
+    template_name='network/organization_list.html'
+
+    def get_queryset(self, **kwargs):
+        return self.model.objects.filter(is_on_map=True)
diff --git a/app/templates/network/organization_list.html b/app/templates/network/organization_list.html
new file mode 100644 (file)
index 0000000..528a28d
--- /dev/null
@@ -0,0 +1,48 @@
+{% extends "pages/page.html" %}
+{% load i18n mezzanine_tags keyword_tags pages_tags organization_tags %}
+
+{% block meta_title %}{% trans "Network" %}{% endblock %}
+
+{% block meta_description %}{% metablock %}
+{{ organization.description }}
+{% endmetablock %}{% endblock %}
+
+{% block page_class %}
+    organization
+{% endblock %}
+
+{% block page_title %}
+  <h1 class="dotted">{% trans "Network" %}</h1>
+{% endblock %}
+
+{% block page_content %}
+
+
+    {% for organization in organizations %}
+
+        {{ organization.name }}<br>
+        {{ organization.lat }}<br>
+        {{ organization.lon }}<br>
+        {{ organization.city }}<br>
+        {{ organization.country.name }}<br>
+
+        <!-- optional -->
+        {% with organization.links|get_type_link:'link' as links %}
+            {% if links %}
+                {{ links.first }}
+            {% endif %}
+        {% endwith %}
+        <br>
+        <!-- optional -->
+        {% with organization.images.all|get_type:'logo' as images %}
+            {% if images %}
+                <img src="{{ MEDIA_URL }}{% thumbnail images.first.file 100 0 left=0 top=0 %}" alt="logo {{ organization.name }}" />
+            {% endif %}
+        {% endwith %}
+        <br><br>
+
+    {% endfor %}
+
+
+
+{% endblock %}