Spring Boot + Vue JS

cafe-151346_640

En esta ocasión veremos como usar Vue JS en una aplicación Spring Boot.

Creamos nuestra tabla contacto.

contacto.sql

CREATE DATABASE IF NOT EXISTS prueba;

USE prueba;

CREATE TABLE IF NOT EXISTS contacto(id int auto_increment primary key, nombre varchar(100), telefono varchar(12) not null, fecha datetime);

Insertamos algunos valores.

INSERT INTO contacto (nombre,telefono,fecha) VALUES ('Daniel Alcantara','76662323', now()), ('Tomas Torres','5559099', now());

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.codemonkey</groupId>
	<artifactId>servidor</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>

	<name>servidor</name>
	<description>Servidor de servicio web</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.5.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web-services</artifactId>
		</dependency>

		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-tomcat</artifactId>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		
		<dependency>
		    <groupId>org.springframework.boot</groupId>
	        <artifactId>spring-boot-starter-web-services</artifactId>
		</dependency>
		<dependency>
		    <groupId>wsdl4j</groupId>
	        <artifactId>wsdl4j</artifactId>
		</dependency>

        <dependency>
		   <groupId>org.slf4j</groupId>
           <artifactId>slf4j-api</artifactId>
           <version>1.6.1</version>
		</dependency>

        <dependency>
		  <groupId>org.springframework.data</groupId>
		  <artifactId>spring-data-rest-core</artifactId>
		  <version>3.1.1.RELEASE</version>
		</dependency>

	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>


<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>jaxb2-maven-plugin</artifactId>
    <version>1.6</version>
    <executions>
      <execution>
        <id>xjc</id>
        <goals>
          <goal>xjc</goal>
        </goals>
      </execution>
    </executions>
    <configuration>
      <schemaDirectory>${project.basedir}/src/main/resources</schemaDirectory>
      <outputDirectory>${project.basedir}/src/main/java/com/codemonkey/clases</outputDirectory>
      <clearOutputDir>false</clearOutputDir>
    </configuration>
  </plugin>


		</plugins>
	</build>


</project>

Nuestro archivo application.yml tendrá el siguiente aspecto:
application.yml

#BANNER
banner:
   charset: UTF-8
   location: banner.txt

spring:
   thymeleaf:
      cache: false
      check-template: true
      check-template-location: true
      content-type: text/html
      enabled: true
      encoding: UTF-8
      suffix: .html
   jpa:
      generate-ddl: true
      database-platform: org.hibernate.dialect.MySQL5Dialect
      show-sql: false
      hibernate.ddl-auto: update
      hibernate.naming-strategy: org.hibernate.cfg.ImprovedNamingStrategy
   servlet.multipart.max-file-size: 128KB
   servlet.multipart.max-request-size: 128KB
   http.multipart.enabled: false
   datasource.url: jdbc:mysql://localhost:3306/prueba?useSSL=false
   datasource.driver-class-name: com.mysql.jdbc.Driver
   datasource.username: root
   datasource.password: root

Nuestra entidad Contacto.java. Usaremos la librería lombok para ahorrar escribir código.

package com.codemonkey.model;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Setter;
import lombok.ToString;
import lombok.Getter;
import lombok.NoArgsConstructor;
import java.time.LocalDate;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.GenerationType;
import javax.persistence.Table;


@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
@Table(name="contacto")
@Entity(name="Contacto")
public class Contacto implements java.io.Serializable{
    private static final long serialVersionUID = 7526472295622776147L;
    
    @Id
    @GeneratedValue(strategy= GenerationType.AUTO)
    @Getter @Setter public int id;
    @Column(name="nombre")
    @Getter @Setter public String nombre;
    @Column(name="telefono")
    @Getter @Setter public String telefono; 
    @Column(name="fecha")
    @Getter @Setter public LocalDate fecha;
}

Ahora un repositorio.
ContactoCrudRepository.java

package com.codemonkey.repository;

import java.util.List;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import com.codemonkey.model.Contacto;

public interface ContactoCrudRepository extends CrudRepository{

    @Query(value="SELECT * FROM contacto ORDER BY id ",nativeQuery=true)
    public List<Contacto> getAllContactos(); 
}

Es necesario notar que dentro de la anotación @Query podemos declarar una consulta SQL nativa. En est caso SELECT * FROM contacto ORDER BY id.

El siguiente paso es declarar un servicio y su implementación.

package com.codemonkey.service;

import java.util.List;
import com.codemonkey.model.Contacto;

public interface ContactoCrudService{
    public List<Contacto> getAllContactos();
}

La implementación de este servicio sería el siguiente:

package com.codemonkey.service.impl;

import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
//import org.springframework.transaction.annotation.Transactional;

