\documentclass[xcolor=dvipsnames]{beamer}
\usetheme{Berkeley}
\usepackage[spanish]{babel}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage{fancyhdr}
\usepackage{graphicx}
\usepackage{mathrsfs}
\usepackage{amsmath}
\usepackage{lmodern}
\usepackage{multimedia}
\usepackage{hyperref}
\usepackage{varioref}
\usepackage{ragged2e}
\usepackage{etoolbox}
\usepackage{lipsum}
\usepackage{fancyvrb}
\fvset{fontsize=\footnotesize}
\RecustomVerbatimEnvironment{verbatim}{Verbatim}{}
\apptocmd{\frame}{}{\justifying}{} % Allow optional arguments after frame.
\usecolortheme[{rgb={0.6,0,0}}]{structure}
\setbeamercovered{transparent}
\setbeamertemplate{items}[ball]
\setbeamertemplate{blocks}[rounded][shadow=true] 
\beamertemplateshadingbackground{gray!50}{white!50}
\newtheorem{Ejemplo}{Django}
\useoutertheme{infolines}
\title []{Framework Django 1.11}
\author{Instructor Ing. Erwin Paredes}
%\logo{ \includegraphics[height=3cm]{figura/logo-blanco2.png}}
\institute{CENDITEL}
\date{\today}

\begin{document}

\section{Cenditel}
\begin{frame}
\maketitle
\end{frame}

\subsection{La Fundación}
\begin{frame}
\begin{block}{Fundación CENDITEL}
\indent   
Somos el Centro Nacional de Desarrollo e Investigación en Tecnologías Libres, cuyas actividades son el desarrollo de proyectos con impacto tecnológico enmarcados en las áreas de Software, Hardware y Telecomunicaciones. 
https://www.cenditel.gob.ve

\end{block}
\end{frame}

\subsection{Finalidad del Curso}
\begin{frame}
\begin{block}{Finalidad}
     
Consolidar la comunidad de desarrollo en software libre alrededor de la tecnología, en este caso el framework de desarrollo Django del lenguaje de programación Python
\end{block}
\end{frame}

\subsection{Contenido del Curso}
\begin{frame}
\begin{block}{Contenido del Curso}
\begin{itemize}
\item 
Introducción
\item 
Configurar ambiente de trabajo
\item 
Crear proyecto
\item 
Crear aplicaciones y estructura del proyecto
\item 
Modelos y migraciones
\item 
Relaciones
\item 
Django shell y Querysets
\item 
Configurar URLs y primera views
\item 
Sistema de plantillas
\item 
Configurar archivos estáticos
\item 
Listar Registros
\item 
Formularios y vista para anexar registros
\item 
Vistas para modificar y eliminar registros
\end{itemize}
\end{block}
\end{frame}


\begin{frame}
\begin{block}{Contenido del Curso}
\begin{itemize}
\item
ListView, CreateView, UpdateView, DeleteView   
\item
Crear Login
\item
Registro de Usuarios
\item
Decorador Login required
\item
Recuperar contraseña por correo
\item
Introducción a conceptos avanzados
\end{itemize}
\end{block}
\end{frame}



\section{Django}
\subsection{Introducción}
\begin{frame}
Django: Es un entorno de trabajo para el desarrollo Web, basado en el lenguaje de programación Python.

Un entorno de trabajo o framework, implica una estructura conceptual y conjunto de herramientas que típicamente son un conjunto de librerías, que permite organizar el desarrollo.

Para el framework Django la estructura conceptual es el denominado MVC (Modelo Vista Controlador), esto es, se organiza el desarrollo en módulos que separan el modelo de datos, la interfaz o vista y el comportamiento.

Por lo que para cada aplicación o módulo que conforma el proyecto se agrupa en lo siguientes archivos:

\begin{itemize}
 \item models.py :Contiene las clases que definen la estructura de datos
 \item views.py  :Contiene la codificación de las funcionalidades que permiten controlar el comportamiento del sistema.
 \item *.html    :Contiene la codificación de la interfaz 
