views.py 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. from django.apps import apps
  2. from django.contrib.gis.db.models import GeometryField
  3. from django.contrib.gis.db.models.functions import AsKML, Transform
  4. from django.contrib.gis.shortcuts import render_to_kml, render_to_kmz
  5. from django.core.exceptions import FieldDoesNotExist
  6. from django.db import DEFAULT_DB_ALIAS, connections
  7. from django.http import Http404
  8. def kml(request, label, model, field_name=None, compress=False, using=DEFAULT_DB_ALIAS):
  9. """
  10. This view generates KML for the given app label, model, and field name.
  11. The field name must be that of a geographic field.
  12. """
  13. placemarks = []
  14. try:
  15. klass = apps.get_model(label, model)
  16. except LookupError:
  17. raise Http404(
  18. 'You must supply a valid app label and module name. Got "%s.%s"'
  19. % (label, model)
  20. )
  21. if field_name:
  22. try:
  23. field = klass._meta.get_field(field_name)
  24. if not isinstance(field, GeometryField):
  25. raise FieldDoesNotExist
  26. except FieldDoesNotExist:
  27. raise Http404("Invalid geometry field.")
  28. connection = connections[using]
  29. if connection.features.has_AsKML_function:
  30. # Database will take care of transformation.
  31. placemarks = klass._default_manager.using(using).annotate(kml=AsKML(field_name))
  32. else:
  33. # If the database offers no KML method, we use the `kml`
  34. # attribute of the lazy geometry instead.
  35. placemarks = []
  36. if connection.features.has_Transform_function:
  37. qs = klass._default_manager.using(using).annotate(
  38. **{"%s_4326" % field_name: Transform(field_name, 4326)}
  39. )
  40. field_name += "_4326"
  41. else:
  42. qs = klass._default_manager.using(using).all()
  43. for mod in qs:
  44. mod.kml = getattr(mod, field_name).kml
  45. placemarks.append(mod)
  46. # Getting the render function and rendering to the correct.
  47. if compress:
  48. render = render_to_kmz
  49. else:
  50. render = render_to_kml
  51. return render("gis/kml/placemarks.kml", {"places": placemarks})
  52. def kmz(request, label, model, field_name=None, using=DEFAULT_DB_ALIAS):
  53. """
  54. Return KMZ for the given app label, model, and field name.
  55. """
  56. return kml(request, label, model, field_name, compress=True, using=using)