import com.codemonkey.repository.ContactoCrudRepository;
import com.codemonkey.service.ContactoCrudService;
import com.codemonkey.model.Contacto;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


@Service("contactoCrudService")
public class ContactoCrudServiceImpl implements ContactoCrudService{
    private final Logger LOGGER = LoggerFactory.getLogger(ContactoCrudServiceImpl.class);

    @Autowired
    private ContactoCrudRepository contactoCrudRepository;
    
    @Override
    public List<Contacto&gt getAllContactos(){
        LOGGER.info("--Has entrado a getAllContactos");
        return contactoCrudRepository.getAllContactos();
    }
} 

Creamos el ContactoRestController.java

package com.codemonkey.controller;

//import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import com.codemonkey.model.Contacto;
import com.codemonkey.service.ContactoCrudService;


@RestController
@RequestMapping("/rest")
public class ContactoRestController{

    private final Logger LOGGER = LoggerFactory.getLogger(ContactoRestController.class);
       
    //@Qualifier("contactoService")
    @Autowired
    private ContactoCrudService contactoCrudService;

    //http:localhost:8080/rest/contactosRest
    @GetMapping("/contactosRest")
    public List<Contacto&gt getAllContactos(){
        LOGGER.info("--Has entrado a http://localhost:8080/rest/contactosRest");
        return contactoCrudService.getAllContactos();
    }
}

Ahora una vista. Antes deberíamos aclarar que debemos la importar tres archivos necesarios para trabajar con Vue JS.

<!--Vue JS -->
<script
  src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js">
</script>
<script
  src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.21.1/babel.min.js">
</script>
<!--axios-->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

contactosVueJS.html

<!DOCTYPE html>
<html lang="es"
      xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org">
    <head>
     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1"/>
        <title>Contactos</title>
        <script type="text/javascript" src="/js/funciones.js"></script>
        <link rel="stylesheet" type="text/css" media="all" href="css/estilos.css" th:href="@{css/estilos.css}" />
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"/>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js"></script>
  <!--Vue JS -->
<script
  src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js">
</script>
<script
  src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.21.1/babel.min.js">
</script>
<!--axios-->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

    </head>
    <body>
<div class="jumbotron text-center">
   <h1 align="center" class="bg-dark text-white">Contactos</h1><br/>
   <a href="#" th:href="@{/proyecto/home}" title="regreso">Home</a>
</div>

<div id="my_app">    
    <div class="table-responsive">
        <table class="table table-dark table-striped" style="font-family: Chakra Petch">
            <thead >
                <tr>
                    <th>Nombre</th>
                    <th>Teléfono</th>
                </tr>
            </thead>
            <tbody>
                <tr v-for="data in contactos">
                    <td> <p contenteditable="true">{{ data.nombre }} </p></td>
                    <td><p contenteditable="true">{{ data.telefono }}</p></td>
                    
                </tr>
            </tbody>
        </table></div>

</div>

<script>
var my_app = new Vue({
    el:'#my_app',
    data(){
        return {
            contactos:[]
        };
    },
    methods:{
        getContactos(){
            axios
            .get('http://localhost:8080/rest/contactosRest')
            .then((data) => {
                this.contactos = data.data
            });
        }
    },
    mounted(){
        this.getContactos()
    },
});
</script>
</body>
</html>

En el fragmento de código javascript podemos analizar lo siguiente

//Creamos un objeto tipo Vue y sus atributos, en este caso el id será "my_app"
   var my_app = new Vue({
    el:'#my_app',
    data(){
        return {
            contactos:[]
        };
    },   //Declaramos un método getContactos() que hace una invocación
// al método get(URL) de axios, en esa URL esta nuestro servicio rest
    methods:{
        getContactos(){
            axios
            .get('http://localhost:8080/rest/contactosRest')
            .then((data) => {
                this.contactos = data.data
            });
        }
    },
    mounted(){
        this.getContactos()
    },
});

Dentro del fragmento HTML se puede observar lo siguiente:

<div id="my_app">    
    <div class="table-responsive">
        <table class="table table-dark table-striped" style="font-family: Chakra Petch">
            <thead >
                <tr>
                    <th>Nombre</th>
                    <th>Teléfono</th>
                </tr>
            </thead>
            <tbody>
                <tr v-for="data in contactos">
                    <td> <p contenteditable="true">{{ data.nombre }} </p></td>
                    <td><p contenteditable="true">{{ data.telefono }}</p></td>
                    
                </tr>
            </tbody>
        </table></div>

</div>

En esta parte accedemos a los atributos nombre y telefono:

{{ data.nombre }}
{{ data.telefono }}

¡Feliz código!

Advertisements

Clases , herencia e interfaces en Typescript