\end{itemize}
\end{frame}

\subsection{Configurar ambiente de trabajo}
\begin{frame}[fragile]

\begin{Large}\textbf{Sitio Oficial}\end{Large}
\begin{verbatim}

https://www.djangoproject.com/

Instalación

https://docs.djangoproject.com/en/1.11/intro/install

Descarga:

https://www.djangoproject.com/download/
\end{verbatim}
\end{frame}

\begin{frame}[fragile]

\begin{Large}\textbf{Instalación}\end{Large}
\begin{verbatim}
// Descomprimir el archivo

tar -xzvf Django1.11.tar.gz

cd Django1.11

python setup.py install

// Comprobar la instalación del framework:

python
import django
django.VERSION

Ctrl + D
\end{verbatim}
\end{frame}

\subsection{Crear proyecto}
\begin{frame}[fragile]

\begin{verbatim}
// Crear el primer proyecto:

django-admin startproject curso

// este comando crea la siguiente infraestructura
de carpetas y archivos:

curso/
    manage.py
    curso/
        __init__.py
        settings.py
        urls.py
        wsgi.py


Configurar la base de datos

\end{verbatim}
\end{frame}

\begin{frame}[fragile]

\begin{verbatim}
// Se debe haber instalado el gestor de la Base de
Datos Postgresql  y la librería de conexión psycopg2
// Creamos la base de datos:
su postgres
psql
CREATE USER administrador;
CREATE DATABASE curso;

// Se edita el archivo curso/settings.py la constante
DATABASES = {
   'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'curso',
        'USER': 'administrador',
        'PASSWORD': 'clave',
        'HOST': '127.0.0.1',
        'PORT': '5432',
  } }
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\begin{verbatim}
// Se guarda y ejecuta el siguiente comando para
crear las tablas iniciales del proyecto:

python manage.py migrate

// Se ejcuta el comando para crear el superusuario o 
usuario administrador del proyecto:

python manage.py createsuperuser

// Se introducen los datos que solicita
// Se ejecuta el siguiente comando para activar el 
servidor de prueba de forma local

python manage.py runserver
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\begin{verbatim}
python manage.py runserver

// Arroja el siguiente mensaje
Performing system checks...

System check identified no issues (0 silenced).

July 26, 2017 - 15:32:30
Django version 1.11.3,using settings 'curso.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

// Abrimos el navegador de preferencia y colocamos la
siguiente dirección para acceder al sistema
administrativo del proyecto:

http://localhost:8000/admin
\end{verbatim}
\end{frame}

\subsection{Crear aplicaciones}
\begin{frame}[fragile]
\begin{verbatim}

http://localhost:8000/admin

// En el debemos autenticarnos con el usuario y
password del superusuario creado en los pasos
anteriores

// Allí podemos gestionar los usuarios del sistema
así como los grupos que evenctualmente se utilizan 
para asignar permisos de acceso.

// En el terminal presionar las teclas Ctrl + C para
interrumpir la ejecución del servidor y así crear 
las aplicaciones del proyecto.

python manage.py startapp encuesta

\end{verbatim}
\end{frame}

\subsection{Modelos}
\begin{frame}[fragile]
\begin{verbatim}
python manage.py startapp encuesta

// Se edita el archivo encuesta/models.py

from django.db import models

class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date =models.DateTimeField('date published')

class Choice(models.Model):
    question = models.ForeignKey(Question, 
               on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)

\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\begin{verbatim}
// Almacenamos y editamos el archivo 
curso/settings.py la constante:

INSTALLED_APPS = [
    ...
    'django.contrib.staticfiles',
    'encuesta',
]

// Para crear las tablas correspondiente de models.py
se ejecuta el comando:

python manage.py makemigrations encuesta

python manage.py migrate encuesta

\end{verbatim}
\end{frame}

\subsection{Relaciones}
\begin{frame}[fragile]
\begin{verbatim}
// Para el manejo de las tablas por medio del 
framework se puede realizar desde el terminal 
con el comando:

