Mikhail Korobov avatar Mikhail Korobov committed 56e4313

Initial import

Comments (0)

Files changed (12)

+syntax: glob
+
+#projects
+.settings/*
+.project
+.pydevproject
+.cache/*
+nbproject/*
+.buildpath
+build.properties
+MANIFEST.MF
+
+#temp files
+*.pyc
+*.pyo
+*.orig
+*~
+stuff/
+
+#os files
+.DS_Store
+Thumbs.db
+
+#setup files
+build/
+dist/
+MANIFEST
+
+#my files
+db.sqlite
+Copyright (c) 2010 Mikhail Korobov
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+include *.txt
+include *.rst
+
+recursive-include easy_maps *.html
+recursive-include easy_maps_tests *.html *.py
+================
+django-easy-maps
+================
+
+This app makes it easy to display a map for given address in django templates.
+The license is MIT.
+
+Installation
+============
+
+::
+
+    pip install geopy
+    pip install django-easy-maps
+
+Usage
+=====
+
+1. Add 'easy_maps' to INSTALLED_APPS
+
+2. Run ``./manage.py syncdb`` (or ``./manage.py migrate easy_maps``
+   if south is in use)
+
+3. Use the ``easy_map`` templatetag::
+
+       {% load easy_maps_tags %}
+
+       <!-- Default map with 300x400 dimensions -->
+       {% easy_map "Russia, Ekaterinburg, Mira 32" 300 400 %}
+
+       <!-- Variable address, custom detail level and custom template -->
+       {% easy_map address 200 200 5 using 'map.html' %}
+
+   It has the following signature::
+
+       {% easy_map <address> [<width> <height>] [<zoom>] [using <template_name>] %}
+
+   The coordinates for map will be obtained using google geocoder on first
+   access. Then they'll be cached in DB. Django's template caching can be used
+   later in order to prevent DB access on each map render::
+
+       {% load easy_maps_tags cache %}
+
+       {% cache 600 my_map firm.address %}
+           {% easy_map firm.address 300 400 %}
+       {% endcache %}
+
+That's all! No API keys, manual geocoding, html/js copy-pasting or
+django model changes is needed.
+
+Customization
+=============
+
+If the default map template is not sufficient then custom map template can be
+used::
+
+   {% easy_map address using 'map.html' %}
+
+   <!-- or -->
+
+   {% easy_map address 200 300 5 using 'map.html' %}
+
+The template will have 'map' (it is the ``easy_maps.models.Address`` instance),
+'width', 'height' and 'zoom' variables. The outer template context is passed
+to 'map.html' as well.
+
+Address model
+=============
+
+easy_maps.models.Address model has the following fields:
+
+* address
+* computed address
+* longtitude
+* latitude
+* geocode_error
+
+Contributing
+============
+
+If you've found a bug, implemented a feature or customized the template and
+think it is useful then please consider contributing. Patches, pull requests or
+just suggestions are welcome!
+
+Source code: https://bitbucket.org/kmike/django-easy-maps/
+
+Bug tracker: https://bitbucket.org/kmike/django-easy-maps/issues/new
+

Empty file added.

easy_maps/migrations/0001_initial.py

+# encoding: utf-8
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        
+        # Adding model 'Address'
+        db.create_table('easy_maps_address', (
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+            ('address', self.gf('django.db.models.fields.CharField')(max_length=255, db_index=True)),
+            ('computed_address', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)),
+            ('latitude', self.gf('django.db.models.fields.FloatField')(null=True, blank=True)),
+            ('longtitude', self.gf('django.db.models.fields.FloatField')(null=True, blank=True)),
+            ('geocode_error', self.gf('django.db.models.fields.BooleanField')(default=False)),
+        ))
+        db.send_create_signal('easy_maps', ['Address'])
+
+
+    def backwards(self, orm):
+        
+        # Deleting model 'Address'
+        db.delete_table('easy_maps_address')
+
+
+    models = {
+        'easy_maps.address': {
+            'Meta': {'object_name': 'Address'},
+            'address': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
+            'computed_address': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'geocode_error': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'latitude': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}),
+            'longtitude': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'})
+        }
+    }
+
+    complete_apps = ['easy_maps']
Add a comment to this file

easy_maps/migrations/__init__.py

Empty file added.

easy_maps/models.py

+from django.db import models
+from geopy import geocoders
+
+class Address(models.Model):
+    address = models.CharField(max_length=255, db_index=True)
+    computed_address = models.CharField(max_length=255, null=True, blank=True)
+    latitude = models.FloatField(null=True, blank=True)
+    longtitude = models.FloatField(null=True, blank=True)
+    geocode_error = models.BooleanField(default=False)
+
+    def fill_geocode_data(self):
+        try:
+            g = geocoders.Google(resource='maps')
+            self.computed_address, (self.latitude, self.longtitude,) = g.geocode(self.address)
+            self.geocode_error = False
+        except UnboundLocalError:
+            self.geocode_error = True
+
+    def save(self, *args, **kwargs):
+        # fill geocode data if it is unknown
+        if (self.longtitude is None) or (self.latitude is None):
+            self.fill_geocode_data()
+        super(Address, self).save(*args, **kwargs)
+
+    def __unicode__(self):
+        return self.address

easy_maps/templates/easy_maps/map.html

+<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
+<div id="map-canvas-{{ map.pk }}" style="width: {{ width }}; height: {{ height }}}" class="easy-map-googlemap"></div>
+
+<script type="text/javascript">
+    function initialize() {
+        var latlng = new google.maps.LatLng({{ map.latitude }}, {{ map.longtitude }});
+        var myOptions = {
+            zoom: {{ zoom }},
+            center: latlng,
+            mapTypeId: google.maps.MapTypeId.ROADMAP
+        };
+        var mapElem = document.getElementById("map-canvas-{{ map.pk }}");
+        var map = new google.maps.Map(mapElem, myOptions);
+
+        var marker = new google.maps.Marker({
+            position: latlng,
+            map: map,
+            title: "{{ map.address }}"
+        });
+    }
+    google.maps.event.addDomListener(window, 'load', initialize);
+</script>
Add a comment to this file

easy_maps/templatetags/__init__.py

Empty file added.

easy_maps/templatetags/easy_maps_tags.py

+#coding: utf-8
+from django import template
+from django.template.loader import render_to_string
+from easy_maps.models import Address
+register = template.Library()
+
+@register.tag
+def easy_map(parser, token):
+    """
+    The syntax:
+        {% easy_map <address> [<width> <height>] [<zoom>] [using <template_name>] %}
+    """
+    width, height, zoom, template_name = None, None, None, None
+    params = token.split_contents()
+
+    # pop the template name
+    if params[-2] == 'using':
+        template_name = params[-1]
+        params = params[:-2]
+
+    if len(params) < 2:
+        raise template.TemplateSyntaxError('easy_map tag requires address argument')
+
+    address = params[1]
+
+    if len(params) == 4:
+        width, height = params[2], params[3]
+    elif len(params) == 5:
+        width, height, zoom = params[2], params[3], params[4]
+    elif len(params) == 3 or len(params) > 5:
+        raise template.TemplateSyntaxError('easy_map tag has the following syntax: '
+                   '{% easy_map <address> <width> <height> [zoom] [using <template_name>] %}')
+    return EasyMapNode(address, width, height, zoom, template_name)
+
+class EasyMapNode(template.Node):
+    def __init__(self, address, width, height, zoom, template_name):
+        self.address = template.Variable(address)
+        self.width = width or ''
+        self.height = height or ''
+        self.zoom = zoom or 16
+        self.template_name = template.Variable(template_name or '"easy_maps/map.html"')
+
+    def render(self, context):
+        try:
+            address = self.address.resolve(context)
+            template_name = self.template_name.resolve(context)
+
+            print address
+            map, _ = Address.objects.get_or_create(address=address)
+            context.update({
+                'map': map,
+                'width': self.width,
+                'height': self.height,
+                'zoom': self.zoom,
+                'template_name': template_name
+            })
+            return render_to_string(template_name, context_instance=context)
+        except template.VariableDoesNotExist:
+            return ''
+#!/usr/bin/env python
+from distutils.core import setup
+version='0.5'
+
+setup(
+    name = 'django-easy-maps',
+    version = version,
+    author = 'Mikhail Korobov',
+    author_email = 'kmike84@gmail.com',
+    url = 'http://bitbucket.org/kmike/django-easy-maps/',
+    download_url = 'http://bitbucket.org/kmike/django-easy-maps/get/tip.zip',
+
+    description = 'This app makes it easy to display a map for a given address.',
+    long_description = open('README.rst').read(),
+    license = 'MIT license',
+    requires = ['django (>=1.0)', 'geopy'],
+
+    packages=['easy_maps', 'easy_maps.templatetags', 'easy_maps.migrations'],
+    package_data={'easy_maps': ['templates/easy_maps/*']},
+
+    classifiers=[
+        'Development Status :: 4 - Beta',
+        'Framework :: Django',
+        'Intended Audience :: Developers',
+        'License :: OSI Approved :: MIT License',
+        'Programming Language :: Python',
+        'Topic :: Software Development :: Libraries :: Python Modules'
+    ],
+)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.