code-3337044_640

Typescript es un lenguaje de tipado estático muy parecido a Java. Al igual que Java posee tipos básicos de datos(number,string,boolean, etc.) y tipos clase (new Number(), new String(), etc.). La creación de clases también es muy similar.

Herencia.

Una clase padre puede heredar atributos y métodos a una clase hija.

Clase padre/superclase Abstracta.

abstract class Abstracta{
	abstract nada():void;
}

Dentro de la superclase Abstracta definimos un método abstracto llamando nada. Recordar que un método abstracto no necesita un cuerpo, sólo la firma(nombre del método y tipo).

Y tendremos dos clases hijas/subclases Hijo e Hija. Por obligación y contrato las subclases deben adoptar los atributos y comportamiento de la superclase.

class Hijo extends Abstracta{
	nada():void{
		console.log("Nada en hijo")
	}
}

class Hija extends Abstracta{
	nada():void{
		console.log("Nada en hija");
	}
}

Observamos que ambas clases implementan el método nada como a ellas les conviene. Ahora las instancias.

let hijo:Hijo=new Hijo();
let hija:Hija=new Hija();
hijo.nada();//Nada en hijo
hija.nada();//Nada en hija

Una clase abstracta no puede ser instanciada, su función es que otras clases hereden de ella.

Recordar que no podemos hacer algo como esto:

//Esto no se puede/debe hacer:
let abstracta: Abstracta= new Abstracta();
//La finalidad de una clase abstract es que hereden de ella,
// no se puede instanciar

El compilador nos dirá que no es posible instanciar una clase abstracta (al igual que en Java).

Interfaces

Una interface es una clase totalmente abstracta. Se pueden definir métodos sin cuerpo.

Síntaxis:

export interface NombreInterface{
   //...
}

Crearemos una interface llamada Servicio con un método (abstract) denominado operacion con dos parámetros.

interface Servicio{
	operacion(x:number,y:number):number;
}

Ahora crearemos dos clases que implementarán el método de la interface Servicio.


/*La clase Suma sumará dos números*/
class Suma implements Servicio{
	operacion(x:number,y:number):number{
		return x+y;
	}
}

/*La clase IMC calculará el índice de masa corporal de una persona*/
class IMC implements Servicio{
	operacion(peso:number,talla:number):number{
		return peso/(talla*talla);
	}
}


/*instanciamos a la clase Suma*/
let suma:Suma=new Suma();

/*instanciamos a la clase IMC*/
let imc:IMC=new IMC();

/*Mostramos los resultados de las operaciones*/
console.log(suma.operacion(3,6));//9
console.log(imc.operacion(60,1.55));//24.973985

¡Feliz código!

Typescript ::Clases

flat-2126884_1280

En post anteriores (uno y dos) vimos como crear, compilar y ejecutar un proyecto usando Typescript , ahora veremos un concepto muy importante: las clases.

Una clase básicamente es el modelo que posee atributos y métodos, y un objeto es una instancia de ese modelo.

Síntaxis

Clase ref = new Constructor();

Con Typescript podemos crear clases de manera similar a los lenguajes orientados a objetos como Java y C# (entre otros más).

En nuestro proyecto del post anterior teníamos el siguiente directorio:

 proyecto/src/index.ts
 proyecto/src/modelo
 proyecto/tsconfig.json
 proyecto/dist

Es importante editar el archivo tsconfig.json
tsconfig.json

{
  "compilerOptions": {
    "target": "es5",                         
    "module": "commonjs",                   
    "sourceMap": true, 
    "outDir": "./dist", 
    "strict": true,  
    "esModuleInterop": true   
  }
}

 

 

Ahora bien, crearemos dos clases Punto (punto.ts) y PuntoColor (puntocolor.ts)

 proyecto/src/index.ts
 proyecto/src/modelo/punto.ts
 proyecto/tsconfig.json
 proyecto/dist

punto.ts

export class Punto{
	x: number;
	y: number;

	constructor(x:number,y:number){
		this.x = x;
		this.y = y;
	}

	getPunto(){
		return "Punto("+this.x+","+this.y+")";
	}
}

Nota: usaremos export para definirla como módulo y poder importarla en index.ts.

Haremos lo mismo:

 proyecto/src/index.ts
 proyecto/src/modelo/punto.ts
 proyecto/src/modelo/puntocolor.ts
 proyecto/tsconfig.json
 proyecto/dist

puntocolor.ts

import {Punto} from "./punto";

export class PuntoColor extends Punto{
	color:string;
	constructor(x:number, y:number,color:string){
		super(x,y);
		this.color = color;
	}

	getPuntoColor(){
		return "PuntoColor("+this.color+","+this.x+","+this.y+")";
	}
}