python manage.py shell


\end{verbatim}
\end{frame}

\subsection{Django shell y Querysets}
\begin{frame}[fragile]
\begin{verbatim}

// Allí podemos ejecutar las siguientes instrucciones

from encuesta.models import Question, Choice
from django.utils import timezone

Question.objects.all()
q = Question(question_text="Que hay de nuevo?", 
                     pub_date=timezone.now())
q.save()
q.id
q.question_text
q.pub_date
q.question_text = "Q ai d nuevo?"
q.save()

Ctril + D para salir
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\begin{verbatim}
Editamos nuevamente el archivo encuesta/models.py 
para añadir el sigueinte metodo a la clase Question

import datetime

from django.db import models
from django.utils import timezone

class Question(models.Model):
    # ...
    def was_published_recently(self):
        return self.pub_date >= timezone.now() -
                      datetime.timedelta(days=1)

Guardamos y volvemos a terminal:

python manage.py shell

\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\begin{verbatim}
from polls.models import Question, Choice

Question.objects.all()
q = Question.objects.get(pk=1)
q.was_published_recently()

q = Question.objects.filter(id=1)

q = Question.objects.filter(
          question_text__startswith='Q')

from django.utils import timezone
current_year = timezone.now().year
Question.objects.get(pub_date__year=current_year)

Question.objects.get(id=2) Error...
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\begin{verbatim}
q = Question.objects.get(pk=1)
q.choice_set.all()
q.choice_set.create(choice_text='No mucho', votes=0)
q.choice_set.create(choice_text='Muchas cosas' 
                                           ,votes=0)
c = q.choice_set.create(choice_text='De todo un poco'
                                           ,votes=0)

c.question

q.choice_set.all()
q.choice_set.count()

Crtl + D para salir

\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\begin{verbatim}
Incluir el modelo de la aplicación encuesta 
en el sistema admin:

Editamos el archivo encuesta/admin.py
from django.contrib import admin

from .models import Question

admin.site.register(Question)

Guardamos y ejecutamos el servidor 
de prueba nuevamente:

python manage.py runserver

en el navegador http://localhost:8000/admin

\end{verbatim}
\end{frame}

\subsection{Configurar URLs y primera views}
\begin{frame}[fragile]
\begin{verbatim}
Crear la primera vista para acceso del proyecto 
Editamos el archivo encuesta/urls.py

from django.conf.urls import url
from . import views
urlpatterns = [
    # ex: /encueta/
    url(r'^$', views.index, name='index'),
    # ex: /encuesta/5/
    url(r'^(?P<question_id>[0-9]+)/$', 
    views.detail, name='detail'),
    # ex: /encuesta/5/results/
    url(r'^(?P<question_id>[0-9]+)/results/$',
    views.results, name='results'),
    # ex: /encuesta/5/vote/
    url(r'^(?P<question_id>[0-9]+)/vote/$',
     views.vote, name='vote'),
]
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\begin{verbatim}
Editamos el archivo encuesta/views.py:

from django.http import HttpResponse
from .models import Question

def index(request):
    question_list = Question.objects.order_by('-pub_date')[:5]
    output = ', '.join([q.question_text for q in question_list])
    return HttpResponse(output)

def detail(request, question_id):
    return HttpResponse("Question No: %s." % question_id)

def results(request, question_id):
    response = "Results of question %s." 
    return HttpResponse(response % question_id)

def vote(request, question_id):
    return HttpResponse("Voting on question %s." % question_id)
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\begin{verbatim}
Guardamos y ejecutamos el servidor de prueba y 
probamos los enlaces desde el navegador:

python manage.py runserver

En el navegador probamos los siguientes enlaces:

http://localhost:8000/encueta
http://localhost:8000/encueta/1
http://localhost:8000/encueta/1/result
http://localhost:8000/encueta/1/vote

\end{verbatim}
\end{frame}

\subsection{Sistema de plantillas}

\begin{frame}[fragile]
\begin{verbatim}
Uso del plantillas:

