Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Building GIS Web Apps with Python & Django

Building GIS Web Apps with Python & Django

This was a *very brief* (20minutes) look at a simple GeoDjango app (a blog with a PointField), given at the MAGIC 2014 conference (Memphis Area Geographic Council).

Brad Montgomery

November 06, 2014
Tweet

More Decks by Brad Montgomery

Other Decks in Technology

Transcript

  1. Building GIS Web Apps with Python & Django ! Brad

    Montgomery MEMpy: Memphis Python User Group (mempy.org) Tennessee Data Commons (tndata.org)
  2. Batteries Included • An object-relational mapper (ORM) • Form Validation

    • Testing Tools • Migrations (recently added to Django) • Built-in apps (admin, auth, caching, sessions, sitemaps, syndication, gis, … more)
  3. Community • 100’s of 3rd-party, open source apps • Many

    are MIT or BSD Licensed. • djangopackages.com
  4. Directory Structure sampleproject/! !"" blog! # !"" __init__.py! # !""

    admin.py! # !"" migrations! # # $"" __init__.py! # !"" models.py! # !"" tests.py! # $"" views.py! # !"" templates/
  5. Projects & Apps sampleproject/! !"" blog! # !"" __init__.py! #

    !"" admin.py! # !"" migrations! # # $"" __init__.py! # !"" models.py! # !"" tests.py! # $"" views.py! # !"" templates/ Most of your work is here.
  6. models.py from django.contrib.auth.models import User! from django.contrib.gis.db import models! !

    ! class Post(models.Model):! author = models.ForeignKey(User)! title = models.CharField(max_length=128)! content = models.TextField()! slug = models.SlugField(max_length=128, unique=True)! published_on = models.DateTimeField(auto_now_add=True)! published_at = models.PointField(srid=4326)! ! objects = models.GeoManager()
  7. models.py from django.contrib.auth.models import User! from django.contrib.gis.db import models! !

    ! class Post(models.Model):! author = models.ForeignKey(User)! title = models.CharField(max_length=128)! content = models.TextField()! slug = models.SlugField(max_length=128, unique=True)! published_on = models.DateTimeField(auto_now_add=True)! published_at = models.PointField(srid=4326)! ! objects = models.GeoManager() corresponds to a database table
  8. models.py from django.contrib.auth.models import User! from django.contrib.gis.db import models! !

    ! class Post(models.Model):! author = models.ForeignKey(User)! title = models.CharField(max_length=128)! content = models.TextField()! slug = models.SlugField(max_length=128, unique=True)! published_on = models.DateTimeField(auto_now_add=True)! published_at = models.PointField(srid=4326)! ! objects = models.GeoManager() columns in the table
  9. models.py from django.contrib.auth.models import User! from django.contrib.gis.db import models! !

    ! class Post(models.Model):! author = models.ForeignKey(User)! title = models.CharField(max_length=128)! content = models.TextField()! slug = models.SlugField(max_length=128, unique=True)! published_on = models.DateTimeField(auto_now_add=True)! published_at = models.PointField(srid=4326)! ! objects = models.GeoManager()
  10. models.py from django.contrib.auth.models import User! from django.contrib.gis.db import models! !

    ! class Post(models.Model):! author = models.ForeignKey(User)! title = models.CharField(max_length=128)! content = models.TextField()! slug = models.SlugField(max_length=128, unique=True)! published_on = models.DateTimeField(auto_now_add=True)! published_at = models.PointField(srid=4326)! ! objects = models.GeoManager()
  11. gis fields from django.contrib.gis.db import models! ! class SomeModel(models.Model):! line

    = models.LineStringField()! poly = models.PolygonField()! geometry = models.GeometryField()! ! lines = models.MultiLineStringField()! points = models.MultiPointField()! polygons = models.MultiPolygonField()! geometries = models.GeometryCollectionField()! ! objects = models.GeoManager()
  12. ORM/gis lookups ! # Get the city using a WKT!

    City.objects.get(! ! mpoly__contains=‘POINT(-95.3385 29.7245)’! )!
  13. ORM/gis lookups ! # Get the city where a Post

    was published! City.objects.get(! ! mpoly__contains=post.published_at! )!
  14. ORM/gis lookups from django.contrib.gis.measure import D! ! # Find other

    posts published within 5 Miles.! radius = (post.published_at, D(mi=5))! Post.objects.filter(! published_at__distance__lte=radius! )
  15. ORM/gis lookups Distance Lookups ! •distance_lt •distance_lte •distance_gt •distance_gte •dwithin

    Spatial Lookups ‣bbcontains ‣bboverlaps ‣covers ‣crosses ‣overlaps ‣intersects ‣touches ‣within ‣…more!
  16. views.py from django.shortcuts import render_to_response! from django.template import RequestContext! from

    models import Post! ! def display_post(request, post_slug): ! post = Post.objects.get(slug=post_slug)! template_data = {'post': post}! template = "blog/post.html"! ! return render_to_response(! template,! template_data,! context_instance=RequestContext(request)! )
  17. views.py from django.shortcuts import render_to_response! from django.template import RequestContext! from

    models import Post! ! def display_post(request, post_slug): ! post = Post.objects.get(slug=post_slug)! template_data = {'post': post}! template = "blog/post.html"! ! return render_to_response(! template,! template_data,! context_instance=RequestContext(request)! )
  18. views.py from django.shortcuts import render_to_response! from django.template import RequestContext! from

    models import Post! ! def display_post(request, post_slug): ! post = Post.objects.get(slug=post_slug)! template_data = {'post': post}! template = "blog/post.html"! ! return render_to_response(! template,! template_data,! context_instance=RequestContext(request)! )
  19. views.py from django.shortcuts import render_to_response! from django.template import RequestContext! from

    models import Post! ! def display_post(request, post_slug): ! post = Post.objects.get(slug=post_slug)! template_data = {'post': post}! template = "blog/post.html"! ! return render_to_response(! template,! template_data,! context_instance=RequestContext(request)! )
  20. views.py from django.shortcuts import render_to_response! from django.template import RequestContext! from

    models import Post! ! def display_post(request, post_slug): ! post = Post.objects.get(slug=post_slug)! template_data = {'post': post}! template = "blog/post.html"! ! return render_to_response(! template,! template_data,! context_instance=RequestContext(request)! )
  21. views.py from django.shortcuts import render_to_response! from django.template import RequestContext! from

    models import Post! ! def display_post(request, post_slug): ! post = Post.objects.get(slug=post_slug)! template_data = {'post': post}! template = "blog/post.html"! ! return render_to_response(! template,! template_data,! context_instance=RequestContext(request)! )
  22. <!DOCTYPE html>! <html>! <head>! <title>! {% block title %}{% endblock

    %}! </title>! </head>! ! <body>! {% block content %}{% endblock %}! </body>! </html> A base.html template
  23. A base.html template <!DOCTYPE html>! <html>! <head>! <title>! {% block

    title %}{% endblock %}! </title>! </head>! ! <body>! {% block content %}{% endblock %}! </body>! </html>
  24. post.html {% extends "base.html" %}! ! {% block title %}!

    {{ post.title }}! {% endblock %}! ! {% block content %}! <h1>{{ post.title }}</h1>! <p>Published at {{ post.published_at }}</p>! ! {{ post.content|urlize|linebreaks }}! ! <p>Published on:! {{ post.published_on|date:"M d, Y" }}</p>! {% endblock %}
  25. {% extends "base.html" %}! ! {% block title %}! {{

    post.title }}! {% endblock %}! ! {% block content %}! <h1>{{ post.title }}</h1>! <p>Published at {{ post.published_at }}</p>! ! {{ post.content|urlize|linebreaks }}! ! <p>Published on:! {{ post.published_on|date:"M d, Y" }}</p>! {% endblock %} post.html
  26. {% extends "base.html" %}! ! {% block title %}! {{

    post.title }}! {% endblock %}! ! {% block content %}! <h1>{{ post.title }}</h1>! <p>Published at {{ post.published_at }}</p>! ! {{ post.content|urlize|linebreaks }}! ! <p>Published on:! {{ post.published_on|date:"M d, Y" }}</p>! {% endblock %} post.html
  27. {% extends "base.html" %}! ! {% block title %}! {{

    post.title }}! {% endblock %}! ! {% block content %}! <h1>{{ post.title }}</h1>! <p>Published at {{ post.published_at }}</p>! ! {{ post.content|urlize|linebreaks }}! ! <p>Published on:! {{ post.published_on|date:"M d, Y" }}</p>! {% endblock %} post.html
  28. {% extends "base.html" %}! ! {% block title %}! {{

    post.title }}! {% endblock %}! ! {% block content %}! <h1>{{ post.title }}</h1>! <p>Published at {{ post.published_at }}</p>! ! {{ post.content|urlize|linebreaks }}! ! <p>Published on:! {{ post.published_on|date:"M d, Y" }}</p>! {% endblock %} post.html
  29. {% extends "base.html" %}! ! {% block title %}! {{

    post.title }}! {% endblock %}! ! {% block content %}! <h1>{{ post.title }}</h1>! <p>Published at {{ post.published_at }}</p>! ! {{ post.content|urlize|linebreaks }}! ! <p>Published on:! {{ post.published_on|date:"M d, Y" }}</p>! {% endblock %} post.html
  30. {% extends "base.html" %}! ! {% block title %}! {{

    post.title }}! {% endblock %}! ! {% block content %}! <h1>{{ post.title }}</h1>! <p>Published at {{ post.published_at }}</p>! ! {{ post.content|urlize|linebreaks }}! ! <p>Published on:! {{ post.published_on|date:"M d, Y" }}</p>! {% endblock %} post.html
  31. {% extends "base.html" %}! ! {% block title %}! {{

    post.title }}! {% endblock %}! ! {% block content %}! <h1>{{ post.title }}</h1>! <p>Published at {{ post.published_at }}</p>! ! {{ post.content|urlize|linebreaks }}! ! <p>Published on:! {{ post.published_on|date:"M d, Y" }}</p>! {% endblock %} post.html
  32. {% extends "base.html" %}! ! {% block title %}! {{

    post.title }}! {% endblock %}! ! {% block content %}! <h1>{{ post.title }}</h1>! <p>Published at {{ post.published_at }}</p>! ! {{ post.content|urlize|linebreaks }}! ! <p>Published on:! {{ post.published_on|date:"M d, Y" }}</p>! {% endblock %} post.html template filters
  33. {% extends "base.html" %}! ! {% block title %}! {{

    post.title }}! {% endblock %}! ! {% block content %}! <h1>{{ post.title }}</h1>! <p>Published at {{ post.published_at }}</p>! ! {{ post.content|urlize|linebreaks }}! ! <p>Published on:! {{ post.published_on|date:"M d, Y" }}</p>! {% endblock %} post.html
  34. {% extends "base.html" %}! ! {% block title %}! {{

    post.title }}! {% endblock %}! ! {% block content %}! <h1>{{ post.title }}</h1>! <p>Published at {{ post.published_at }}</p>! ! {{ post.content|urlize|linebreaks }}! ! <p>Published on:! {{ post.published_on|date:"M d, Y" }}</p>! {% endblock %} post.html template filter
  35. Root URLConf: urls.py from django.conf.urls import patterns, include, url! !

    from django.contrib import admin! admin.autodiscover()! ! urlpatterns = patterns('',! url(r'^blog/(?P<post_slug>.+)/$',! 'blog.views.display_post',! name='display_post'),! url(r'^admin/', include(admin.site.urls)),! )
  36. from django.conf.urls import patterns, include, url! ! from django.contrib import

    admin! admin.autodiscover()! ! urlpatterns = patterns('',! url(r'^blog/(?P<post_slug>.+)/$',! 'blog.views.display_post',! name='display_post'),! url(r'^admin/', include(admin.site.urls)),! ) Root URLConf: urls.py
  37. from django.conf.urls import patterns, include, url! ! from django.contrib import

    admin! admin.autodiscover()! ! urlpatterns = patterns('',! url(r'^blog/(?P<post_slug>.+)/$',! 'blog.views.display_post',! name='display_post'),! url(r'^admin/', include(admin.site.urls)),! ) Root URLConf: urls.py
  38. from django.conf.urls import patterns, include, url! ! from django.contrib import

    admin! admin.autodiscover()! ! urlpatterns = patterns('',! url(r'^blog/(?P<post_slug>.+)/$',! 'blog.views.display_post',! name='display_post'),! url(r'^admin/', include(admin.site.urls)),! ) Root URLConf: urls.py
  39. from django.conf.urls import patterns, include, url! ! from django.contrib import

    admin! admin.autodiscover()! ! urlpatterns = patterns('',! url(r'^blog/(?P<post_slug>.+)/$',! 'blog.views.display_post',! name='display_post'),! url(r'^admin/', include(admin.site.urls)),! ) Root URLConf: urls.py
  40. from django.conf.urls import patterns, include, url! ! from django.contrib import

    admin! admin.autodiscover()! ! urlpatterns = patterns('',! url(r'^blog/(?P<post_slug>.+)/$',! 'blog.views.display_post',! name='display_post'),! url(r'^admin/', include(admin.site.urls)),! ) Root URLConf: urls.py
  41. An HTTP Request from django.conf.urls import patterns, include, url! !

    from django.contrib import admin! admin.autodiscover()! ! urlpatterns = patterns('',! url(r'^blog/(?P<post_slug>.+)/$',! 'blog.views.display_post',! name='display_post'),! url(r'^admin/', include(admin.site.urls)),! ) blog/sample-title/
  42. An HTTP Request from django.conf.urls import patterns, include, url! !

    from django.contrib import admin! admin.autodiscover()! ! urlpatterns = patterns('',! url(r'^blog/(?P<post_slug>.+)/$',! 'blog.views.display_post',! name='display_post'),! url(r'^admin/', include(admin.site.urls)),! ) blog/sample-title/
  43. An HTTP Request def display_post(request, post_slug): ! post = Post.objects.get(slug=post_slug)!

    template_data = {'post': post}! template = "blog/post.html"! ! return render_to_response(! template,! template_data,! context_instance=RequestContext(request)! ) sample-title
  44. An HTTP Request {% extends "base.html" %}! ! {% block

    title %}! {{ post.title }}! {% endblock %}! ! {% block content %}! <h1>{{ post.title }}</h1>! <p>Published at {{ post.published_at }}</p>! ! {{ post.content|urlize|linebreaks }}! ! <p>Published on:! {{ post.published_on|date:"M d, Y" }}</p>! {% endblock %} sampleproject/blog/templates/blog/post.html Sample Title
  45. An HTTP Request {% extends "base.html" %}! ! {% block

    title %}! {{ post.title }}! {% endblock %}! ! {% block content %}! <h1>{{ post.title }}</h1>! <p>Published at {{ post.published_at }}</p>! ! {{ post.content|urlize|linebreaks }}! ! <p>Published on:! {{ post.published_on|date:"M d, Y" }}</p>! {% endblock %} sampleproject/blog/templates/blog/post.html (35, 89)
  46. An HTTP Request {% extends "base.html" %}! ! {% block

    title %}! {{ post.title }}! {% endblock %}! ! {% block content %}! <h1>{{ post.title }}</h1>! <p>Published at {{ post.published_at }}</p>! ! {{ post.content|urlize|linebreaks }}! ! <p>Published on:! {{ post.published_on|date:"M d, Y" }}</p>! {% endblock %} sampleproject/blog/templates/blog/post.html Lorem Ipsum...
  47. An HTTP Request {% extends "base.html" %}! ! {% block

    title %}! {{ post.title }}! {% endblock %}! ! {% block content %}! <h1>{{ post.title }}</h1>! <p>Published at {{ post.published_at }}</p>! ! {{ post.content|urlize|linebreaks }}! ! <p>Published on:! {{ post.published_on|date:"M d, Y" }}</p>! {% endblock %} sampleproject/blog/templates/blog/post.html Nov 3, 2012