Es importante notar que usamos extends para señalar que PuntoColor es clase hija de Punto.

    Punto <- Clase padre
     |
  PuntoColor <- Clase hija

Importaremos ambas clases en el archivo index.ts usando import muy al estilo de lenguajes como Java, Python, etc.

import {Clase} from "./directorioDondeSeEncuentraClase/clase";

Nota: A pesar que definimos el nombre del archivo en minúsculas, es necesario respetar la síntaxis del lenguaje.

index.ts

//Importamos ambas clases, respetando el uso de mayúsculas
import {Punto} from "./modelo/punto";
import {PuntoColor} from "./modelo/puntocolor";

//instanciamos clase Punto
let my_punto: Punto = new Punto(2,4);
console.log("Salida: ",my_punto.getPunto());

//instanciamos clase PuntoColor
let my_puntoColor : PuntoColor = new PuntoColor(4,7,"Verde");
console.log("Salida: ",my_puntoColor.getPuntoColor());

Compilamos:

$ tsc --watch

Ejecutamos:

$ node dist/

Tipos básicos en Typescript

ec564-shomecode4

Typescript es un lenguaje de programación que compila a código javascript. La extensión que usa es la *.ts (Ej. nodo.ts, gato.ts, etc.)

En el post anterior se habló de su instalación y un ejemplo básico. En esta ocasión crearemos un archivo llamado index.ts mostrando los tipos básicos.

Antes de nada creamos un directorio y nos ubicamos en el:

$ mkdir basico
$ cd basico

Iniciamos un proyecto con tsc –init y listamos el directorio para ver el archivo generado.

$ tsc --init
$ ls

El archivo generado se llama tsconfig.json. Debemos modificarlo para que nos quede de la siguiente forma.

tsconfig.json

{
  "compilerOptions": {
    "target": "es5",                          
    "module": "commonjs",                    
    "sourceMap": true,                    
    "outDir": "./dist",                       
    "strict": true,                           
    "esModuleInterop": true                   
  }
}

Dentro del directorio principal (basico) debemos tener una carpeta src. Ahí crearemos el archivo index.ts.

En Typescript tenemos tipos number, string, boolean, etc. Recodermos que es un lenguaje de tipado estático (al menos esa es la idea) y por ende es necesario, en algunos casos, delarar el tipo de variable a usar.

Una declaración sencilla (declarando una variable tipo ‘Int’):

let entero: number = 33;

Un tipo string y/o char:

let caracter: string = 'X';
let cadena: string = "En un lugar lejano del viejo oeste.";

Un tipo booleano:

let booleano: Boolean;
booleano = false;

Un tipo null e undefined:

let indefinido = undefined;
let nulo = null;

También podemos definir arreglos:

//Un arreglo tipo 'Int'
let arregloEnteros : Array<number> ;
arregloEnteros=[1,2,3,4,5];

//Un arreglo tipo string
let arregloString : Array<string> = ["A","B","C"];

Para recorrer estos arreglos podemos usar el clásico for o la forma ‘for each’:

//for clásico
for(var i=0 ; i < arregloEnteros.length; i++){
	console.log(arregloEnteros[i]);
}

//for for each
console.log("foreach:");
for(let arr of arregloString){
	console.log(arr);
}

Código completo:
index.ts

let caracter: string = 'X';
let entero: number = 33;
let binario: number = 0b11101 ;
let flotante: number = 34.55;
let cadena: string = "En un lugar lejano del viejo oeste.";
let booleano: boolean = false;
let indefinido = undefined;
let nulo = null;
let arregloEnteros : Array<number>
arregloEnteros=[1,2,3,4,5];
let arregloString : Array<string> = ["A","B","C"];
console.log("Typescript funcionando!!");
console.log("Caracter: ",caracter);
console.log("Entero: ",entero);
console.log("Binario: ",binario);
console.log("Flotante: ",flotante);
console.log("Cadena: ",cadena);
console.log("Booleano: ",booleano);
console.log("Undefined: ",indefinido);
console.log("Null: ",nulo);
console.log("for clasico:");
for(var i=0 ; i < arregloEnteros.length; i++){
	console.log(arregloEnteros[i]);
}
console.log("foreach:");
for(let arr of arregloString){
	console.log(arr);
}

Compilamos con:

$ tsc --watch

Ejecutamos con:

$ node dist/

Si no marca ningún error nos debería mostrar lo siguiente:

typescript

Sinatra: Hola, mundo!

frank-sinatra-3525676_640

Instalando Sinatra y dependencias

$ sudo apt-get update

$ sudo gem install sinatra

$ sudo gem install haml

$ sudo gem install bundler

Crear archivo Gemfile (sin extensión)