Creamos la siguiente estructura

cd encuesta
mkdir templates
mkdir templates/encuesta

y editamos el archivo index.html allí

gedit encuesta/templates/encuesta/index.html

\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\begin{verbatim}
{% if question_list %}
    <ul>
    {% for question in question_list %}
        <li>
         <a href="/encuesta/{{ question.id }}/">
          {{
            question.question_text
          }}
         </a>
        </li>
    {% endfor %}
    </ul>
{% else %}
    <p>No hay encuestas.</p>
{% endif %}
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\begin{verbatim}
Guardamos y modificamos el archivo encuesta views.py 
para que utilice la plantilla

from django.http import HttpResponse
from django.template import loader

from .models import Question


def index(request):
    question_list = Question.objects.order_by('-pub_date')[:5]
    template = loader.get_template('polls/index.html')
    context = {
        'question_list': question_list,
    }
    return HttpResponse(template.render(context, request))

\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\begin{verbatim}
o utilizando la shortcuts render

from django.shortcuts import render

from .models import Question


def index(request):
    question_list = Question.objects.order_by('-pub_date')[:5]
    context = {'question_list': question_list}
    return render(request, 'polls/index.html', context)


\end{verbatim}
\end{frame}

\subsection{Configurar estáticos}
\begin{frame}[fragile]
\begin{verbatim}
Descargar plantillas prediseñadas, por ejemplo:

https://adminlte.io/

Copiar los directorios ccs y js en los en la carpeta static

Copiar los archivo *.html en la carpeta templates

Editar index.html y cambiar los enlaces a cada archivo en:

<link rel="stylesheet" 
href="{% static 'css/DataTables/jquery.dataTables.min.css' %}">

\end{verbatim}
\end{frame}

\subsection{Listar Registros}
\begin{frame}[fragile]
\begin{verbatim}
Creamos el archivo ajax.py

# -*- encoding: utf-8 -*-
from django.conf import settings
from django_datatables_view.base_datatable_view import (
   BaseDatatableView)
   
from django.contrib.auth.models import (
    User)

class ListUsersAjaxView(BaseDatatableView):
    model = User
    columns = ['pk','first_name','last_name','username','email',
               'date_joined', 'last_joined' ]
    order_columns = ['pk', 'username']
    max_display_length = 500
    
    def __init__(self):
        super(ListUsersAjaxView, self).__init__()

    def get_initial_queryset(self):
        return self.model.objects.all()
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\begin{verbatim}
def prepare_results(self, qs):
  json_data = []
  for item in qs:
    json_data.append([
      username,
     "{0} {1}".format(str(item.first_name),str(item.last_name)),
      item.email,
      item.date_joined.strftime("%Y-%m-%d %H:%M:%S"),
      last_login                
    ])
            
  return json_data
# Fin del archivo ajax.py

#En el archivo urls.py anexar las siguientes lineas
from .ajax import *

