Index: curso_django/curso_django.tex
===================================================================
--- curso_django/curso_django.tex	(revision e11d965137204bdfee40198ee5c54f17088dde46)
+++ curso_django/curso_django.tex	(revision fd1bfc1399fd886ae0edcd71c3c0ba2d44ee7305)
@@ -1076,4 +1076,466 @@
 \end{frame}
 
+\subsection{Geodjango}
+\begin{frame}[fragile]
+\begin{verbatim}
+Para la gestiÃ³n de datos geolocalizados debe utilizar 
+una extensiÃ³n de django denominada Geodjango
+
+InstalaciÃ³n de componentes para la gestiÃ³n de mapas
+en particular la extensiÃ³n django.contrib.gis
+
+Entrar como root para la instalacion
+
+aptitude install python3.4 python3-pip python3.4-dev 
+python3-setuptools
+
+aptitude install python3-virtualenv virtualenvwrapper
+
+Salir del modo root y crear el ambiente:
+
+$ mkvirtualenv --python=/usr/bin/python3 geodjango
+\end{verbatim}
+\end{frame}
+
+\begin{frame}[fragile]
+\begin{verbatim}
+Instalar los requerimientos del proyecto
+
+Para activar el ambiente virtual geodjango ejecute el comando:
+
+$ workon geodjango
+
+Quedando activado el entorno virtual de esta manera.
+
+(geodjango)$
+
+Crear el archivo requerimientos.txt
+vim requerimientos.txt
+
+*** Inicio del archivo requerimientos.txt
+Django==1.11.4
+psycopg2==2.7.1
+pytz==2017.2
+*** fin del archivo requeimientos.txt
+
+Ejecutar el comando de descarga e instalaciÃ³n
+pip install -r requeimientos.txt
+\end{verbatim}
+\end{frame}
+
+\begin{frame}[fragile]
+\begin{verbatim}
+Crear el proyecto geodjango-demo
+
+django-admin startproject geodjango-demo
+
+cd geodjango-demo
+
+Crear base de datos y Migrar los modelos
+
+Como super usuario instalar postgis:
+
+aptitude install postgis
+
+aptitude install postgresql-x.x-postgis-x.x
+
+Nota: las x.x debe ser sustituidad por la versiÃ³n de 
+Postgres instalada
+\end{verbatim}
+\end{frame}
+
+\begin{frame}[fragile]
+\begin{verbatim}
+Ingresar a la consola de postgres con la siguiente orden:
+$ psql
+
+Ejecutar la siguiente sentencia estando en la consola de 
+postgres:
+
+postgres=# CREATE DATABASE geodjango OWNER=postgres;
+postgres=#  \q
+
+$ psql geodjango
+
+geodjango=# CREATE EXTENSION postgis;
+geodjango=# \q
+
+Editar el archivo geodjango-demo/settings.py
+
+INSTALLED_APPS = [
+    ...
+    'django.contrib.gis',
+]
+\end{verbatim}
+\end{frame}
+
+\begin{frame}[fragile]
+\begin{verbatim}
+Modificar la conexiÃ³n para la base de datos:
+
+DATABASES = {
+    'default': {
+        'ENGINE': 'django.contrib.gis.db.backends.postgis',
+        'NAME': 'geodjango',
+        'USER': 'administrador',
+        'PASSWORD': 'clave',
+        'HOST': 'localhost',
+        'PORT': '5432',
+        'ATOMIC_REQUESTS': True, 
+        # Crea transacciones en cada peticion de la vista
+    }
+}
+
+Para migrar los modelos del proyecto se debe usar 
+el siguiente comando:
+
+(geodjango)$ python manage.py makemigrations
+(geodjango)$ python manage.py migrate
+(geodjango)$ python manage.py createsuperusuer
+\end{verbatim}
+\end{frame}
+
+\begin{frame}[fragile]
+\begin{verbatim}
+Creamos la aplicaciÃ³n geolocation
+(geodjango)$ python manage.py startapp geolocation
+
+Creamos el archivos geolocation/urls.py
+# -*- coding: utf-8 -*-
+from django.conf.urls import url
+from .views import *
+urlpatterns = [
+                url(r'^register-poly/',
+                    RegisterPolyView.as_view(),
+                    name="register_poly"),
+                url(r'^list-zipcode/',
+                    ListZipcodeView.as_view(),
+                    name="list_zipcode"),
+                url(r'^delete-zipcode/(?P<pk>\d+)/',
+                    ZipcodeDeleteView.as_view(),
+                    name="delete_zipcode"),
+                url(r'update-zipcode/(?P<pk>\d+)/$',
+                    ZipCodeUpdate.as_view(),
+                    name='update_zipcode')
+              ]
+\end{verbatim}
+\end{frame}
+
+\begin{frame}[fragile]
+\begin{verbatim}
+Modificar el archivo geolocation/views.py
+
+# -*- coding: utf-8 -*-
+from django.contrib import messages
+from django.contrib.messages.views import SuccessMessageMixin
+from django.urls import reverse_lazy
+from django.views.generic.edit import (
+    FormView, DeleteView, UpdateView
+    )
+from django.views.generic import ListView
+
+from .forms import *
+from .models import *
+
+\end{verbatim}
+\end{frame}
+
+\begin{frame}[fragile]
+\begin{verbatim}
+class RegisterPolyView(FormView):
+    form_class = ZipcodeForms
+    template_name = 'geodjango-template.html'
+    success_url = '/geolocation/register-poly/'
+    def form_valid(self, form, **kwargs):
+        new_zipcode = form.save()
+        messages.success(self.request, 
+        "ZipCode %s, registrado con exito" % (str(new_zipcode)))
+        return super(RegisterPolyView, self).form_valid(form)
+class ListZipcodeView(ListView):
+    model = Zipcode
+    template_name = 'geodjango-list.html'
+    paginate_by = 3
+class ZipcodeDeleteView(DeleteView):
+    model = Zipcode
+    success_url = reverse_lazy('geolocation:list_zipcode')
+class ZipCodeUpdate(UpdateView, SuccessMessageMixin):
+    model = Zipcode
+    form_class = ZipcodeForms
+    success_message = 'ZipCode Actualizado con exito'
+    success_url = reverse_lazy('geolocation:list_zipcode')
+\end{verbatim}
+\end{frame}
+
+\begin{frame}[fragile]
+\begin{verbatim}
+Editar el archivo admin.py
+# -*- coding: utf-8 -*-
+from django.contrib.gis import admin
+from .models import *
+admin.site.register(Zipcode, admin.OSMGeoAdmin)
+
+Editar el archivo apps.py
+from django.apps import AppConfig
+class GeolocationConfig(AppConfig):
+    name = 'geolocation'
+
+Editar el archivo forms.py
+# -*- coding: utf-8 -*-
+from django.contrib.gis import forms
+from .models import *
+
+class ZipcodeForms(forms.ModelForm):
+    class Meta:
+        model = Zipcode
+        fields = '__all__'
+\end{verbatim}
+\end{frame}
+
+\begin{frame}[fragile]
+\begin{verbatim}
+    def __init__(self, *args, **kwargs):
+        super(ZipcodeForms, self).__init__(*args, **kwargs)
+        self.fields['code'].widget.attrs.update(
+           {'class': 'form-control','placeholder': 'Zip Code'})
+        self.fields['code'].label = 'Zip Code'
+        self.fields['code'].required = True
+
+        # Se le agrega la ruta donde se construye el mapa 
+        # con el default_zoom
+        self.fields['poly'].widget = 
+         forms.OSMWidget.template_name = 'openlayers-cust.html'
+
+        # Se le agrega al campo los atributos que por defecto 
+        # tiene la ubicacion (lat lon) de Venezuela
+        # Con un zoom por defecto de 5.2 y
+        # Un alto y ancho de 600X400
+        self.fields['poly'].widget = forms.OSMWidget(attrs={
+                         'default_zoom': 5.2, 'map_width': 600,
+                         'map_height': 400, 'default_lat': 8,
+                         'default_lon': -66})
+        self.fields['poly'].label = 'Cordenadas Poligonales'
+        self.fields['poly'].required = True
+\end{verbatim}
+\end{frame}
+
+\begin{frame}[fragile]
+\begin{verbatim}
+Editar el archivo models.py
+# -*- coding: utf-8 -*-
+from django.contrib.gis.db import models
+
+class Zipcode(models.Model):
+    code = models.CharField(max_length=5) #Campo del ZipCode
+    poly = models.PolygonField() #Campo de la poligonal
+    class Meta:
+        ordering = ('code',)
+        verbose_name = 'Zipcode'
+        verbose_name_plural = 'Zipcodes'
+    def __str__(self):
+        return self.code
+class Elevation(models.Model):
+    name = models.CharField(max_length=100)
+    rast = models.RasterField()
+    class Meta:
+        ordering = ('name',)
+        verbose_name = 'Elevation'
+        verbose_name_plural = 'Elevations'
+    def __str__(self):
+        return self.name
+\end{verbatim}
+\end{frame}
+
+\begin{frame}[fragile]
+\begin{verbatim}
+Editar el archivo geodjango-demo/settings.py
+
+INSTALLED_APPS = [
+    ...
+    'django.contrib.gis',
+    'geolocation',
+]
+
+Guardamos y ejecutamos el comando 
+(geodjango)$ python manage.py makemigrations geolocation
+(geodjango)$ python manage.py migrate geolocation
+
+Editamos el Templates para lo cual creamos la carpeta templates
+y creamos los archivos geodjango-template.html y 
+geodjango-list.html
+
+mkdir geolocation/templates
+cd geolocation/templates
+
+\end{verbatim}
+\end{frame}
+
+\begin{frame}[fragile]
+\begin{verbatim}
+Archivo geodjango-list.html
+{% extends "admin/base.html" %}
+{% block title %}Listar Zipcode {% endblock title %}
+{% block branding %}
+    <h1 id="site-name"><a href="{% url 'admin:index' %}">
+    Demo-GeoDjango</a></h1>
+{% endblock %}
+{% block breadcrumbs %}
+    <div class="breadcrumbs">
+    <a href="{% url 'geolocation:register_poly' %}">
+    Registrar ZipCode</a>/
+    <a href="{% url 'geolocation:list_zipcode' %}">
+    Listar ZipCode</a>
+    {% if title %} &rsaquo; {{ title }}{% endif %}
+    </div>
+{% endblock breadcrumbs%}
+{% block content %}
+    <h1>Zip Codes</h1>
+    <table><thead><tr><th>ZipCodes</th>
+                      <th>Coordenadas</th>
+                      <th>Acciones</th></tr></thead>
+\end{verbatim}
+\end{frame}
+
+\begin{frame}[fragile]
+\begin{verbatim}
+    {% for zips in object_list %}
+        <tbody><tr>
+         <td>{{ zips.code }}</td>
+         <td>{{ zips.poly }}</td>
+         <td><a title="Editar" class="changelink" 
+          href="{% url 'geolocation:update_zipcode' zips.pk %}">
+          </a>
+         <a title="Eliminar" class="deletelink" 
+          href="{% url 'geolocation:delete_zipcode' zips.pk %}">
+          </a>
+         </td></tr></tbody>
+    {% empty %}
+        <tbody>
+            <tr><td>No hay zipcode.</td></tr>
+        </tbody>
+    {% endfor %}
+ 
+    </table>
+\end{verbatim}
+\end{frame}
+
+\begin{frame}[fragile]
+\begin{verbatim}
+
+    {% if is_paginated %}
+        <div class="pagination">
+            <span class="page-links">
+                {% if page_obj.has_previous %}
+<a href="/geolocation/list-zipcode/?page=
+{{ page_obj.previous_page_number }}">Anterior</a>
+                {% endif %}
+                <span class="page-current">
+PÃ¡gina {{ page_obj.number }}de{{ page_obj.paginator.num_pages }}
+                </span>
+                {% if page_obj.has_next %}
+<a href="/geolocation/list-zipcode/?page=
+{{ page_obj.next_page_number }}">Siguiente</a>
+                {% endif %}
+          </span>
+        </div>
+    {% endif %}
+{% endblock content %}
+""" Fin del archivo geodjango-list.html
+\end{verbatim}
+\end{frame}
+
+\begin{frame}[fragile]
+\begin{verbatim}
+""" Archivo geodjango-templates.html
+{% extends "admin/base.html" %}
+{% block title %}Registrar Zipcode {% endblock title %}
+{% block extrastyle %}{{ form.media }}{% endblock extrastyle %}
+{% block branding %}  <h1 id="site-name">
+<a href="{% url 'admin:index' %}">Demo-GeoDjango</a></h1>
+{% endblock branding %}
+{% block breadcrumbs %}
+    <div class="breadcrumbs">
+    <a href="{% url 'geolocation:register_poly' %}">
+    Registrar ZipCode</a>
+    <a href="{% url 'geolocation:list_zipcode' %}">
+    Listar ZipCode</a>
+    {% if title %} &rsaquo; {{ title }}{% endif %} </div>
+{% endblock breadcrumbs%}
+{% block content %}
+    <form method="post">{% csrf_token %}
+        <div class="form-row">{{ form.as_p }}</div>
+        <div class="submit-row">
+         <input type="submit" value="Agregar ZipCode" />
+        </div></form>
+{% endblock content %}
+\end{verbatim}
+\end{frame}
+
+\begin{frame}[fragile]
+\begin{verbatim}
+""" Archivo openlayers-cust.html
+
+{% extends "gis/openlayers.html" %}
+{% load l10n %}
+
+{% block options %}{{ block.super }}
+options['default_lon'] = {{ default_lon|unlocalize }};
+options['default_lat'] = {{ default_lat|unlocalize }};
+options['default_zoom'] = {{ default_zoom|unlocalize }};
+{% endblock %}
+
+{% block base_layer %}
+var base_layer = new ol.layer.Tile({source: 
+                                    new ol.source.OSM()});
+{% endblock %}
+
+\end{verbatim}
+\end{frame}
+
+\begin{frame}[fragile]
+\begin{verbatim}
+
+{% block content %}
+    <form method="post">
+    {% csrf_token %}
+        <div class="form-row">
+            {{ form.as_p }}
+        </div>
+        <div class="submit-row">
+<label>&nbsp;</label>
+<input type="submit" value="Agregar ZipCode" />
+        </div>
+    </form>
+{% endblock content %}
+
+""" Fin del archivo geodjango-templates.html
+
+\end{verbatim}
+\end{frame}
+
+\begin{frame}[fragile]
+\begin{verbatim}
+Editar el archivo geodjango-demo/urls.py
+
+from django.conf.urls import url, include
+from django.contrib.gis import admin
+
+urlpatterns = [
+    url(r'^admin/', admin.site.urls),
+    url(r'^geolocation/', include('geolocation.urls', 
+    namespace="geolocation")),
+]
+
+Guardar y ahora se puede ejecutar el comando 
+
+(geodjango)$ python manage.py runserver
+
+Y acceder desde un navegador la direcciÃ³n 
+
+http://localhost:8000/geolocation/register-poly/
+
+\end{verbatim}
+\end{frame}
+
+
 \begin{frame}[plain]
 