$ nano Gemfile
source :rubygems

gem 'sinatra', :git => 'git://github.com/sinatra/sinatra.git'
$ bundle install

Crear un Hola, mundo con Sinatra

hola.rb

require 'sinatra'

require 'rubygems'

require 'bundler/setup'

get '/sinatra' do

"
<h1> Hola, Sinatra!</h1>
"

end

Ejecutar aplicación:

$ ruby hola.rb

Abrir el navegador en http://localhost:4567/sinatra

Creando un proyecto y app con Django(2)

robotics-2180263_1920

En el post pasado de Django vimos como crear un proyecto y una aplicación (app). Ahora veremos como crear un super usuario para gestionar nuestra BD (en SQLite3).

Abrimos una terminal y tecleamos:

$ python manage.py createsuperuser

Se te pedirá un nombre de usuario, correo electrónico y la clave de usuario.

Migramos (para sincronizar los cambios y creación de la BD)

$ python manage.py migrate

Ejecutamos y abrimos el navegador en http://localhost:8000/admin/

$ python manage.py runserver

Te direccionará a una ventana de administrador donde podrás ver Grupos y Usuarios registrados. En el próximo post registraremos los modelos (entidades) creadas previamente en el post anterior.

Creando un proyecto y app en Django (1)

simple

En el anterior post sobre Django vimos como crear un proyecto.  En está ocasión crearemos una aplicación. Para ello abrimos una terminal y tecleamos lo siguiente:

$ django-admin startproject computers && cd computers

Con esto creamos un proyecto llamado computers.  Ahora creamos una app (denominada computadoras).

$ python manage.py startapp computadoras

Te creará un proyecto con la siguiente estructura:

computers
├───manage.py
└───computers
    ├───settings.py
    ├───urls.py
    ├───wsgi.py
    ├───__init__.py
└───computadoras
    ├───admin.py
    ├───__init__.py
    ├───models.py
    ├───urls.py
    ├───test.py
    ├───views.py

Editamos computers/settings.py y agregamos la app creada (computadoras).

INSTALLED_APPS = ( 
   #... 
   'computadoras', 
)

Configuramos además la base de datos en sqlite3.

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

Configuramos idioma y carpeta de archivos estáticos (static)

#...
LANGUAGE_CODE = 'es'
TIME_ZONE = 'America/Mexico_City'
USE_I18N = True
USE_L10N = True
USE_TZ = True
STATIC_URL = '/static/'

PROJECT_DIR = os.path.dirname(os.path.abspath(__file__))
STATIC_ROOT = os.path.join(PROJECT_DIR, 'static')

PROJECT_NAME="Sistema de administracion de computadoras"

Dentro de la carpeta computadoras tenemos un archivo llamado models.py y nos servirá para ccrear nuestros modelos (clases/entidades) de nuestra BD.

Definiremos tres:

  • Departamento
  • Equipo
  • Usuario

Departamento tendrá dos campos: area y responsable.

class Departamento(models.Model):
    area = models.CharField(max_length=50)
    responsable = models.CharField(max_length=50)

#Esto equivale al toString() de Java
    def __str__(self):
        return "Departamento{id:"+str(self.id)+", area:"+self.area+", responsable:"+self.responsable+"}"

Equipo tendrá los siguientes campos: bien, arrendado, asignado, ….