urlpatterns = [
    ....
url(r'^listar-users/$', ListUsersAjaxView.as_view(),
        name="listar_users"),
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\begin{verbatim}
Se anexa el siguiente código el archivo index.html
En la parte visual:

<div id="datatable"></div>

Y en la parte de código javascript

<script type="text/javascript">
$(document).ready(function() {
   $('#datatable').dataTable({
        "processing": true,
        "serverSide": true,
        "ajax": {% url 'listar_user'%},
        language: {url: JSON_DATA}
        });
    $('#datatable')
        .removeClass('display')
        .addClass('table table-striped table-bordered');
});
</script>
\end{verbatim}
\end{frame}

\subsection{Anexar registros}
\begin{frame}[fragile]
\begin{verbatim}
Creamos el método en el archivo views.py

def AnexarRegistro(request):
    if request.method == 'POST':
        
        vusername = request.POST['username']
        u = User(username = vusername)
        u.save()
        message = _("El usuario fue creado")
        template = loader.get_template('personal/profile.html')
    context = {'message':message}
    return HttpResponse(template.render(context, request))
       
\end{verbatim}
\end{frame}

\subsection{Modificar y eliminar registros}
\begin{frame}[fragile]
\begin{verbatim}
@login_required
def change_profile(request):
    """ Cambiar perfil de usuario
    """
    if request.method == 'POST':
        user_id = request.POST['user_id']
        personal = User.objects.get(user_id=request.user.id)               
        personal.first_name = request.POST['fname']
        personal.last_name = request.POST['lname']
        personal.email = request.POST['email']
        personal.is_active = request.POST.get('is_active')
        personal.user.save()
        
        message = _("The profile change was made")
	context = {'personal':personal,'message':message,}
    template = loader.get_template('personal/profile.html')
    return HttpResponse(template.render(context, request))

\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\begin{verbatim}
@login_required
def delete_personal(request):
    """ Delete users 
    """
    id = json.loads(request.POST['seleccionados'])
    print id 
 
    for id_values in id:
        if id_values["id"] != "0":
	           
            u = User.objects.get(pk=int(id_values["id"]))
            u.delete()   
	   
    return redirect('personal')
\end{verbatim}
\end{frame}

\subsection{View's}
\begin{frame}[fragile]
\begin{verbatim}
####  ListView

# En el archivo views.py

from django.views.generic.list import ListView
from django.utils import timezone

from articles.models import Article

class ArticleListView(ListView):

    model = Article

    def get_context_data(self, **kwargs):
        context = super(ArticleListView, 
                        self).get_context_data(**kwargs)
        context['now'] = timezone.now()
        return context

\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\begin{verbatim}

# En el archivo urls.py
from django.conf.urls import url

from article.views import ArticleListView

urlpatterns = [
 url(r'^$',ArticleListView.as_view(),name='article-list'),
]

# El template
<h1>Articles</h1>
<ul>
{% for article in object_list %}
    <li>
    {{ article.pub_date|date }} - {{ article.headline }}
    </li>
{% empty %}
    <li>No articles yet.</li>
{% endfor %}
</ul>
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\begin{verbatim}
#### DetailView

# En el archivo views.py

from django.views.generic.detail import DetailView
from django.utils import timezone

from articles.models import Article

class ArticleDetailView(DetailView):

    model = Article

    def get_context_data(self, **kwargs):
        context = super(ArticleDetailView, self).
                  get_context_data(**kwargs)
        context['now'] = timezone.now()
        return context
        
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\begin{verbatim}

# En el archivo urls.py

from django.conf.urls import url

from article.views import ArticleDetailView

urlpatterns = [
 url(r'^(?P<slug>[-\w]+)/$',ArticleDetailView.as_view(),
                            name='article-detail'),
]

# El template

<h1>{{ object.headline }}</h1>
<p>{{ object.content }}</p>
<p>Reporter: {{ object.reporter }}</p>
<p>Published: {{ object.pub_date|date }}</p>
<p>Date: {{ now|date }}</p>
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\begin{verbatim}
#### CreateView

from django.views.generic.edit import CreateView
from myapp.models import Author

class AuthorCreate(CreateView):
    model = Author
    fields = ['name']

# En el template

<form action="" method="post">{% csrf_token %}
    {{ form.as_p }}
    <input type="submit" value="Save" />
</form>

\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\begin{verbatim}
#### UpdateView

from django.views.generic.edit import UpdateView
from myapp.models import Author

class AuthorUpdate(UpdateView):
    model = Author
    fields = ['name']
    template_name_suffix = '_update_form'
    
# En el template

<form action="" method="post">{% csrf_token %}
    {{ form.as_p }}
    <input type="submit" value="Update" />
</form>

\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\begin{verbatim}
#### DeleteView

from django.views.generic.edit import DeleteView
from django.urls import reverse_lazy
from myapp.models import Author

class AuthorDelete(DeleteView):
    model = Author
    success_url = reverse_lazy('author-list')
    
# En el template

<form action="" method="post">{% csrf_token %}
    <p>Are you sure you want to delete "{{ object }}"?</p>
    <input type="submit" value="Confirm" />
</form>

\end{verbatim}
\end{frame}

\subsection{Crear Login}
\begin{frame}[fragile]
\begin{verbatim}
Creamos la aplicacion user desde la consola:

python manage.py startapp user

Editamos el archivo user/views.py:

# -*- coding: utf-8 -*-

from django.shortcuts import render
from django.contrib import messages
from django.contrib.auth import (
    authenticate, logout, login
)
from django.contrib.auth.models import (
    Group, Permission, User
)

class LoginView(FormView):
    form_class = FormularioLogin
    template_name = 'users.login.html'
    success_url = '/inicio/'
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\begin{verbatim}
def form_valid(self, form):
        
    usuario = form.cleaned_data['usuario']
    contrasena = form.cleaned_data['contrasena']
    usuario = authenticate(username=usuario,password=contrasena)
        
    if usuario is not None:
        login(self.request, usuario)
        messages.info(self.request,'Bienvenido %s has ingresado\
                                    Sistema con el usuario %s \
                                    ' % (usuario.first_name,
                                         usuario.username))
    else:
        self.success_url = reverse_lazy('users:login')
        messages.warning(self.request,'Verifique su nombre y \
                                       contraseña\
                                      y vuelve a intertar')

    return super(LoginView, self).form_valid(form)
 
\end{verbatim}
\end{frame}

\subsection{Registro de Usuarios}
\begin{frame}[fragile]
\begin{verbatim}
#### Crear Permisos desde el shell ejecutar

from myapp.models import BlogPost
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType

content_type = ContentType.objects.get_for_model(BlogPost)
permission = Permission.objects.create(
    codename='can_publish',
    name='Can Publish Posts',
    content_type=content_type,
)

\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\begin{verbatim}

from django.contrib.auth.models import Permission, User
from django.contrib.contenttypes.models import ContentType
from django.shortcuts import get_object_or_404

from myapp.models import BlogPost

def user_gains_perms(request, user_id):
    user = get_object_or_404(User, pk=user_id)
    # any permission check will 
    #cache the current set of permissions
    user.has_perm('myapp.change_blogpost')

    content_type=ContentType.objects.get_for_model(BlogPost)
    permission = Permission.objects.get(
        codename='change_blogpost',
        content_type=content_type,
    )
    user.user_permissions.add(permission)

\end{verbatim}
\end{frame}

\subsection{Login required}
\begin{frame}[fragile]
\begin{verbatim}

from django.contrib.auth.decorators import 
  login_required, permission_required
from django.views.generic import TemplateView

from .views import VoteView

urlpatterns = [
    url(r'^about/$', login_required(
           TemplateView.as_view(template_name="secret.html"))),
    url(r'^vote/$', permission_required(
           'polls.can_vote')(VoteView.as_view())),
]

\end{verbatim}
\end{frame}

\subsection{Recuperar contraseña por correo}
\begin{frame}[fragile]
\begin{verbatim}
def newpassword(request):
    puser = request.POST['puser']
    try:
        user = User.objects.get(username=puser)
        randompass = ''.join([choice(
        '1234567890qwertyuiopasdfghjklzxcvbnm') 
        for i in range(10)])
        print randompass
        subject = _('System: New Password')
        message = _('Your password is reset, new password: ')
                    + randompass
        user.email_user("subject","message")
        user.set_password(randompass)
        user.save()
    except:
        print "error send mail"
        mensaje = _("User not found")
    return redirect('/authenticate/signin')
 
\end{verbatim}
\end{frame}

\subsection{Conceptos avanzados}
\begin{frame}[fragile]
\begin{verbatim}
Otros conceptos

* Internacionalización
* Zonas Horarias
* Servidor Web
* Geodjango
* Django Rest

 Entre otros...

\end{verbatim}
\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]

  
      \begin{center}

        \font\endfont = cmss10 at 15.40mm
        \color{Brown}
        \endfont 
        \baselineskip 20.0mm

        CENDITEL

      \end{center}    

    
\end{frame}


\end{document}
