commit f79181440f5b1b6d832f25ed3471525f1476df92 Author: Francisco Sandoval Date: Sat Jun 24 13:35:17 2023 -0400 primer commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f80fb39 --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +# carpeta de dependencias +/dependencias + +# ignorar respaldos de base de datos +*.sql.gz + +db.sqlite3 +.env +.vscode +__pycache__ \ No newline at end of file diff --git a/database/create-tables.sql b/database/create-tables.sql new file mode 100644 index 0000000..8427275 --- /dev/null +++ b/database/create-tables.sql @@ -0,0 +1,105 @@ +/*==============================================================*/ +/* Table: APLICACIONES */ +/*==============================================================*/ +create table if not exists APLICACIONES ( + ID_APLICACION integer not null primary key, + APP varchar(100) null, + VIGENTE boolean null +); + +/*==============================================================*/ +/* Table: PERSONA */ +/*==============================================================*/ +create table if not exists PERSONA ( + RUT numeric(12) not null primary key, + ID_TIPO_TRATAMIENTO integer null, + DV char(1) null, + NOMBRES varchar(100) null, + APELLIDO_A varchar(100) null, + APELLIDO_B varchar(100) null, + FONO varchar(100) null, + EMAIL varchar(100) null, + FECHA_NACIMIENTO date null +); + +/*==============================================================*/ +/* Table: ROL */ +/*==============================================================*/ +create table if not exists ROL ( + ID_ROL integer not null primary key, + NOMBRE_ROL varchar(100) not null +); + +/*==============================================================*/ +/* Table: ROL_APLICACION */ +/*==============================================================*/ +create table if not exists ROL_APLICACION ( + ID_APLICACION integer not null, + ID_ROL integer not null, + SOLO_VISUALIZAR boolean null, + constraint PK_ROL_APLICACION primary key (ID_APLICACION, ID_ROL) +); + +/*==============================================================*/ +/* Table: TIPO_TRATAMIENTO_PERSONA */ +/*==============================================================*/ +create table if not exists TIPO_TRATAMIENTO_PERSONA ( + ID_TIPO_TRATAMIENTO integer not null primary key, + TRATAMIENTO varchar(50) null +); + +comment on table TIPO_TRATAMIENTO_PERSONA is +'Establece el tratamiento de como dirigirse hacia una persona: +Ejemplo +Se�or +Se�ora +Srta'; + +/*==============================================================*/ +/* Table: USUARIO */ +/*==============================================================*/ +create table if not exists USUARIO ( + LOGIN varchar(20) not null primary key, + RUT numeric(12) null, + CLAVE varchar(20) null, + VIGENTE boolean null +); + +/*==============================================================*/ +/* Table: USUARIO_ROL */ +/*==============================================================*/ +create table if not exists USUARIO_ROL ( + LOGIN varchar(20) null, + ID_ROL integer null, + VIGENTE boolean null +); + +alter table PERSONA + add constraint FK_PERSONA_REFERENCE_TIPO_TRA foreign key (ID_TIPO_TRATAMIENTO) + references TIPO_TRATAMIENTO_PERSONA (ID_TIPO_TRATAMIENTO) + on delete restrict on update restrict; + +alter table ROL_APLICACION + add constraint FK_ROL_APLI_REFERENCE_APLICACI foreign key (ID_APLICACION) + references APLICACIONES (ID_APLICACION) + on delete restrict on update restrict; + +alter table ROL_APLICACION + add constraint FK_ROL_APLI_REFERENCE_ROL foreign key (ID_ROL) + references ROL (ID_ROL) + on delete restrict on update restrict; + +alter table USUARIO + add constraint FK_USUARIO_REFERENCE_PERSONA foreign key (RUT) + references PERSONA (RUT) + on delete restrict on update restrict; + +alter table USUARIO_ROL + add constraint FK_USUARIO__REFERENCE_USUARIO foreign key (LOGIN) + references USUARIO (LOGIN) + on delete restrict on update restrict; + +alter table USUARIO_ROL + add constraint FK_USUARIO__REFERENCE_ROL foreign key (ID_ROL) + references ROL (ID_ROL) + on delete restrict on update restrict; diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml new file mode 100644 index 0000000..d242094 --- /dev/null +++ b/docker/docker-compose.yml @@ -0,0 +1,44 @@ +version: "3" +name: transporte + +services: + + app: + image: python:3.11-alpine + depends_on: + - db + environment: + - PORT=4000 + - DBHOST=db + - DBNAME=database + - DBSCHEMA=desarrollo2 + - DBUSER=postgres + - DBPASS=password + ports: + - 4000:4000 + volumes: + - ../:/app + working_dir: /app + command: sh /app/docker/start.sh + + db: + image: postgres:14-alpine + volumes: + - db:/var/lib/postgresql/data + environment: + POSTGRES_PASSWORD: password + POSTGRES_DB: database + PGDATA: /var/lib/postgresql/data/pgdata + + adminer: + image: adminer + ports: + - 8080:8080 + environment: + ADMINER_DEFAULT_SERVER: db + ADMINER_DEFAULT_USER: postgres + ADMINER_DEFAULT_PASSWORD: password + ADMINER_DESIGN: lucas-sandery + +volumes: + db: \ No newline at end of file diff --git a/docker/start.sh b/docker/start.sh new file mode 100644 index 0000000..70cf4db --- /dev/null +++ b/docker/start.sh @@ -0,0 +1,25 @@ +#!/bin/sh + +# instalar dependencias +cd /app + +if [[ ! -d ./dependencias ]]; then + python -m venv dependencias + . ./dependencias/bin/activate + pip install -r requirements.txt +fi +. ./dependencias/bin/activate + + +if [[ ! -d ./project ]]; then + django-admin startproject project +fi + +chmod o+w -R project/ + +if [[ ! -f .env ]] && [[ -f .env.develop ]]; then + cp .env.develop .env +fi + +# iniciar servidor +python ./project/manage.py runserver 0.0.0.0:$PORT diff --git a/project/api/__init__.py b/project/api/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/project/api/admin.py b/project/api/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/project/api/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/project/api/apps.py b/project/api/apps.py new file mode 100644 index 0000000..66656fd --- /dev/null +++ b/project/api/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class ApiConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'api' diff --git a/project/api/migrations/0001_initial.py b/project/api/migrations/0001_initial.py new file mode 100644 index 0000000..0048a72 --- /dev/null +++ b/project/api/migrations/0001_initial.py @@ -0,0 +1,101 @@ +# Generated by Django 4.2.2 on 2023-06-24 17:03 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Aplicaciones', + fields=[ + ('id_aplicacion', models.IntegerField(primary_key=True, serialize=False)), + ('app', models.CharField(blank=True, max_length=100, null=True)), + ('vigente', models.BooleanField(blank=True, null=True)), + ], + options={ + 'db_table': 'aplicaciones', + 'managed': False, + }, + ), + migrations.CreateModel( + name='Persona', + fields=[ + ('rut', models.DecimalField(decimal_places=0, max_digits=12, primary_key=True, serialize=False)), + ('dv', models.CharField(blank=True, max_length=1, null=True)), + ('nombres', models.CharField(blank=True, max_length=100, null=True)), + ('apellido_a', models.CharField(blank=True, max_length=100, null=True)), + ('apellido_b', models.CharField(blank=True, max_length=100, null=True)), + ('fono', models.CharField(blank=True, max_length=100, null=True)), + ('email', models.CharField(blank=True, max_length=100, null=True)), + ('fecha_nacimiento', models.DateField(blank=True, null=True)), + ], + options={ + 'db_table': 'persona', + 'managed': False, + }, + ), + migrations.CreateModel( + name='Rol', + fields=[ + ('id_rol', models.IntegerField(primary_key=True, serialize=False)), + ('nombre_rol', models.CharField(max_length=100)), + ], + options={ + 'db_table': 'rol', + 'managed': False, + }, + ), + migrations.CreateModel( + name='TipoTratamientoPersona', + fields=[ + ('id_tipo_tratamiento', models.IntegerField(primary_key=True, serialize=False)), + ('tratamiento', models.CharField(blank=True, max_length=50, null=True)), + ], + options={ + 'db_table': 'tipo_tratamiento_persona', + 'db_table_comment': 'Establece el tratamiento de como dirigirse hacia una persona:\r\nEjemplo\r\nSe�or\r\nSe�ora\r\nSrta', + 'managed': False, + }, + ), + migrations.CreateModel( + name='Usuario', + fields=[ + ('login', models.CharField(max_length=20, primary_key=True, serialize=False)), + ('clave', models.CharField(blank=True, max_length=20, null=True)), + ('vigente', models.BooleanField(blank=True, null=True)), + ], + options={ + 'db_table': 'usuario', + 'managed': False, + }, + ), + migrations.CreateModel( + name='UsuarioRol', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('vigente', models.BooleanField(blank=True, null=True)), + ], + options={ + 'db_table': 'usuario_rol', + 'managed': False, + }, + ), + migrations.CreateModel( + name='RolAplicacion', + fields=[ + ('id_aplicacion', models.OneToOneField(db_column='id_aplicacion', on_delete=django.db.models.deletion.DO_NOTHING, primary_key=True, serialize=False, to='api.aplicaciones')), + ('solo_visualizar', models.BooleanField(blank=True, null=True)), + ], + options={ + 'db_table': 'rol_aplicacion', + 'managed': False, + }, + ), + ] diff --git a/project/api/migrations/__init__.py b/project/api/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/project/api/models.py b/project/api/models.py new file mode 100644 index 0000000..2a75849 --- /dev/null +++ b/project/api/models.py @@ -0,0 +1,85 @@ +# This is an auto-generated Django model module. +# You'll have to do the following manually to clean this up: +# * Rearrange models' order +# * Make sure each model has one field with primary_key=True +# * Make sure each ForeignKey and OneToOneField has `on_delete` set to the desired behavior +# * Remove `managed = False` lines if you wish to allow Django to create, modify, and delete the table +# Feel free to rename the models, but don't rename db_table values or field names. +from django.db import models + + +class Aplicacion(models.Model): + id_aplicacion = models.IntegerField(primary_key=True) + app = models.CharField(max_length=100, blank=True, null=True) + vigente = models.BooleanField(blank=True, null=True) + + class Meta: + managed = False + db_table = 'aplicaciones' + + +class Persona(models.Model): + rut = models.DecimalField(primary_key=True, max_digits=12, decimal_places=0) + id_tipo_tratamiento = models.ForeignKey('TipoTratamientoPersona', models.DO_NOTHING, db_column='id_tipo_tratamiento', blank=True, null=True) + dv = models.CharField(max_length=1, blank=True, null=True) + nombres = models.CharField(max_length=100, blank=True, null=True) + apellido_a = models.CharField(max_length=100, blank=True, null=True) + apellido_b = models.CharField(max_length=100, blank=True, null=True) + fono = models.CharField(max_length=100, blank=True, null=True) + email = models.CharField(max_length=100, blank=True, null=True) + fecha_nacimiento = models.DateField(blank=True, null=True) + + class Meta: + managed = False + db_table = 'persona' + + +class Rol(models.Model): + id_rol = models.IntegerField(primary_key=True) + nombre_rol = models.CharField(max_length=100) + + class Meta: + managed = False + db_table = 'rol' + + +class RolAplicacion(models.Model): + id_aplicacion = models.OneToOneField(Aplicacion, models.DO_NOTHING, db_column='id_aplicacion', primary_key=True) # The composite primary key (id_aplicacion, id_rol) found, that is not supported. The first column is selected. + id_rol = models.ForeignKey(Rol, models.DO_NOTHING, db_column='id_rol') + solo_visualizar = models.BooleanField(blank=True, null=True) + + class Meta: + managed = False + db_table = 'rol_aplicacion' + unique_together = (('id_aplicacion', 'id_rol'),) + + +class TipoTratamientoPersona(models.Model): + id_tipo_tratamiento = models.IntegerField(primary_key=True) + tratamiento = models.CharField(max_length=50, blank=True, null=True) + + class Meta: + managed = False + db_table = 'tipo_tratamiento_persona' + db_table_comment = 'Establece el tratamiento de como dirigirse hacia una persona:\r\nEjemplo\r\nSe�or\r\nSe�ora\r\nSrta' + + +class Usuario(models.Model): + login = models.CharField(primary_key=True, max_length=20) + rut = models.ForeignKey(Persona, models.DO_NOTHING, db_column='rut', blank=True, null=True) + clave = models.CharField(max_length=20, blank=True, null=True) + vigente = models.BooleanField(blank=True, null=True) + + class Meta: + managed = False + db_table = 'usuario' + + +class UsuarioRol(models.Model): + login = models.ForeignKey(Usuario, models.DO_NOTHING, db_column='login', blank=True, null=True) + id_rol = models.ForeignKey(Rol, models.DO_NOTHING, db_column='id_rol', blank=True, null=True) + vigente = models.BooleanField(blank=True, null=True) + + class Meta: + managed = False + db_table = 'usuario_rol' diff --git a/project/api/serializers.py b/project/api/serializers.py new file mode 100644 index 0000000..819b837 --- /dev/null +++ b/project/api/serializers.py @@ -0,0 +1,7 @@ +from rest_framework import serializers +from .models import Aplicacion + +class AplicacionSerializer(serializers.ModelSerializer): + class Meta: + model = Aplicacion + fields = '__all__' \ No newline at end of file diff --git a/project/api/tests.py b/project/api/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/project/api/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/project/api/urls.py b/project/api/urls.py new file mode 100644 index 0000000..dc8caee --- /dev/null +++ b/project/api/urls.py @@ -0,0 +1,10 @@ +from django.urls import path, include +from rest_framework import routers +from api import views + +router = routers.DefaultRouter() +router.register(r'aplicaciones', views.AplicacionViewSet) + +urlpatterns = [ + path('', include(router.urls)), +] \ No newline at end of file diff --git a/project/api/views.py b/project/api/views.py new file mode 100644 index 0000000..c0aaad3 --- /dev/null +++ b/project/api/views.py @@ -0,0 +1,8 @@ +from rest_framework import viewsets +from .models import Aplicacion +from .serializers import AplicacionSerializer + +# Create your views here. +class AplicacionViewSet(viewsets.ModelViewSet): + queryset = Aplicacion.objects.all() + serializer_class = AplicacionSerializer \ No newline at end of file diff --git a/project/manage.py b/project/manage.py new file mode 100755 index 0000000..2c49f3a --- /dev/null +++ b/project/manage.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python +"""Django's command-line utility for administrative tasks.""" +import os +import sys + + +def main(): + """Run administrative tasks.""" + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'project.settings') + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc + execute_from_command_line(sys.argv) + + +if __name__ == '__main__': + main() diff --git a/project/project/__init__.py b/project/project/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/project/project/asgi.py b/project/project/asgi.py new file mode 100644 index 0000000..c9e4e67 --- /dev/null +++ b/project/project/asgi.py @@ -0,0 +1,16 @@ +""" +ASGI config for project project. + +It exposes the ASGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/4.2/howto/deployment/asgi/ +""" + +import os + +from django.core.asgi import get_asgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'project.settings') + +application = get_asgi_application() diff --git a/project/project/settings.py b/project/project/settings.py new file mode 100644 index 0000000..bfd5d91 --- /dev/null +++ b/project/project/settings.py @@ -0,0 +1,141 @@ +""" +Django settings for project project. + +Generated by 'django-admin startproject' using Django 4.2.2. + +For more information on this file, see +https://docs.djangoproject.com/en/4.2/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/4.2/ref/settings/ +""" + +from pathlib import Path +from decouple import config + +# Build paths inside the project like this: BASE_DIR / 'subdir'. +BASE_DIR = Path(__file__).resolve().parent.parent + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = 'django-insecure-ozq@8*t6cy&$lmu@qsvz+l6omsfncj6r1w)s**rtl3vd&j8_#b' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS = [ '*' ] + + +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'rest_framework', + 'coreapi', + 'corsheaders', + 'api' +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] + +ROOT_URLCONF = 'project.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'project.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/4.2/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.postgresql', + 'HOST': config('DBHOST', 'localhost'), + 'PORT': config('DBPORT', 5432), + 'USER': config('DBUSER','postgres'), + 'PASSWORD': config('DBPASS','password'), + 'NAME': config('DBNAME','database'), + 'OPTIONS': { + 'options': '-c search_path=' + config('DBSCHEMA', 'public') + } + } +} + + +# Password validation +# https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/4.2/topics/i18n/ + +LANGUAGE_CODE = 'es-cl' + +TIME_ZONE = 'America/Santiago' + +USE_I18N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/4.2/howto/static-files/ + +STATIC_URL = 'static/' + +# Default primary key field type +# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field + +DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' + +REST_FRAMEWORK = { 'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema' } +CORS_ALLOW_CREDENTIALS = True +CORS_ALLOWED_ORIGINS = [ + "http://localhost:3000", +] \ No newline at end of file diff --git a/project/project/urls.py b/project/project/urls.py new file mode 100644 index 0000000..0d6271e --- /dev/null +++ b/project/project/urls.py @@ -0,0 +1,25 @@ +""" +URL configuration for project project. + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/4.2/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: path('', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.urls import include, path + 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) +""" +from django.contrib import admin +from django.urls import path, include +from rest_framework.documentation import include_docs_urls + +urlpatterns = [ + path('admin/', admin.site.urls), + path('api/', include('api.urls')), + path('docs/', include_docs_urls(title = 'API Documentation')), +] diff --git a/project/project/wsgi.py b/project/project/wsgi.py new file mode 100644 index 0000000..6f61a78 --- /dev/null +++ b/project/project/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for project project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/4.2/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'project.settings') + +application = get_wsgi_application() diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..a5c0fa0 --- /dev/null +++ b/readme.md @@ -0,0 +1,57 @@ + +# Dependencias + +* **Django**: framework django +* **psycopg2-binary**: permite uso de base datos postgres +* **djangorestframework**: permite crear rest api json +* **django-cors-headers**: requerido para desarrollo de frontend, permite acceso desde una dominio distinto al backend +* **coreapi**: genera documentación de rest api +* **python-decouple**: lee archivo .env para variables de ambiente +* **PyJWT**: permite generar json-web-token +* **pymongo**: permite conectarse a base datos mongo + + +# Docker + +Para iniciar la aplicacion usando docker + +~~~bash +cd /docker +docker compose up -d +~~~ + + + +# Script para levantar aplicacion python + +**start.sh** + +~~~bash +#!/bin/sh +cd /app + +# si no existe directorio de ambiente, se crea +if [ ! -d /app/libs ]; then + python -m venv libs + . ./libs/bin/activate + pip install -r requirements.txt +fi + +# activar ambiente con dependencias +. ./libs/bin/activate + +# si no existe un proyecto inicial, lo crea +if [ ! -d /app/project ]; then + django-admin startproject project +fi + +# iniciar servidor con puerto 8000 +python /app/project/manage.py runserver 0.0.0.0:8000 +~~~ + +# Extraer models de base de datos + +~~~bash +python manage.py inspectdb > api/models.py +~~~ + diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..40e8da2 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,8 @@ +Django +psycopg2-binary +djangorestframework +django-cors-headers +coreapi +python-decouple +PyJWT +pymongo \ No newline at end of file