class Equipo(models.Model):
    #user = models.ForeignKey('auth.User', on_delete=models.CASCADE)
    bien = models.CharField(max_length=50,default='MXL4332-')
    arrendado = models.CharField(max_length=50,default='77')
    asignado = models.IntegerField(default=0)
    ip = models.GenericIPAddressField(default='148.215.24.1')
    dns = models.GenericIPAddressField(default='148.215.1.1')
    red = models.CharField(max_length=50)
    OPERATIVO_CHOICES = (
        ('Windows XP', 'Windows XP'),
        ('Windows 7', 'Windows 7'),
        ('Windows Vista', 'Windows Vista'),
        ('Windows 8', 'Windows 8'),
        ('Windows 10', 'Windows 10'),
        ('Linux OS', 'Linux OS'),
        ('Mac OS X','Mac OS X'),
        ('No especificado','No especificado'),
    )

    TIPO_CHOICES = (
        ('Escritorio', 'Escritorio'),
        ('Portatil', 'Portatil'),
        ('No especificado','No especificado'),
    )

    PISO_CHOICES = (
        ('PISO 1', 'PISO 1'),
        ('PISO 2', 'PISO 2'),
        ('PISO 3','PISO 3'),
        ('PISO 4','PISO 4'),
        ('PISO 0','PISO 0'),
    )

    operativo = models.CharField(max_length=50,choices=OPERATIVO_CHOICES, default='Windows 8')
    tipo = models.CharField(max_length=50,choices=TIPO_CHOICES, default='Escritorio')
    maquina = models.CharField(max_length=50,default='PC77')
    dominio = models.CharField(max_length=50, default='PC77')
    modelo = models.CharField(max_length=50)
    administrador = models.CharField(max_length=50, default='SOPTEC REDALYC')
    ubicacion = models.CharField(max_length=50,choices=PISO_CHOICES, default='PISO 2')
    actualizada = models.BooleanField(default=False)
    departamento = models.ForeignKey(Departamento)

    def __str__(self):
        actualizada = "Actualizada" if self.actualizada==True else "No actualizada"
        return "Computadora{id:"+str(self.id)+",bien:"+ self.bien +", asignado:"+str(self.asignado)+", Ip:"+self.ip +", Dns:"+self.dns+", red:"+self.red+", operativo:"+self.operativo+", tipo:"+self.tipo+", maquina:"+self.maquina+", dominio:"+self.dominio+", modelo:"+self.modelo+", admin:"+self.administrador+", ubicacion:"+self.ubicacion+", actualizada:" +actualizada+", departamento: "+str(self.departamento) +"}"

    def actualizar(self):
        tmp = "Actualizada" if self.actualizada==True else "No actualizada"
        return tmp

    def asignar(self):
        tmp = "no asignado" if self.asignado==0 else str(self.asignado)
return tmp

Usuario: nombre,apellidos, usuario, password, cargo, computadora,…

class Usuario(models.Model):
    nombre = models.CharField(max_length=50)
    apellidos = models.CharField(max_length=50)
    usuario = models.CharField(max_length=50)
    password = models.CharField(max_length=50)
    CARGO_CHOICES = (
        ('CAPTURISTA', 'CAPTURISTA'),
        ('PROGRAMADOR', 'PROGRAMADOR'),
        ('NO ESPECIFICADO','NO ESPECIFICADO'),
        ('DISENADOR','DISENADOR'),
        ('SERVICIO SOCIAL','SERVICIO SOCIAL'),
        ('LIDER DE PROYECTO','LIDER DE PROYECTO'),
        ('JEFE DE AREA','JEFE DE AREA'),
        ('SOPORTE TECNICO','SOPORTE TECNICO'),
        ('INVESTIGADOR','INVESTIGADOR'),
        ('DIRECTOR GENERAL','DIRECTOR GENERAL'),
    )
    cargo = models.CharField(max_length=50,choices=CARGO_CHOICES, default='CAPTURISTA ')
    computadora =  models.ForeignKey(Equipo)

    def __str__(self):
return "Usuario{id:"+str(self.id)+", nombre:"+self.nombre+" "+self.apellidos+", usuario:"+self.usuario+", cargo: "+self.cargo+", computadora: "+self.computadora.bien+", departamento: "+self.computadora.departamento.area+"}"

Edición: Se editó Usuario.
Finalmente tendremos.
computadoras/models.py

# coding: utf-8

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

#Entidad computadoras_departamento
class Departamento(models.Model):
    area = models.CharField(max_length=50)
    responsable = models.CharField(max_length=50)

    def __str__(self):
        return "Departamento{id:"+str(self.id)+", area:"+self.area+", responsable:"+self.responsable+"}"

#Entidad computadoras_equipo
class Equipo(models.Model):
    bien = models.CharField(max_length=50,default='MXL4332-')
    arrendado = models.CharField(max_length=50,default='77')
    asignado = models.IntegerField(default=0)
    ip = models.GenericIPAddressField(default='148.215.24.1')
    dns = models.GenericIPAddressField(default='148.215.1.1')
    red = models.CharField(max_length=50)
#Esto servirá para crear una lista de opciones
    OPERATIVO_CHOICES = (
        ('Windows XP', 'Windows XP'),
        ('Windows 7', 'Windows 7'),
        ('Windows Vista', 'Windows Vista'),
        ('Windows 8', 'Windows 8'),
        ('Windows 10', 'Windows 10'),
        ('Linux OS', 'Linux OS'),
        ('Mac OS X','Mac OS X'),
        ('No especificado','No especificado'),
    )

    TIPO_CHOICES = (
        ('Escritorio', 'Escritorio'),
        ('Portatil', 'Portatil'),
        ('No especificado','No especificado'),
    )

    PISO_CHOICES = (
        ('PISO 1', 'PISO 1'),
        ('PISO 2', 'PISO 2'),
        ('PISO 3','PISO 3'),
        ('PISO 4','PISO 4'),
        ('PISO 0','PISO 0'),
    )

    operativo = models.CharField(max_length=50,choices=OPERATIVO_CHOICES, default='Windows 8')
    tipo = models.CharField(max_length=50,choices=TIPO_CHOICES, default='Escritorio')
    maquina = models.CharField(max_length=50,default='PC77')
    dominio = models.CharField(max_length=50, default='PC77')
    modelo = models.CharField(max_length=50)
    administrador = models.CharField(max_length=50, default='SOPTEC REDALYC')
    ubicacion = models.CharField(max_length=50,choices=PISO_CHOICES, default='PISO 2')
    actualizada = models.BooleanField(default=False)
    departamento = models.ForeignKey(Departamento)

    def __str__(self):
        actualizada = "Actualizada" if self.actualizada==True else "No actualizada"
        return "Computadora{id:"+str(self.id)+",bien:"+ self.bien +", asignado:"+str(self.asignado)+", Ip:"+self.ip +", Dns:"+self.dns+", red:"+self.red+", operativo:"+self.operativo+", tipo:"+self.tipo+", maquina:"+self.maquina+", dominio:"+self.dominio+", modelo:"+self.modelo+", admin:"+self.administrador+", ubicacion:"+self.ubicacion+", actualizada:" +actualizada+", departamento: "+str(self.departamento) +"}"

    def actualizar(self):
        tmp = "Actualizada" if self.actualizada==True else "No actualizada"
        return tmp

    def asignar(self):
        tmp = "no asignado" if self.asignado==0 else str(self.asignado)
        return tmp

#Entidad computadoras_usuario
class Usuario(models.Model):
    nombre = models.CharField(max_length=50)
    apellidos = models.CharField(max_length=50)
    usuario = models.CharField(max_length=50)
    password = models.CharField(max_length=50)
    CARGO_CHOICES = (
        ('CAPTURISTA', 'CAPTURISTA'),
        ('PROGRAMADOR', 'PROGRAMADOR'),
        ('NO ESPECIFICADO','NO ESPECIFICADO'),
        ('DISENADOR','DISENADOR'),
        ('SERVICIO SOCIAL','SERVICIO SOCIAL'),
        ('LIDER DE PROYECTO','LIDER DE PROYECTO'),
        ('JEFE DE AREA','JEFE DE AREA'),
        ('SOPORTE TECNICO','SOPORTE TECNICO'),
        ('INVESTIGADOR','INVESTIGADOR'),
        ('DIRECTOR GENERAL','DIRECTOR GENERAL'),
    )
    cargo = models.CharField(max_length=50,choices=CARGO_CHOICES, default='CAPTURISTA ')
    computadora =  models.ForeignKey(Equipo)

    def __str__(self):
        apellidos = "" if self.apellidos=="NO ESPECIFICADO" else self.apellidos
        return "Usuario{id:"+str(self.id)+", nombre:"+self.nombre+" "+apellidos+", usuario:"+self.usuario+", cargo: "+self.cargo+", computadora: "+self.computadora.bien+", departamento: "+self.computadora.departamento.area+"}"

    def apellidos_get(self):
        apellidos = "" if self.apellidos=="NO ESPECIFICADO" else self.apellidos
        return apellidos

Creamos la BD y migramos.

$ python manage.py makemigrations computadoras
$ python manage.py migrate computadoras
$ python manage.py migrate

Ejecutamos:

$ python manage.py runserver

Abrimos nuestro navegador en http://127.0.0.1:8000

Debe aparecer la página de bienvenida. En el siguiente post crearemos un super usuario para la gestión de la BD.

Aquí la segunta parte: https://codemonkeyjunior.wordpress.com/2018/09/30/creando-un-proyecto-y-app-con-django2/

Angular JS

code-3337044_640

Angular JS es muy usado hoy en día para la creación de aplicaciones SPA (una sola página). Permite extender etiquetas HTML y crear nuevas funcionalidades. Validar formularios, manejar un lenguaje de expresiones, etc.

Lenguaje de expresión

 <p>5+5= {{ 5 + 5 }}</p>
 <p>5/80= {{ 5/80 }}</p>
<p>16-8= {{ 16 - 8}}</p>
<p>21*3= {{ 21 * 3 }}</p>
<p>45&gt;34= {{ 45&gt;34 }}  </p>
<p>66==66= {{ 66==66}} </p>
<p>8!=9= {{ 8!=9 }} </p>
<p>7=9 }} </p>

Escribiremos un ejemplo.Creamos una página HTML (por ejemplo, prog0.html).

Primero: obtener Angular JS


<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"> </script>

El formulario pide intoducir la edad. En caso que sea igual o mayor a 18 saldrá un mensaje de “Eres mayor de edad”.


<div ng-app="" ng-init="edad='0'">
<p> Introduce tu edad: </p>

<p> {{ edad>=18? "Eres mayor de edad" : edad }}   </p>
</div>
 

Inicializamos le edad con valor 0. Si tecleas un valor menor a 18 solo se mostrará abajo y si escribes 18 o un valor mayor nos mostrará “Eres mayor de edad”.

Inicializar más de una variable.

<div ng-app="" ng-init="saludo='Buenas tardes'; edad='18' ">

<p ng-bind="saludo">  </p>
<p>
{{  saludo=="Buenos tardes"?  "Igualmente" : "Buenas noches"  }}
</p>

<p ng-bind="edad"> </p>
<p>
{{ edad>=18? "Eres mayor de edad" : edad }}
</p>

</div>

 

Django … un vistazo

BeFunky_pythonlang.jpg

Django es el framework favorito para programar aplicaciones web usando el lenguaje Python. En este instalaremos este framework en la plataforma Linux Ubuntu.

Actualizamos el repositorio desde terminal de comandos.

 $ sudo apt-get update

Procedemos a la instalación de Django.

Usando python-django

$ sudo apt-get install python-django

Usando pip

$ pip install Django==2.1.1

Comprobamos su instalación. Tecleamos python en la terminal:

$ python

>>import django
>>exit()

Si no sale nada, entonces la instalación es correcta

Ver la versión instalada:

$ django-admin --version
2.1.1

Otra forma:

$ python -c "import django; print(django.get_version())"

¿Listos? ¡Entonces a crear un primer proyecto usando este framework!

Nota: Es recomendable crear una carpeta y desde ahí crear el proyecto.

 $ mkdir sitio
 $ cd sitio
$ django-admin startproject sitio
$ cd sitio 

Nos creará una estructura similar a esta

sitio
├───manage.py
└───sitio
        settings.py
        urls.py
        wsgi.py
        __init__.py

Editamos settings.py

LANGUAGE_CODE = 'es'

TIME_ZONE = 'America/Mexico_City'  

Migramos los cambios de lenguaje.

$ python manage.py migrate

Ejecutamos:

$ python manage.py runserver

Abrimos el navegador en http://127.0.0.1:8000/

Selección_001

 

Link

https://www.digitalocean.com/community/tutorials/how-to-install-the-django-web-framework-on-ubuntu-16-04

Typescript

1*FIL7OY2C71HPz9vNVeHsAw

Programar con Javascript siempre será necesario si vas a desarrollar una aplicación web. Para quienes usan lenguajes como Java, usar Javascript puede parecerles familiar. Para otros que han usado C y/o C++ no tanto.

Typescript es un lenguaje de tipado estático y permite la interoperabilidad con Angular y similares. En este post veremos como instalar typescript. Antes de cualquier cosa puedes consultar cómo instalar node y npm en este link.

Una vez instalados podemos teclear desde una terminal de comandos:

$ sudo npm install -g typescript

Comprobamos su instalación:

$ npm ls -g
$ tsc -v

Creamos un archivo llamado nodo.ts y definimos una clase como lo hacemos en Java (omitiendo el public)

nodo.ts

class Nodo{
}

Podemos definir atributos y sus tipos:

class Nodo{

nodo: Nodo;

numero: number;

cadena: string;

}

Typescript nos permite definir variables tipo String, Number, Boolean…

Su constructor luce así:

class Nodo{

//...

constructor(nodo: Nodo,numero: number,cadena: string){
    this.nodo=nodo;
    this.numero=numero;
    this.cadena=cadena;
}

}

Definir un método para retornar sus atributos:

class Nodo{

//...

toString(){
    return this.nodo+":"+this.numero+":"+this.cadena;
}

}

Crear instancias de la clase Nodo

let n1 = new Nodo(null,12"A");
let n2 = new Nodo(n1,13,"B");
let n3 = new Nodo(n2,14,"C");

Imprimir en terminal:

console.log(n3.toString());
console.log(n2.toString());
console.log(n1.toString());

Tenemos así finalmente:

class Nodo{
	nodo:Nodo;
	numero:number;
        cadena:string;

	constructor(nodo:Nodo,numero:number,cadena:string){
	   this.nodo=nodo;
           this.numero=numero;
	   this.cadena=cadena;
	   
	}

  toString(){
     return this.nodo+":"+this.numero+":"+this.cadena;
    }
	
}

let n1 = new Nodo(null,12"A");
let n2 = new Nodo(n1,13,"B");
let n3 = new Nodo(n2,14,"C");
console.log(n3.toString());
console.log(n2.toString());
console.log(n1.toString());

Compilamos el código dentro de nodo.ts

$ tsc nodo.ts

Si no hay errores, nos generará un archivo llamado nodo.js. Procedemos a ejecutarlo con node.

$ node nodo.js