| @ -0,0 +1,87 @@ | |||
| -- MySQL dump 10.13 Distrib 8.0.36, for Linux (x86_64) | |||
| -- | |||
| -- Host: localhost Database: automoviles | |||
| -- ------------------------------------------------------ | |||
| -- Server version 11.2.2-MariaDB-1:11.2.2+maria~ubu2204 | |||
| /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; | |||
| /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; | |||
| /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; | |||
| /*!50503 SET NAMES utf8mb4 */; | |||
| /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; | |||
| /*!40103 SET TIME_ZONE='+00:00' */; | |||
| /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; | |||
| /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; | |||
| /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; | |||
| /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; | |||
| -- | |||
| -- Table structure for table `carburante` | |||
| -- | |||
| DROP TABLE IF EXISTS `carburante`; | |||
| /*!40101 SET @saved_cs_client = @@character_set_client */; | |||
| /*!50503 SET character_set_client = utf8mb4 */; | |||
| CREATE TABLE `carburante` ( | |||
| `identificador` int(11) NOT NULL AUTO_INCREMENT, | |||
| `fecha` date DEFAULT NULL, | |||
| `vehiculo` text DEFAULT NULL, | |||
| `kms` int(11) DEFAULT NULL, | |||
| `litros` decimal(10,3) DEFAULT NULL, | |||
| `descuento` decimal(10,2) DEFAULT NULL, | |||
| `precioxlitro` decimal(10,3) DEFAULT NULL, | |||
| `importe` decimal(10,2) DEFAULT NULL, | |||
| PRIMARY KEY (`identificador`) | |||
| ) ENGINE=InnoDB AUTO_INCREMENT=250 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_spanish_ci; | |||
| /*!40101 SET character_set_client = @saved_cs_client */; | |||
| -- | |||
| -- Dumping data for table `carburante` | |||
| -- | |||
| LOCK TABLES `carburante` WRITE; | |||
| /*!40000 ALTER TABLE `carburante` DISABLE KEYS */; | |||
| INSERT INTO `carburante` VALUES (1,'2021-12-14','1018KPD',52731,0.000,0.00,0.000,0.00),(2,'2021-12-23','1018KPD',53162,52.800,0.00,1.280,67.32),(3,'2021-12-31','1018KPD',54122,49.990,0.00,1.280,63.74),(4,'2022-01-22','1018KPD',54946,49.140,0.00,1.270,62.65),(5,'2022-02-09','1018KPD',55908,49.240,0.00,1.320,65.24),(6,'2022-03-03','1018KPD',56909,48.610,0.00,1.380,67.03),(7,'2022-03-18','1018KPD',57542,30.060,0.00,1.750,52.54),(8,'2022-04-10','1018KPD',58497,46.630,0.00,1.500,69.98),(9,'2022-05-12','1018KPD',59447,47.140,0.00,1.530,72.11),(10,'2022-05-19','1018KPD',60414,48.570,0.00,1.640,79.81),(11,'2022-06-09','1018KPD',61147,36.200,0.00,1.720,62.12),(12,'2022-06-25','1018KPD',62116,49.170,0.00,1.840,90.29),(16,'2022-09-14','1018KPD',66359,53.240,0.00,1.590,84.83),(17,'2022-09-23','1018KPD',67107,37.260,0.00,1.490,55.48),(19,'2023-01-24','1018KPD',71790,43.040,2.12,1.590,70.54),(21,'2022-12-03','1018KPD',70061,46.380,2.04,1.420,68.13),(22,'2022-12-26','1018KPD',70919,44.580,1.85,1.34 | |||
| 0,61.68),(23,'2023-03-05','1018KPD',73711,47.850,0.00,1.490,71.20),(24,'2023-03-25','1018KPD',74749,49.840,0.00,1.450,72.17),(25,'2023-02-19','1018KPD',72763,49.380,2.34,1.530,77.97),(27,'2023-05-06','1018KPD',76434,32.280,0.00,1.370,44.09),(28,'2023-05-22','1018KPD',77366,45.040,0.00,1.300,58.46),(45,'2022-07-09','1018KPD',63129,47.030,0.00,1.690,79.38),(46,'2022-08-12','1018KPD',64088,43.730,0.00,1.500,65.55),(47,'2022-08-22','1018KPD',65185,52.780,0.00,1.490,78.80),(50,'2022-10-12','1018KPD',68204,52.040,2.51,1.560,83.73),(51,'2022-11-11','1018KPD',69158,45.280,2.37,1.690,78.91),(61,'2023-06-10','1018KPD',78170,41.090,0.00,1.320,54.16),(62,'2023-06-19','1018KPD',79038,40.780,1.95,1.430,60.11),(151,'2022-06-28','7630LYR',219,9.880,0.00,1.920,18.96),(152,'2022-06-28','7630LYR',236,27.360,0.00,1.880,51.33),(153,'2022-07-14','7630LYR',904,32.240,0.00,1.720,55.58),(154,'2022-07-26','7630LYR',1433,30.490,0.00,1.590,48.43),(155,'2022-08-21','7630LYR',2030,32.920,0.00,1.420,46.72),(156,' | |||
| 2022-09-26','7630LYR',2627,23.920,0.00,1.390,33.16),(157,'2022-10-18','7630LYR',3169,22.970,0.00,1.430,32.74),(158,'2022-11-09','7630LYR',3791,29.600,0.00,1.410,41.88),(159,'2022-11-27','7630LYR',4363,28.800,1.20,1.350,38.80),(160,'2022-12-22','7630LYR',4851,26.740,1.06,1.280,34.18),(161,'2023-01-12','7630LYR',5291,23.520,1.09,1.500,35.34),(162,'2023-02-01','7630LYR',5702,27.360,1.28,1.520,41.52),(163,'2023-02-20','7630LYR',6141,24.090,1.13,1.520,36.67),(164,'2023-03-15','7630LYR',6631,25.520,1.21,1.530,38.96),(165,'2023-04-17','7630LYR',7325,29.400,1.47,1.620,47.62),(166,'2023-05-28','7630LYR',8413,24.160,1.17,1.560,37.70),(167,'2023-06-25','7630LYR',8956,26.380,1.30,1.590,41.94),(168,'2023-07-10','7630LYR',9471,29.040,1.35,1.497,43.49),(176,'2023-07-14','1018KPD',79875,40.560,1.74,1.407,56.26),(177,'2023-07-22','1018KPD',80806,46.290,1.95,1.371,63.05),(178,'2023-07-25','7630LYR',10043,24.850,1.40,1.622,40.32),(182,'2023-08-07','1018KPD',81695,44.390,0.00,1.439,63.88),(201,'2023-08 | |||
| -09','7630LYR',10582,26.490,1.39,1.696,44.94),(202,'2023-08-23','7630LYR',11050,24.050,1.22,1.638,39.40),(203,'2023-08-27','1018KPD',82715,50.400,0.00,1.529,77.06),(204,'2023-09-14','7630LYR',11508,21.440,1.14,1.726,37.00),(205,'2023-09-19','1018KPD',83709,48.350,0.00,1.598,77.26),(206,'2023-09-27','1018KPD',84171,23.010,0.00,1.558,35.85),(207,'2023-10-10','1018KPD',85104,48.000,0.00,1.509,72.43),(212,'2023-10-15','7630LYR',12006,25.090,1.25,1.609,40.37),(213,'2023-10-27','1018KPD',86021,46.770,0.00,1.499,70.11),(214,'2023-11-04','7630LYR',12427,25.640,1.17,1.474,37.78),(215,'2023-11-11','1018KPD',86757,39.580,1.71,1.398,55.33),(216,'2023-11-20','7630LYR',12933,26.160,0.00,1.529,40.00),(217,'2023-11-23','1018KPD',87503,42.410,1.75,1.331,56.45),(218,'2023-12-04','1018KPD',88256,41.190,0.00,1.399,57.62),(219,'2023-12-17','1018KPD',88964,41.200,1.66,1.305,53.78),(220,'2024-01-06','7630LYR',13414,30.720,1.34,1.411,43.36),(222,'2024-01-07','1018KPD',89802,47.770,1.91,1.293,61.75),(223,'2 | |||
| 024-01-22','7630LYR',13903,25.080,0.00,1.479,37.09),(224,'2024-01-27','1018KPD',90723,45.250,0.00,1.334,60.37),(226,'2024-02-11','7630LYR',14365,28.450,0.00,1.454,41.37),(233,'2024-02-12','1018KPD',91672,48.310,0.00,1.449,70.00),(235,'2024-02-27','1018KPD',92489,41.990,0.00,1.379,57.91),(236,'2024-02-29','7630LYR',14857,23.960,1.12,1.517,36.35),(237,'2024-03-18','7630LYR',15287,13.000,0.00,1.538,20.00),(239,'2024-03-19','1018KPD',93327,43.850,0.00,1.374,60.25),(240,'2024-03-25','7630LYR',15537,19.240,0.00,1.559,30.00),(241,'2024-04-06','7630LYR',15935,29.390,0.00,1.479,43.48),(242,'2024-04-08','1018KPD',94167,41.110,0.00,1.374,56.49),(243,'2024-04-22','7630LYR',16465,25.920,0.00,1.569,40.66),(244,'2024-04-29','1018KPD',95042,43.630,0.00,1.445,63.03),(247,'2024-05-13','7630LYR',16963,26.800,0.00,1.549,41.51),(248,'2024-05-21','1018KPD',96585,28.330,0.00,1.399,39.63),(249,'2024-05-27','1018KPD',97597,49.480,0.00,1.373,67.96); | |||
| /*!40000 ALTER TABLE `carburante` ENABLE KEYS */; | |||
| UNLOCK TABLES; | |||
| -- | |||
| -- Table structure for table `vehiculos` | |||
| -- | |||
| DROP TABLE IF EXISTS `vehiculos`; | |||
| /*!40101 SET @saved_cs_client = @@character_set_client */; | |||
| /*!50503 SET character_set_client = utf8mb4 */; | |||
| CREATE TABLE `vehiculos` ( | |||
| `identificador` int(11) NOT NULL AUTO_INCREMENT, | |||
| `marca` text NOT NULL, | |||
| `modelo` text NOT NULL, | |||
| `matricula` text NOT NULL, | |||
| PRIMARY KEY (`identificador`) | |||
| ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; | |||
| /*!40101 SET character_set_client = @saved_cs_client */; | |||
| -- | |||
| -- Dumping data for table `vehiculos` | |||
| -- | |||
| LOCK TABLES `vehiculos` WRITE; | |||
| /*!40000 ALTER TABLE `vehiculos` DISABLE KEYS */; | |||
| INSERT INTO `vehiculos` VALUES (2,'Toyota','Corolla','7630LYR'),(3,'BMW','318d','1018KPD'); | |||
| /*!40000 ALTER TABLE `vehiculos` ENABLE KEYS */; | |||
| UNLOCK TABLES; | |||
| /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; | |||
| /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; | |||
| /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; | |||
| /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; | |||
| /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; | |||
| /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; | |||
| /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; | |||
| /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; | |||
| -- Dump completed on 2024-05-30 19:20:57 | |||
| @ -0,0 +1,42 @@ | |||
| # init.py | |||
| from flask import Flask | |||
| from flask_sqlalchemy import SQLAlchemy | |||
| from flask_login import LoginManager | |||
| from . import models | |||
| # init SQLAlchemy so we can use it later in our models | |||
| db = SQLAlchemy() | |||
| def create_app(): | |||
| app = Flask(__name__) | |||
| app.config['SECRET_KEY'] = '9OLWxND4o83j4K4iuopO' | |||
| app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db.sqlite' | |||
| db.init_app(app) | |||
| with app.app_context(): | |||
| db.create_all() | |||
| login_manager = LoginManager() | |||
| login_manager.login_view = 'auth.login' | |||
| login_manager.init_app(app) | |||
| from .models import User | |||
| @login_manager.user_loader | |||
| def load_user(user_id): | |||
| # since the user_id is just the primary key of our user table, use it in the query for the user | |||
| return User.query.get(int(user_id)) | |||
| # blueprint for auth routes in our app | |||
| from .auth import auth as auth_blueprint | |||
| app.register_blueprint(auth_blueprint) | |||
| # blueprint for non-auth parts of app | |||
| from .main import main as main_blueprint | |||
| app.register_blueprint(main_blueprint) | |||
| return app | |||
| @ -0,0 +1,63 @@ | |||
| # auth.py | |||
| from flask import Blueprint, render_template, redirect, url_for, request, flash | |||
| from werkzeug.security import generate_password_hash, check_password_hash | |||
| from flask_login import login_user, logout_user, login_required | |||
| from .models import User | |||
| from . import db | |||
| auth = Blueprint('auth', __name__) | |||
| @auth.route('/login') | |||
| def login(): | |||
| return render_template('login.html') | |||
| @auth.route('/login', methods=['POST']) | |||
| def login_post(): | |||
| email = request.form.get('email') | |||
| password = request.form.get('password') | |||
| remember = True if request.form.get('remember') else False | |||
| user = User.query.filter_by(email=email).first() | |||
| # check if user actually exists | |||
| # take the user supplied password, hash it, and compare it to the hashed password in database | |||
| if not user or not check_password_hash(user.password, password): | |||
| flash('Please check your login details and try again.') | |||
| return redirect(url_for('auth.login')) # if user doesn't exist or password is wrong, reload the page | |||
| # if the above check passes, then we know the user has the right credentials | |||
| login_user(user, remember=remember) | |||
| return redirect(url_for('main.profile')) | |||
| @auth.route('/signup') | |||
| def signup(): | |||
| return render_template('signup.html') | |||
| @auth.route('/signup', methods=['POST']) | |||
| def signup_post(): | |||
| email = request.form.get('email') | |||
| name = request.form.get('name') | |||
| password = request.form.get('password') | |||
| user = User.query.filter_by(email=email).first() # if this returns a user, then the email already exists in database | |||
| if user: # if a user is found, we want to redirect back to signup page so user can try again | |||
| flash('Email address already exists') | |||
| return redirect(url_for('auth.signup')) | |||
| # create new user with the form data. Hash the password so plaintext version isn't saved. | |||
| new_user = User(email=email, name=name, password=generate_password_hash(password, method='pbkdf2:sha256')) | |||
| # add the new user to the database | |||
| db.session.add(new_user) | |||
| db.session.commit() | |||
| return redirect(url_for('auth.login')) | |||
| @auth.route('/logout') | |||
| @login_required | |||
| def logout(): | |||
| logout_user() | |||
| return redirect(url_for('main.index')) | |||
| @ -0,0 +1,34 @@ | |||
| # main.py | |||
| from flask import Blueprint, render_template, redirect, url_for | |||
| from flask_login import login_required, current_user | |||
| from .models import Carburante, db | |||
| main = Blueprint('main', __name__) | |||
| @main.route('/') | |||
| def index(): | |||
| return render_template('index.html') | |||
| @main.route('/profile') | |||
| @login_required | |||
| def profile(): | |||
| return render_template('profile.html', name=current_user.name) | |||
| @main.route('/listado') | |||
| def listado(): | |||
| repostaje = db.get_or_404(Carburante, 1) | |||
| # check if user actually exists | |||
| # take the user supplied password, hash it, and compare it to the hashed password in database | |||
| if not repostaje : | |||
| print("no encuentro nada") | |||
| return redirect(url_for('main.profile')) # if user doesn't exist or password is wrong, reload the page | |||
| print("Datos: ", repostaje) | |||
| # if the above check passes, then we know the user has the right credentials | |||
| return redirect(url_for('main.listado')) | |||
| @ -0,0 +1,28 @@ | |||
| # models.py | |||
| from flask_login import UserMixin | |||
| from flask_sqlalchemy import SQLAlchemy | |||
| db = SQLAlchemy() | |||
| class User(UserMixin, db.Model): | |||
| id = db.Column(db.Integer, primary_key=True) # primary keys are required by SQLAlchemy | |||
| email = db.Column(db.String(100), unique=True) | |||
| password = db.Column(db.String(100)) | |||
| name = db.Column(db.String(1000)) | |||
| class Carburante(db.Model): | |||
| identificador = db.Column(db.Integer, primary_key=True) | |||
| fecha = db.Column(db.Date()) | |||
| vehiculo = db.Column(db.String(20)) | |||
| kms = db.Column(db.Integer) | |||
| litros = db.Column(db.DECIMAL(10,3)) | |||
| descuento = db.Column(db.DECIMAL(10,2)) | |||
| precioxlitro = db.Column(db.DECIMAL(10,3)) | |||
| importe = db.Column(db.DECIMAL(10,2)) | |||
| class Vehiculos(db.Model): | |||
| identificador = db.Column(db.Integer, primary_key=True) | |||
| marca = db.Column(db.String(20)) | |||
| modelo = db.Column(db.String(20)) | |||
| matricula = db.Column(db.String(20)) | |||
| @ -0,0 +1,59 @@ | |||
| <!-- templates/base.html --> | |||
| <!DOCTYPE html> | |||
| <html> | |||
| <head> | |||
| <meta charset="utf-8"> | |||
| <meta http-equiv="X-UA-Compatible" content="IE=edge"> | |||
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |||
| <title>Flask Auth Example</title> | |||
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.2/css/bulma.min.css" /> | |||
| </head> | |||
| <body> | |||
| <section class="hero is-primary is-fullheight"> | |||
| <div class="hero-head"> | |||
| <nav class="navbar"> | |||
| <div class="container"> | |||
| <div id="navbarMenuHeroA" class="navbar-menu"> | |||
| <div class="navbar-end"> | |||
| <a href="{{ url_for('main.index') }}" class="navbar-item"> | |||
| Home | |||
| </a> | |||
| {% if current_user.is_authenticated %} | |||
| <a href="{{ url_for('main.profile') }}" class="navbar-item"> | |||
| Profile | |||
| </a> | |||
| {% endif %} | |||
| {% if not current_user.is_authenticated %} | |||
| <a href="{{ url_for('auth.login') }}" class="navbar-item"> | |||
| Login | |||
| </a> | |||
| <a href="{{ url_for('auth.signup') }}" class="navbar-item"> | |||
| Sign Up | |||
| </a> | |||
| {% endif %} | |||
| {% if current_user.is_authenticated %} | |||
| <a href="{{ url_for('auth.logout') }}" class="navbar-item"> | |||
| Logout | |||
| </a> | |||
| {% endif %} | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </nav> | |||
| </div> | |||
| <div class="hero-body"> | |||
| <div class="container has-text-centered"> | |||
| {% block content %} | |||
| {% endblock %} | |||
| </div> | |||
| </div> | |||
| </section> | |||
| </body> | |||
| </html> | |||
| @ -0,0 +1,12 @@ | |||
| <!-- templates/index.html --> | |||
| {% extends "base.html" %} | |||
| {% block content %} | |||
| <h1 class="title"> | |||
| Flask Login Example | |||
| </h1> | |||
| <h2 class="subtitle"> | |||
| Easy authentication and authorization in Flask. | |||
| </h2> | |||
| {% endblock %} | |||
| @ -0,0 +1,12 @@ | |||
| <!-- templates/profile.html --> | |||
| {% extends "base.html" %} | |||
| {% block content %} | |||
| <h1 class="title"> | |||
| Welcome, {{ name }}! | |||
| </h1> | |||
| <h2> | |||
| Aquí saldrá el listado | |||
| </h2> | |||
| {% endblock %} | |||
| @ -0,0 +1,38 @@ | |||
| <!-- templates/login.html --> | |||
| {% extends "base.html" %} | |||
| {% block content %} | |||
| <div class="column is-4 is-offset-4"> | |||
| <h3 class="title">Login</h3> | |||
| <div class="box"> | |||
| {% with messages = get_flashed_messages() %} | |||
| {% if messages %} | |||
| <div class="notification is-danger"> | |||
| {{ messages[0] }} | |||
| </div> | |||
| {% endif %} | |||
| {% endwith %} | |||
| <form method="POST" action="/login"> | |||
| <div class="field"> | |||
| <div class="control"> | |||
| <input class="input is-large" type="email" name="email" placeholder="Your Email" autofocus=""> | |||
| </div> | |||
| </div> | |||
| <div class="field"> | |||
| <div class="control"> | |||
| <input class="input is-large" type="password" name="password" placeholder="Your Password"> | |||
| </div> | |||
| </div> | |||
| <div class="field"> | |||
| <label class="checkbox"> | |||
| <input type="checkbox"> | |||
| Remember me | |||
| </label> | |||
| </div> | |||
| <button class="button is-block is-info is-large is-fullwidth">Login</button> | |||
| </form> | |||
| </div> | |||
| </div> | |||
| {% endblock %} | |||
| @ -0,0 +1,9 @@ | |||
| <!-- templates/profile.html --> | |||
| {% extends "base.html" %} | |||
| {% block content %} | |||
| <h1 class="title"> | |||
| Welcome, {{ name }}! | |||
| </h1> | |||
| {% endblock %} | |||
| @ -0,0 +1,39 @@ | |||
| <!-- templates/signup.html --> | |||
| {% extends "base.html" %} | |||
| {% block content %} | |||
| <div class="column is-4 is-offset-4"> | |||
| <h3 class="title">Sign Up</h3> | |||
| <div class="box"> | |||
| {% with messages = get_flashed_messages() %} | |||
| {% if messages %} | |||
| <div class="notification is-danger"> | |||
| {{ messages[0] }}. Go to <a href="{{ url_for('auth.login') }}">login page</a>. | |||
| </div> | |||
| {% endif %} | |||
| {% endwith %} | |||
| <form method="POST" action="/signup"> | |||
| <div class="field"> | |||
| <div class="control"> | |||
| <input class="input is-large" type="email" name="email" placeholder="Email" autofocus=""> | |||
| </div> | |||
| </div> | |||
| <div class="field"> | |||
| <div class="control"> | |||
| <input class="input is-large" type="text" name="name" placeholder="Name" autofocus=""> | |||
| </div> | |||
| </div> | |||
| <div class="field"> | |||
| <div class="control"> | |||
| <input class="input is-large" type="password" name="password" placeholder="Password"> | |||
| </div> | |||
| </div> | |||
| <button class="button is-block is-info is-large is-fullwidth">Sign Up</button> | |||
| </form> | |||
| </div> | |||
| </div> | |||
| {% endblock %} | |||
| @ -0,0 +1,88 @@ | |||
| INSERT INTO `carburante` VALUES (1,'2021-12-14','1018KPD',52731,0.000,0.00,0.000,0.00); | |||
| INSERT INTO `carburante` VALUES (2,'2021-12-23','1018KPD',53162,52.800,0.00,1.280,67.32); | |||
| INSERT INTO `carburante` VALUES (3,'2021-12-31','1018KPD',54122,49.990,0.00,1.280,63.74); | |||
| INSERT INTO `carburante` VALUES (4,'2022-01-22','1018KPD',54946,49.140,0.00,1.270,62.65); | |||
| INSERT INTO `carburante` VALUES (5,'2022-02-09','1018KPD',55908,49.240,0.00,1.320,65.24); | |||
| INSERT INTO `carburante` VALUES (6,'2022-03-03','1018KPD',56909,48.610,0.00,1.380,67.03); | |||
| INSERT INTO `carburante` VALUES (7,'2022-03-18','1018KPD',57542,30.060,0.00,1.750,52.54); | |||
| INSERT INTO `carburante` VALUES (8,'2022-04-10','1018KPD',58497,46.630,0.00,1.500,69.98); | |||
| INSERT INTO `carburante` VALUES (9,'2022-05-12','1018KPD',59447,47.140,0.00,1.530,72.11); | |||
| INSERT INTO `carburante` VALUES (10,'2022-05-19','1018KPD',60414,48.570,0.00,1.640,79.81); | |||
| INSERT INTO `carburante` VALUES (11,'2022-06-09','1018KPD',61147,36.200,0.00,1.720,62.12); | |||
| INSERT INTO `carburante` VALUES (12,'2022-06-25','1018KPD',62116,49.170,0.00,1.840,90.29); | |||
| INSERT INTO `carburante` VALUES (16,'2022-09-14','1018KPD',66359,53.240,0.00,1.590,84.83); | |||
| INSERT INTO `carburante` VALUES (17,'2022-09-23','1018KPD',67107,37.260,0.00,1.490,55.48); | |||
| INSERT INTO `carburante` VALUES (19,'2023-01-24','1018KPD',71790,43.040,2.12,1.590,70.54); | |||
| INSERT INTO `carburante` VALUES (21,'2022-12-03','1018KPD',70061,46.380,2.04,1.420,68.13); | |||
| INSERT INTO `carburante` VALUES (22,'2022-12-26','1018KPD',70919,44.580,1.85,1.340,61.68); | |||
| INSERT INTO `carburante` VALUES (23,'2023-03-05','1018KPD',73711,47.850,0.00,1.490,71.20); | |||
| INSERT INTO `carburante` VALUES (24,'2023-03-25','1018KPD',74749,49.840,0.00,1.450,72.17); | |||
| INSERT INTO `carburante` VALUES (25,'2023-02-19','1018KPD',72763,49.380,2.34,1.530,77.97); | |||
| INSERT INTO `carburante` VALUES (27,'2023-05-06','1018KPD',76434,32.280,0.00,1.370,44.09); | |||
| INSERT INTO `carburante` VALUES (28,'2023-05-22','1018KPD',77366,45.040,0.00,1.300,58.46); | |||
| INSERT INTO `carburante` VALUES (45,'2022-07-09','1018KPD',63129,47.030,0.00,1.690,79.38); | |||
| INSERT INTO `carburante` VALUES (46,'2022-08-12','1018KPD',64088,43.730,0.00,1.500,65.55); | |||
| INSERT INTO `carburante` VALUES (47,'2022-08-22','1018KPD',65185,52.780,0.00,1.490,78.80); | |||
| INSERT INTO `carburante` VALUES (50,'2022-10-12','1018KPD',68204,52.040,2.51,1.560,83.73); | |||
| INSERT INTO `carburante` VALUES (51,'2022-11-11','1018KPD',69158,45.280,2.37,1.690,78.91); | |||
| INSERT INTO `carburante` VALUES (61,'2023-06-10','1018KPD',78170,41.090,0.00,1.320,54.16); | |||
| INSERT INTO `carburante` VALUES (62,'2023-06-19','1018KPD',79038,40.780,1.95,1.430,60.11); | |||
| INSERT INTO `carburante` VALUES (151,'2022-06-28','7630LYR',219,9.880,0.00,1.920,18.96); | |||
| INSERT INTO `carburante` VALUES (152,'2022-06-28','7630LYR',236,27.360,0.00,1.880,51.33); | |||
| INSERT INTO `carburante` VALUES (153,'2022-07-14','7630LYR',904,32.240,0.00,1.720,55.58); | |||
| INSERT INTO `carburante` VALUES (154,'2022-07-26','7630LYR',1433,30.490,0.00,1.590,48.43); | |||
| INSERT INTO `carburante` VALUES (155,'2022-08-21','7630LYR',2030,32.920,0.00,1.420,46.72); | |||
| INSERT INTO `carburante` VALUES (156,'2022-09-26','7630LYR',2627,23.920,0.00,1.390,33.16); | |||
| INSERT INTO `carburante` VALUES (157,'2022-10-18','7630LYR',3169,22.970,0.00,1.430,32.74); | |||
| INSERT INTO `carburante` VALUES (158,'2022-11-09','7630LYR',3791,29.600,0.00,1.410,41.88); | |||
| INSERT INTO `carburante` VALUES (159,'2022-11-27','7630LYR',4363,28.800,1.20,1.350,38.80); | |||
| INSERT INTO `carburante` VALUES (160,'2022-12-22','7630LYR',4851,26.740,1.06,1.280,34.18); | |||
| INSERT INTO `carburante` VALUES (161,'2023-01-12','7630LYR',5291,23.520,1.09,1.500,35.34); | |||
| INSERT INTO `carburante` VALUES (162,'2023-02-01','7630LYR',5702,27.360,1.28,1.520,41.52); | |||
| INSERT INTO `carburante` VALUES (163,'2023-02-20','7630LYR',6141,24.090,1.13,1.520,36.67); | |||
| INSERT INTO `carburante` VALUES (164,'2023-03-15','7630LYR',6631,25.520,1.21,1.530,38.96); | |||
| INSERT INTO `carburante` VALUES (165,'2023-04-17','7630LYR',7325,29.400,1.47,1.620,47.62); | |||
| INSERT INTO `carburante` VALUES (166,'2023-05-28','7630LYR',8413,24.160,1.17,1.560,37.70); | |||
| INSERT INTO `carburante` VALUES (167,'2023-06-25','7630LYR',8956,26.380,1.30,1.590,41.94); | |||
| INSERT INTO `carburante` VALUES (168,'2023-07-10','7630LYR',9471,29.040,1.35,1.497,43.49); | |||
| INSERT INTO `carburante` VALUES (176,'2023-07-14','1018KPD',79875,40.560,1.74,1.407,56.26); | |||
| INSERT INTO `carburante` VALUES (177,'2023-07-22','1018KPD',80806,46.290,1.95,1.371,63.05); | |||
| INSERT INTO `carburante` VALUES (178,'2023-07-25','7630LYR',10043,24.850,1.40,1.622,40.32); | |||
| INSERT INTO `carburante` VALUES (182,'2023-08-07','1018KPD',81695,44.390,0.00,1.439,63.88); | |||
| INSERT INTO `carburante` VALUES (201,'2023-08-09','7630LYR',10582,26.490,1.39,1.696,44.94); | |||
| INSERT INTO `carburante` VALUES (202,'2023-08-23','7630LYR',11050,24.050,1.22,1.638,39.40); | |||
| INSERT INTO `carburante` VALUES (203,'2023-08-27','1018KPD',82715,50.400,0.00,1.529,77.06); | |||
| INSERT INTO `carburante` VALUES (204,'2023-09-14','7630LYR',11508,21.440,1.14,1.726,37.00); | |||
| INSERT INTO `carburante` VALUES (205,'2023-09-19','1018KPD',83709,48.350,0.00,1.598,77.26); | |||
| INSERT INTO `carburante` VALUES (206,'2023-09-27','1018KPD',84171,23.010,0.00,1.558,35.85); | |||
| INSERT INTO `carburante` VALUES (207,'2023-10-10','1018KPD',85104,48.000,0.00,1.509,72.43); | |||
| INSERT INTO `carburante` VALUES (212,'2023-10-15','7630LYR',12006,25.090,1.25,1.609,40.37); | |||
| INSERT INTO `carburante` VALUES (213,'2023-10-27','1018KPD',86021,46.770,0.00,1.499,70.11); | |||
| INSERT INTO `carburante` VALUES (214,'2023-11-04','7630LYR',12427,25.640,1.17,1.474,37.78); | |||
| INSERT INTO `carburante` VALUES (215,'2023-11-11','1018KPD',86757,39.580,1.71,1.398,55.33); | |||
| INSERT INTO `carburante` VALUES (216,'2023-11-20','7630LYR',12933,26.160,0.00,1.529,40.00); | |||
| INSERT INTO `carburante` VALUES (217,'2023-11-23','1018KPD',87503,42.410,1.75,1.331,56.45); | |||
| INSERT INTO `carburante` VALUES (218,'2023-12-04','1018KPD',88256,41.190,0.00,1.399,57.62); | |||
| INSERT INTO `carburante` VALUES (219,'2023-12-17','1018KPD',88964,41.200,1.66,1.305,53.78); | |||
| INSERT INTO `carburante` VALUES (220,'2024-01-06','7630LYR',13414,30.720,1.34,1.411,43.36); | |||
| INSERT INTO `carburante` VALUES (222,'2024-01-07','1018KPD',89802,47.770,1.91,1.293,61.75); | |||
| INSERT INTO `carburante` VALUES (223,'2024-01-22','7630LYR',13903,25.080,0.00,1.479,37.09); | |||
| INSERT INTO `carburante` VALUES (224,'2024-01-27','1018KPD',90723,45.250,0.00,1.334,60.37); | |||
| INSERT INTO `carburante` VALUES (226,'2024-02-11','7630LYR',14365,28.450,0.00,1.454,41.37); | |||
| INSERT INTO `carburante` VALUES (233,'2024-02-12','1018KPD',91672,48.310,0.00,1.449,70.00); | |||
| INSERT INTO `carburante` VALUES (235,'2024-02-27','1018KPD',92489,41.990,0.00,1.379,57.91); | |||
| INSERT INTO `carburante` VALUES (236,'2024-02-29','7630LYR',14857,23.960,1.12,1.517,36.35); | |||
| INSERT INTO `carburante` VALUES (237,'2024-03-18','7630LYR',15287,13.000,0.00,1.538,20.00); | |||
| INSERT INTO `carburante` VALUES (239,'2024-03-19','1018KPD',93327,43.850,0.00,1.374,60.25); | |||
| INSERT INTO `carburante` VALUES (240,'2024-03-25','7630LYR',15537,19.240,0.00,1.559,30.00); | |||
| INSERT INTO `carburante` VALUES (241,'2024-04-06','7630LYR',15935,29.390,0.00,1.479,43.48); | |||
| INSERT INTO `carburante` VALUES (242,'2024-04-08','1018KPD',94167,41.110,0.00,1.374,56.49); | |||
| INSERT INTO `carburante` VALUES (243,'2024-04-22','7630LYR',16465,25.920,0.00,1.569,40.66); | |||
| INSERT INTO `carburante` VALUES (244,'2024-04-29','1018KPD',95042,43.630,0.00,1.445,63.03); | |||
| INSERT INTO `carburante` VALUES (247,'2024-05-13','7630LYR',16963,26.800,0.00,1.549,41.51); | |||
| INSERT INTO `carburante` VALUES (248,'2024-05-21','1018KPD',96585,28.330,0.00,1.399,39.63); | |||
| INSERT INTO `carburante` VALUES (249,'2024-05-27','1018KPD',97597,49.480,0.00,1.373,67.96); | |||
| /** INSERT INTO `vehiculos` VALUES INSERT INTO `carburante` VALUES (2,'Toyota','Corolla','7630LYR'); | |||
| (3,'BMW','318d','1018KPD'); | |||
| @ -0,0 +1,69 @@ | |||
| from flask import Flask, render_template, redirect, url_for, request | |||
| from flask_sqlalchemy import SQLAlchemy | |||
| from flask_migrate import Migrate | |||
| from flask_login import LoginManager, login_required, current_user | |||
| from models import db, Student, User, Carburante | |||
| from forms import RepostajeForm | |||
| app = Flask(__name__) | |||
| app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///students.db' | |||
| app.config['SECRET_KEY'] = 'mysecret' | |||
| db.init_app(app) | |||
| migrate = Migrate(app, db) | |||
| login_manager = LoginManager() | |||
| login_manager.login_view = 'auth.login' | |||
| login_manager.init_app(app) | |||
| @login_manager.user_loader | |||
| def load_user(user_id): | |||
| # since the user_id is just the primary key of our user table, use it in the query for the user | |||
| return User.query.get(int(user_id)) | |||
| # blueprint for auth routes in our app | |||
| from auth import auth as auth_blueprint | |||
| app.register_blueprint(auth_blueprint) | |||
| @app.route('/') | |||
| def index(): | |||
| repostajes = Carburante.query.all() | |||
| return render_template('index.html', repostajes=repostajes) | |||
| @app.route('/add', methods=['GET', 'POST']) | |||
| @login_required | |||
| def add_repostaje(): | |||
| form = RepostajeForm() | |||
| if form.validate_on_submit(): | |||
| precioxlitro = (form.importe.data - form.descuento.data) / form.litros.data | |||
| repostaje = Carburante(fecha=form.fecha.data, vehiculo=form.vehiculo.data, kms=form.kms.data, litros=form.litros.data, descuento=form.descuento.data, importe=form.importe.data, precioxlitro=precioxlitro) | |||
| db.session.add(repostaje) | |||
| db.session.commit() | |||
| return redirect(url_for('index')) | |||
| return render_template('add_record.html', form=form) | |||
| @app.route('/edit/<int:id>', methods=['GET', 'POST']) | |||
| @login_required | |||
| def edit_repostaje(identificador): | |||
| repostaje = Carburante.query.get_or_404(id) | |||
| form = RepostajeForm(obj=repostaje) | |||
| if form.validate_on_submit(): | |||
| repostaje.name = form.name.data | |||
| repostaje.age = form.age.data | |||
| repostaje.grade = form.grade.data | |||
| db.session.commit() | |||
| return redirect(url_for('index')) | |||
| return render_template('edit_record.html', form=form, repostaje=repostaje) | |||
| @app.route('/delete/<int:id>') | |||
| @login_required | |||
| def delete_repostaje(id): | |||
| repostaje = Carburante.query.get_or_404(id) | |||
| db.session.delete(repostaje) | |||
| db.session.commit() | |||
| return redirect(url_for('index')) | |||
| if __name__ == '__main__': | |||
| app.run(debug=True) | |||
| @ -0,0 +1,62 @@ | |||
| # auth.py | |||
| from flask import Blueprint, render_template, redirect, url_for, request, flash | |||
| from werkzeug.security import generate_password_hash, check_password_hash | |||
| from flask_login import login_user, logout_user, login_required | |||
| from models import User, db | |||
| auth = Blueprint('auth', __name__) | |||
| @auth.route('/login') | |||
| def login(): | |||
| return render_template('login.html') | |||
| @auth.route('/login', methods=['POST']) | |||
| def login_post(): | |||
| email = request.form.get('email') | |||
| password = request.form.get('password') | |||
| remember = True if request.form.get('remember') else False | |||
| user = User.query.filter_by(email=email).first() | |||
| # check if user actually exists | |||
| # take the user supplied password, hash it, and compare it to the hashed password in database | |||
| if not user or not check_password_hash(user.password, password): | |||
| flash('Please check your login details and try again.') | |||
| return redirect(url_for('auth.login')) # if user doesn't exist or password is wrong, reload the page | |||
| # if the above check passes, then we know the user has the right credentials | |||
| login_user(user, remember=remember) | |||
| return redirect(url_for('index')) | |||
| @auth.route('/signup') | |||
| def signup(): | |||
| return render_template('signup.html') | |||
| @auth.route('/signup', methods=['POST']) | |||
| def signup_post(): | |||
| email = request.form.get('email') | |||
| name = request.form.get('name') | |||
| password = request.form.get('password') | |||
| user = User.query.filter_by(email=email).first() # if this returns a user, then the email already exists in database | |||
| if user: # if a user is found, we want to redirect back to signup page so user can try again | |||
| flash('Email address already exists') | |||
| return redirect(url_for('auth.signup')) | |||
| # create new user with the form data. Hash the password so plaintext version isn't saved. | |||
| new_user = User(email=email, name=name, password=generate_password_hash(password, method='pbkdf2:sha256')) | |||
| # add the new user to the database | |||
| db.session.add(new_user) | |||
| db.session.commit() | |||
| return redirect(url_for('auth.login')) | |||
| @auth.route('/logout') | |||
| @login_required | |||
| def logout(): | |||
| logout_user() | |||
| return redirect(url_for('index')) | |||
| @ -0,0 +1,21 @@ | |||
| from flask_wtf import FlaskForm | |||
| from wtforms import StringField, IntegerField, SubmitField, DateField, BooleanField, DecimalField, fields | |||
| from wtforms.validators import DataRequired | |||
| class FlexibleDecimalField(fields.DecimalField): | |||
| def process_formdata(self, valuelist): | |||
| if valuelist: | |||
| valuelist[0] = valuelist[0].replace(",", ".") | |||
| return super(FlexibleDecimalField, self).process_formdata(valuelist) | |||
| class RepostajeForm(FlaskForm): | |||
| fecha = DateField('Fecha', validators=[DataRequired()]) | |||
| vehiculo = StringField('Vehículo', validators=[DataRequired()]) | |||
| kms = IntegerField('Kilómetros', validators=[DataRequired()]) | |||
| litros = FlexibleDecimalField('Litros', validators=[DataRequired()]) | |||
| descuento = BooleanField('Descuento') | |||
| importe = FlexibleDecimalField('Importe', validators=[DataRequired()]) | |||
| submit = SubmitField('Crear') | |||
| @ -0,0 +1,4 @@ | |||
| export FLASK_APP=app.py | |||
| flask db init | |||
| flask db migrate -m "Initial migration." | |||
| flask db upgrade | |||
| @ -0,0 +1 @@ | |||
| Single-database configuration for Flask. | |||
| @ -0,0 +1,50 @@ | |||
| # A generic, single database configuration. | |||
| [alembic] | |||
| # template used to generate migration files | |||
| # file_template = %%(rev)s_%%(slug)s | |||
| # set to 'true' to run the environment during | |||
| # the 'revision' command, regardless of autogenerate | |||
| # revision_environment = false | |||
| # Logging configuration | |||
| [loggers] | |||
| keys = root,sqlalchemy,alembic,flask_migrate | |||
| [handlers] | |||
| keys = console | |||
| [formatters] | |||
| keys = generic | |||
| [logger_root] | |||
| level = WARN | |||
| handlers = console | |||
| qualname = | |||
| [logger_sqlalchemy] | |||
| level = WARN | |||
| handlers = | |||
| qualname = sqlalchemy.engine | |||
| [logger_alembic] | |||
| level = INFO | |||
| handlers = | |||
| qualname = alembic | |||
| [logger_flask_migrate] | |||
| level = INFO | |||
| handlers = | |||
| qualname = flask_migrate | |||
| [handler_console] | |||
| class = StreamHandler | |||
| args = (sys.stderr,) | |||
| level = NOTSET | |||
| formatter = generic | |||
| [formatter_generic] | |||
| format = %(levelname)-5.5s [%(name)s] %(message)s | |||
| datefmt = %H:%M:%S | |||
| @ -0,0 +1,113 @@ | |||
| import logging | |||
| from logging.config import fileConfig | |||
| from flask import current_app | |||
| from alembic import context | |||
| # this is the Alembic Config object, which provides | |||
| # access to the values within the .ini file in use. | |||
| config = context.config | |||
| # Interpret the config file for Python logging. | |||
| # This line sets up loggers basically. | |||
| fileConfig(config.config_file_name) | |||
| logger = logging.getLogger('alembic.env') | |||
| def get_engine(): | |||
| try: | |||
| # this works with Flask-SQLAlchemy<3 and Alchemical | |||
| return current_app.extensions['migrate'].db.get_engine() | |||
| except (TypeError, AttributeError): | |||
| # this works with Flask-SQLAlchemy>=3 | |||
| return current_app.extensions['migrate'].db.engine | |||
| def get_engine_url(): | |||
| try: | |||
| return get_engine().url.render_as_string(hide_password=False).replace( | |||
| '%', '%%') | |||
| except AttributeError: | |||
| return str(get_engine().url).replace('%', '%%') | |||
| # add your model's MetaData object here | |||
| # for 'autogenerate' support | |||
| # from myapp import mymodel | |||
| # target_metadata = mymodel.Base.metadata | |||
| config.set_main_option('sqlalchemy.url', get_engine_url()) | |||
| target_db = current_app.extensions['migrate'].db | |||
| # other values from the config, defined by the needs of env.py, | |||
| # can be acquired: | |||
| # my_important_option = config.get_main_option("my_important_option") | |||
| # ... etc. | |||
| def get_metadata(): | |||
| if hasattr(target_db, 'metadatas'): | |||
| return target_db.metadatas[None] | |||
| return target_db.metadata | |||
| def run_migrations_offline(): | |||
| """Run migrations in 'offline' mode. | |||
| This configures the context with just a URL | |||
| and not an Engine, though an Engine is acceptable | |||
| here as well. By skipping the Engine creation | |||
| we don't even need a DBAPI to be available. | |||
| Calls to context.execute() here emit the given string to the | |||
| script output. | |||
| """ | |||
| url = config.get_main_option("sqlalchemy.url") | |||
| context.configure( | |||
| url=url, target_metadata=get_metadata(), literal_binds=True | |||
| ) | |||
| with context.begin_transaction(): | |||
| context.run_migrations() | |||
| def run_migrations_online(): | |||
| """Run migrations in 'online' mode. | |||
| In this scenario we need to create an Engine | |||
| and associate a connection with the context. | |||
| """ | |||
| # this callback is used to prevent an auto-migration from being generated | |||
| # when there are no changes to the schema | |||
| # reference: http://alembic.zzzcomputing.com/en/latest/cookbook.html | |||
| def process_revision_directives(context, revision, directives): | |||
| if getattr(config.cmd_opts, 'autogenerate', False): | |||
| script = directives[0] | |||
| if script.upgrade_ops.is_empty(): | |||
| directives[:] = [] | |||
| logger.info('No changes in schema detected.') | |||
| conf_args = current_app.extensions['migrate'].configure_args | |||
| if conf_args.get("process_revision_directives") is None: | |||
| conf_args["process_revision_directives"] = process_revision_directives | |||
| connectable = get_engine() | |||
| with connectable.connect() as connection: | |||
| context.configure( | |||
| connection=connection, | |||
| target_metadata=get_metadata(), | |||
| **conf_args | |||
| ) | |||
| with context.begin_transaction(): | |||
| context.run_migrations() | |||
| if context.is_offline_mode(): | |||
| run_migrations_offline() | |||
| else: | |||
| run_migrations_online() | |||
| @ -0,0 +1,24 @@ | |||
| """${message} | |||
| Revision ID: ${up_revision} | |||
| Revises: ${down_revision | comma,n} | |||
| Create Date: ${create_date} | |||
| """ | |||
| from alembic import op | |||
| import sqlalchemy as sa | |||
| ${imports if imports else ""} | |||
| # revision identifiers, used by Alembic. | |||
| revision = ${repr(up_revision)} | |||
| down_revision = ${repr(down_revision)} | |||
| branch_labels = ${repr(branch_labels)} | |||
| depends_on = ${repr(depends_on)} | |||
| def upgrade(): | |||
| ${upgrades if upgrades else "pass"} | |||
| def downgrade(): | |||
| ${downgrades if downgrades else "pass"} | |||
| @ -0,0 +1,46 @@ | |||
| """Initial migration. | |||
| Revision ID: 8eb4774e3960 | |||
| Revises: aa6e7ede1321 | |||
| Create Date: 2024-06-10 15:30:29.774459 | |||
| """ | |||
| from alembic import op | |||
| import sqlalchemy as sa | |||
| # revision identifiers, used by Alembic. | |||
| revision = '8eb4774e3960' | |||
| down_revision = 'aa6e7ede1321' | |||
| branch_labels = None | |||
| depends_on = None | |||
| def upgrade(): | |||
| # ### commands auto generated by Alembic - please adjust! ### | |||
| op.create_table('carburante', | |||
| sa.Column('identificador', sa.Integer(), nullable=False), | |||
| sa.Column('fecha', sa.Date(), nullable=True), | |||
| sa.Column('vehiculo', sa.String(length=20), nullable=True), | |||
| sa.Column('kms', sa.Integer(), nullable=True), | |||
| sa.Column('litros', sa.DECIMAL(precision=10, scale=3), nullable=True), | |||
| sa.Column('descuento', sa.DECIMAL(precision=10, scale=2), nullable=True), | |||
| sa.Column('precioxlitro', sa.DECIMAL(precision=10, scale=3), nullable=True), | |||
| sa.Column('importe', sa.DECIMAL(precision=10, scale=2), nullable=True), | |||
| sa.PrimaryKeyConstraint('identificador') | |||
| ) | |||
| op.create_table('vehiculos', | |||
| sa.Column('identificador', sa.Integer(), nullable=False), | |||
| sa.Column('marca', sa.String(length=20), nullable=True), | |||
| sa.Column('modelo', sa.String(length=20), nullable=True), | |||
| sa.Column('matricula', sa.String(length=20), nullable=True), | |||
| sa.PrimaryKeyConstraint('identificador') | |||
| ) | |||
| # ### end Alembic commands ### | |||
| def downgrade(): | |||
| # ### commands auto generated by Alembic - please adjust! ### | |||
| op.drop_table('vehiculos') | |||
| op.drop_table('carburante') | |||
| # ### end Alembic commands ### | |||
| @ -0,0 +1,34 @@ | |||
| """Initial migration. | |||
| Revision ID: 9f932e36f8fb | |||
| Revises: | |||
| Create Date: 2024-06-10 14:54:57.602942 | |||
| """ | |||
| from alembic import op | |||
| import sqlalchemy as sa | |||
| # revision identifiers, used by Alembic. | |||
| revision = '9f932e36f8fb' | |||
| down_revision = None | |||
| branch_labels = None | |||
| depends_on = None | |||
| def upgrade(): | |||
| # ### commands auto generated by Alembic - please adjust! ### | |||
| op.create_table('student', | |||
| sa.Column('id', sa.Integer(), nullable=False), | |||
| sa.Column('name', sa.String(length=100), nullable=False), | |||
| sa.Column('age', sa.Integer(), nullable=False), | |||
| sa.Column('grade', sa.String(length=10), nullable=False), | |||
| sa.PrimaryKeyConstraint('id') | |||
| ) | |||
| # ### end Alembic commands ### | |||
| def downgrade(): | |||
| # ### commands auto generated by Alembic - please adjust! ### | |||
| op.drop_table('student') | |||
| # ### end Alembic commands ### | |||
| @ -0,0 +1,35 @@ | |||
| """Initial migration. | |||
| Revision ID: aa6e7ede1321 | |||
| Revises: 9f932e36f8fb | |||
| Create Date: 2024-06-10 15:16:49.313757 | |||
| """ | |||
| from alembic import op | |||
| import sqlalchemy as sa | |||
| # revision identifiers, used by Alembic. | |||
| revision = 'aa6e7ede1321' | |||
| down_revision = '9f932e36f8fb' | |||
| branch_labels = None | |||
| depends_on = None | |||
| def upgrade(): | |||
| # ### commands auto generated by Alembic - please adjust! ### | |||
| op.create_table('user', | |||
| sa.Column('id', sa.Integer(), nullable=False), | |||
| sa.Column('email', sa.String(length=100), nullable=True), | |||
| sa.Column('password', sa.String(length=100), nullable=True), | |||
| sa.Column('name', sa.String(length=1000), nullable=True), | |||
| sa.PrimaryKeyConstraint('id'), | |||
| sa.UniqueConstraint('email') | |||
| ) | |||
| # ### end Alembic commands ### | |||
| def downgrade(): | |||
| # ### commands auto generated by Alembic - please adjust! ### | |||
| op.drop_table('user') | |||
| # ### end Alembic commands ### | |||
| @ -0,0 +1,35 @@ | |||
| from flask_sqlalchemy import SQLAlchemy | |||
| from flask_login import UserMixin | |||
| db = SQLAlchemy() | |||
| class Student(db.Model): | |||
| id = db.Column(db.Integer, primary_key=True) | |||
| name = db.Column(db.String(100), nullable=False) | |||
| age = db.Column(db.Integer, nullable=False) | |||
| grade = db.Column(db.String(10), nullable=False) | |||
| def __repr__(self): | |||
| return f'<Student {self.name}>' | |||
| class User(UserMixin, db.Model): | |||
| id = db.Column(db.Integer, primary_key=True) # primary keys are required by SQLAlchemy | |||
| email = db.Column(db.String(100), unique=True) | |||
| password = db.Column(db.String(100)) | |||
| name = db.Column(db.String(1000)) | |||
| class Carburante(db.Model): | |||
| identificador = db.Column(db.Integer, primary_key=True) | |||
| fecha = db.Column(db.Date()) | |||
| vehiculo = db.Column(db.String(20)) | |||
| kms = db.Column(db.Integer) | |||
| litros = db.Column(db.DECIMAL(10,3)) | |||
| descuento = db.Column(db.DECIMAL(10,2)) | |||
| precioxlitro = db.Column(db.DECIMAL(10,3)) | |||
| importe = db.Column(db.DECIMAL(10,2)) | |||
| class Vehiculos(db.Model): | |||
| identificador = db.Column(db.Integer, primary_key=True) | |||
| marca = db.Column(db.String(20)) | |||
| modelo = db.Column(db.String(20)) | |||
| matricula = db.Column(db.String(20)) | |||
| @ -0,0 +1,88 @@ | |||
| INSERT INTO `carburante` VALUES (1,'2021-12-14','1018KPD',52731,0.000,0.00,0.000,0.00); | |||
| INSERT INTO `carburante` VALUES (2,'2021-12-23','1018KPD',53162,52.800,0.00,1.280,67.32); | |||
| INSERT INTO `carburante` VALUES (3,'2021-12-31','1018KPD',54122,49.990,0.00,1.280,63.74); | |||
| INSERT INTO `carburante` VALUES (4,'2022-01-22','1018KPD',54946,49.140,0.00,1.270,62.65); | |||
| INSERT INTO `carburante` VALUES (5,'2022-02-09','1018KPD',55908,49.240,0.00,1.320,65.24); | |||
| INSERT INTO `carburante` VALUES (6,'2022-03-03','1018KPD',56909,48.610,0.00,1.380,67.03); | |||
| INSERT INTO `carburante` VALUES (7,'2022-03-18','1018KPD',57542,30.060,0.00,1.750,52.54); | |||
| INSERT INTO `carburante` VALUES (8,'2022-04-10','1018KPD',58497,46.630,0.00,1.500,69.98); | |||
| INSERT INTO `carburante` VALUES (9,'2022-05-12','1018KPD',59447,47.140,0.00,1.530,72.11); | |||
| INSERT INTO `carburante` VALUES (10,'2022-05-19','1018KPD',60414,48.570,0.00,1.640,79.81); | |||
| INSERT INTO `carburante` VALUES (11,'2022-06-09','1018KPD',61147,36.200,0.00,1.720,62.12); | |||
| INSERT INTO `carburante` VALUES (12,'2022-06-25','1018KPD',62116,49.170,0.00,1.840,90.29); | |||
| INSERT INTO `carburante` VALUES (16,'2022-09-14','1018KPD',66359,53.240,0.00,1.590,84.83); | |||
| INSERT INTO `carburante` VALUES (17,'2022-09-23','1018KPD',67107,37.260,0.00,1.490,55.48); | |||
| INSERT INTO `carburante` VALUES (19,'2023-01-24','1018KPD',71790,43.040,2.12,1.590,70.54); | |||
| INSERT INTO `carburante` VALUES (21,'2022-12-03','1018KPD',70061,46.380,2.04,1.420,68.13); | |||
| INSERT INTO `carburante` VALUES (22,'2022-12-26','1018KPD',70919,44.580,1.85,1.340,61.68); | |||
| INSERT INTO `carburante` VALUES (23,'2023-03-05','1018KPD',73711,47.850,0.00,1.490,71.20); | |||
| INSERT INTO `carburante` VALUES (24,'2023-03-25','1018KPD',74749,49.840,0.00,1.450,72.17); | |||
| INSERT INTO `carburante` VALUES (25,'2023-02-19','1018KPD',72763,49.380,2.34,1.530,77.97); | |||
| INSERT INTO `carburante` VALUES (27,'2023-05-06','1018KPD',76434,32.280,0.00,1.370,44.09); | |||
| INSERT INTO `carburante` VALUES (28,'2023-05-22','1018KPD',77366,45.040,0.00,1.300,58.46); | |||
| INSERT INTO `carburante` VALUES (45,'2022-07-09','1018KPD',63129,47.030,0.00,1.690,79.38); | |||
| INSERT INTO `carburante` VALUES (46,'2022-08-12','1018KPD',64088,43.730,0.00,1.500,65.55); | |||
| INSERT INTO `carburante` VALUES (47,'2022-08-22','1018KPD',65185,52.780,0.00,1.490,78.80); | |||
| INSERT INTO `carburante` VALUES (50,'2022-10-12','1018KPD',68204,52.040,2.51,1.560,83.73); | |||
| INSERT INTO `carburante` VALUES (51,'2022-11-11','1018KPD',69158,45.280,2.37,1.690,78.91); | |||
| INSERT INTO `carburante` VALUES (61,'2023-06-10','1018KPD',78170,41.090,0.00,1.320,54.16); | |||
| INSERT INTO `carburante` VALUES (62,'2023-06-19','1018KPD',79038,40.780,1.95,1.430,60.11); | |||
| INSERT INTO `carburante` VALUES (151,'2022-06-28','7630LYR',219,9.880,0.00,1.920,18.96); | |||
| INSERT INTO `carburante` VALUES (152,'2022-06-28','7630LYR',236,27.360,0.00,1.880,51.33); | |||
| INSERT INTO `carburante` VALUES (153,'2022-07-14','7630LYR',904,32.240,0.00,1.720,55.58); | |||
| INSERT INTO `carburante` VALUES (154,'2022-07-26','7630LYR',1433,30.490,0.00,1.590,48.43); | |||
| INSERT INTO `carburante` VALUES (155,'2022-08-21','7630LYR',2030,32.920,0.00,1.420,46.72); | |||
| INSERT INTO `carburante` VALUES (156,'2022-09-26','7630LYR',2627,23.920,0.00,1.390,33.16); | |||
| INSERT INTO `carburante` VALUES (157,'2022-10-18','7630LYR',3169,22.970,0.00,1.430,32.74); | |||
| INSERT INTO `carburante` VALUES (158,'2022-11-09','7630LYR',3791,29.600,0.00,1.410,41.88); | |||
| INSERT INTO `carburante` VALUES (159,'2022-11-27','7630LYR',4363,28.800,1.20,1.350,38.80); | |||
| INSERT INTO `carburante` VALUES (160,'2022-12-22','7630LYR',4851,26.740,1.06,1.280,34.18); | |||
| INSERT INTO `carburante` VALUES (161,'2023-01-12','7630LYR',5291,23.520,1.09,1.500,35.34); | |||
| INSERT INTO `carburante` VALUES (162,'2023-02-01','7630LYR',5702,27.360,1.28,1.520,41.52); | |||
| INSERT INTO `carburante` VALUES (163,'2023-02-20','7630LYR',6141,24.090,1.13,1.520,36.67); | |||
| INSERT INTO `carburante` VALUES (164,'2023-03-15','7630LYR',6631,25.520,1.21,1.530,38.96); | |||
| INSERT INTO `carburante` VALUES (165,'2023-04-17','7630LYR',7325,29.400,1.47,1.620,47.62); | |||
| INSERT INTO `carburante` VALUES (166,'2023-05-28','7630LYR',8413,24.160,1.17,1.560,37.70); | |||
| INSERT INTO `carburante` VALUES (167,'2023-06-25','7630LYR',8956,26.380,1.30,1.590,41.94); | |||
| INSERT INTO `carburante` VALUES (168,'2023-07-10','7630LYR',9471,29.040,1.35,1.497,43.49); | |||
| INSERT INTO `carburante` VALUES (176,'2023-07-14','1018KPD',79875,40.560,1.74,1.407,56.26); | |||
| INSERT INTO `carburante` VALUES (177,'2023-07-22','1018KPD',80806,46.290,1.95,1.371,63.05); | |||
| INSERT INTO `carburante` VALUES (178,'2023-07-25','7630LYR',10043,24.850,1.40,1.622,40.32); | |||
| INSERT INTO `carburante` VALUES (182,'2023-08-07','1018KPD',81695,44.390,0.00,1.439,63.88); | |||
| INSERT INTO `carburante` VALUES (201,'2023-08-09','7630LYR',10582,26.490,1.39,1.696,44.94); | |||
| INSERT INTO `carburante` VALUES (202,'2023-08-23','7630LYR',11050,24.050,1.22,1.638,39.40); | |||
| INSERT INTO `carburante` VALUES (203,'2023-08-27','1018KPD',82715,50.400,0.00,1.529,77.06); | |||
| INSERT INTO `carburante` VALUES (204,'2023-09-14','7630LYR',11508,21.440,1.14,1.726,37.00); | |||
| INSERT INTO `carburante` VALUES (205,'2023-09-19','1018KPD',83709,48.350,0.00,1.598,77.26); | |||
| INSERT INTO `carburante` VALUES (206,'2023-09-27','1018KPD',84171,23.010,0.00,1.558,35.85); | |||
| INSERT INTO `carburante` VALUES (207,'2023-10-10','1018KPD',85104,48.000,0.00,1.509,72.43); | |||
| INSERT INTO `carburante` VALUES (212,'2023-10-15','7630LYR',12006,25.090,1.25,1.609,40.37); | |||
| INSERT INTO `carburante` VALUES (213,'2023-10-27','1018KPD',86021,46.770,0.00,1.499,70.11); | |||
| INSERT INTO `carburante` VALUES (214,'2023-11-04','7630LYR',12427,25.640,1.17,1.474,37.78); | |||
| INSERT INTO `carburante` VALUES (215,'2023-11-11','1018KPD',86757,39.580,1.71,1.398,55.33); | |||
| INSERT INTO `carburante` VALUES (216,'2023-11-20','7630LYR',12933,26.160,0.00,1.529,40.00); | |||
| INSERT INTO `carburante` VALUES (217,'2023-11-23','1018KPD',87503,42.410,1.75,1.331,56.45); | |||
| INSERT INTO `carburante` VALUES (218,'2023-12-04','1018KPD',88256,41.190,0.00,1.399,57.62); | |||
| INSERT INTO `carburante` VALUES (219,'2023-12-17','1018KPD',88964,41.200,1.66,1.305,53.78); | |||
| INSERT INTO `carburante` VALUES (220,'2024-01-06','7630LYR',13414,30.720,1.34,1.411,43.36); | |||
| INSERT INTO `carburante` VALUES (222,'2024-01-07','1018KPD',89802,47.770,1.91,1.293,61.75); | |||
| INSERT INTO `carburante` VALUES (223,'2024-01-22','7630LYR',13903,25.080,0.00,1.479,37.09); | |||
| INSERT INTO `carburante` VALUES (224,'2024-01-27','1018KPD',90723,45.250,0.00,1.334,60.37); | |||
| INSERT INTO `carburante` VALUES (226,'2024-02-11','7630LYR',14365,28.450,0.00,1.454,41.37); | |||
| INSERT INTO `carburante` VALUES (233,'2024-02-12','1018KPD',91672,48.310,0.00,1.449,70.00); | |||
| INSERT INTO `carburante` VALUES (235,'2024-02-27','1018KPD',92489,41.990,0.00,1.379,57.91); | |||
| INSERT INTO `carburante` VALUES (236,'2024-02-29','7630LYR',14857,23.960,1.12,1.517,36.35); | |||
| INSERT INTO `carburante` VALUES (237,'2024-03-18','7630LYR',15287,13.000,0.00,1.538,20.00); | |||
| INSERT INTO `carburante` VALUES (239,'2024-03-19','1018KPD',93327,43.850,0.00,1.374,60.25); | |||
| INSERT INTO `carburante` VALUES (240,'2024-03-25','7630LYR',15537,19.240,0.00,1.559,30.00); | |||
| INSERT INTO `carburante` VALUES (241,'2024-04-06','7630LYR',15935,29.390,0.00,1.479,43.48); | |||
| INSERT INTO `carburante` VALUES (242,'2024-04-08','1018KPD',94167,41.110,0.00,1.374,56.49); | |||
| INSERT INTO `carburante` VALUES (243,'2024-04-22','7630LYR',16465,25.920,0.00,1.569,40.66); | |||
| INSERT INTO `carburante` VALUES (244,'2024-04-29','1018KPD',95042,43.630,0.00,1.445,63.03); | |||
| INSERT INTO `carburante` VALUES (247,'2024-05-13','7630LYR',16963,26.800,0.00,1.549,41.51); | |||
| INSERT INTO `carburante` VALUES (248,'2024-05-21','1018KPD',96585,28.330,0.00,1.399,39.63); | |||
| INSERT INTO `carburante` VALUES (249,'2024-05-27','1018KPD',97597,49.480,0.00,1.373,67.96); | |||
| INSERT INTO `vehiculos` VALUES (2,'Toyota','Corolla','7630LYR'); | |||
| INSERT INTO `vehiculos` VALUES (3,'BMW','318d','1018KPD'); | |||
| @ -0,0 +1,27 @@ | |||
| {% extends "layout.html" %} | |||
| {% block content %} | |||
| <h1>Add Student</h1> | |||
| <form method="POST"> | |||
| {{ form.hidden_tag() }} | |||
| <div class="form-group"> | |||
| {{ form.fecha.label }} {{ form.fecha(class_="form-control") }} | |||
| </div> | |||
| <div class="form-group"> | |||
| {{ form.vehiculo.label }} {{ form.vehiculo(class_="form-control") }} | |||
| </div> | |||
| <div class="form-group"> | |||
| {{ form.kms.label }} {{ form.kms(class_="form-control") }} | |||
| </div> | |||
| <div class="form-group"> | |||
| {{ form.litros.label }} {{ form.litros(class_="form-control") }} | |||
| </div> | |||
| <div class="form-group"> | |||
| {{ form.descuento.label }} {{ form.descuento(class_="form-control") }} | |||
| </div> | |||
| <div class="form-group"> | |||
| {{ form.importe.label }} {{ form.importe(class_="form-control") }} | |||
| </div> | |||
| {{ form.submit(class_="btn btn-primary") }} | |||
| </form> | |||
| {% endblock %} | |||
| @ -0,0 +1,59 @@ | |||
| <!-- templates/base.html --> | |||
| <!DOCTYPE html> | |||
| <html> | |||
| <head> | |||
| <meta charset="utf-8"> | |||
| <meta http-equiv="X-UA-Compatible" content="IE=edge"> | |||
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |||
| <title>Flask Auth Example</title> | |||
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.2/css/bulma.min.css" /> | |||
| </head> | |||
| <body> | |||
| <section class="hero is-primary is-fullheight"> | |||
| <div class="hero-head"> | |||
| <nav class="navbar"> | |||
| <div class="container"> | |||
| <div id="navbarMenuHeroA" class="navbar-menu"> | |||
| <div class="navbar-end"> | |||
| <a href="{{ url_for('index') }}" class="navbar-item"> | |||
| Home | |||
| </a> | |||
| {% if current_user.is_authenticated %} | |||
| <a href="{{ url_for('main.profile') }}" class="navbar-item"> | |||
| Profile | |||
| </a> | |||
| {% endif %} | |||
| {% if not current_user.is_authenticated %} | |||
| <a href="{{ url_for('auth.login') }}" class="navbar-item"> | |||
| Login | |||
| </a> | |||
| <a href="{{ url_for('auth.signup') }}" class="navbar-item"> | |||
| Sign Up | |||
| </a> | |||
| {% endif %} | |||
| {% if current_user.is_authenticated %} | |||
| <a href="{{ url_for('auth.logout') }}" class="navbar-item"> | |||
| Logout | |||
| </a> | |||
| {% endif %} | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </nav> | |||
| </div> | |||
| <div class="hero-body"> | |||
| <div class="container has-text-centered"> | |||
| {% block content %} | |||
| {% endblock %} | |||
| </div> | |||
| </div> | |||
| </section> | |||
| </body> | |||
| </html> | |||
| @ -0,0 +1,17 @@ | |||
| {% extends "layout.html" %} | |||
| {% block content %} | |||
| <h1>Edit Student</h1> | |||
| <form method="POST"> | |||
| {{ form.hidden_tag() }} | |||
| <div class="form-group"> | |||
| {{ form.name.label }} {{ form.name(class_="form-control") }} | |||
| </div> | |||
| <div class="form-group"> | |||
| {{ form.age.label }} {{ form.age(class_="form-control") }} | |||
| </div> | |||
| <div class="form-group"> | |||
| {{ form.grade.label }} {{ form.grade(class_="form-control") }} | |||
| </div> | |||
| {{ form.submit(class_="btn btn-primary") }} | |||
| </form> | |||
| {% endblock %} | |||
| @ -0,0 +1,35 @@ | |||
| {% extends "layout.html" %} | |||
| {% block content %} | |||
| <h1>Students List</h1> | |||
| <a href="{{ url_for('add_repostaje') }}" class="btn btn-primary">Add Student</a> | |||
| <table class="table"> | |||
| <thead> | |||
| <tr> | |||
| <th>ID</th> | |||
| <th>Name</th> | |||
| <th>Age</th> | |||
| <th>Grade</th> | |||
| <th>Actions</th> | |||
| </tr> | |||
| </thead> | |||
| <tbody> | |||
| {% for repostajes in repostajess %} | |||
| <tr> | |||
| <td>{{ repostajes.identificador }}</td> | |||
| <td>{{ repostajes.fecha }}</td> | |||
| <td>{{ repostajes.vehiculo }}</td> | |||
| <td>{{ repostajes.kms }}</td> | |||
| <td>{{ repostajes.litros }}</td> | |||
| <td>{{ repostajes.descuento }}</td> | |||
| <td>{{ repostajes.precioxlitro }}</td> | |||
| <td>{{ repostajes.importe }}</td> | |||
| <td> | |||
| <a href="{{ url_for('edit_record', id=repostajes.identificador) }}" class="btn btn-warning">Edit</a> | |||
| <a href="{{ url_for('delete_record', id=repostajes.identificador) }}" class="btn btn-danger">Delete</a> | |||
| </td> | |||
| </tr> | |||
| {% endfor %} | |||
| </tbody> | |||
| </table> | |||
| {% endblock %} | |||
| @ -0,0 +1,12 @@ | |||
| <!DOCTYPE html> | |||
| <html> | |||
| <head> | |||
| <title>Student CRUD</title> | |||
| <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"> | |||
| </head> | |||
| <body> | |||
| <div class="container"> | |||
| {% block content %}{% endblock %} | |||
| </div> | |||
| </body> | |||
| </html> | |||
| @ -0,0 +1,42 @@ | |||
| <!-- templates/login.html --> | |||
| {% extends "base.html" %} | |||
| {% block content %} | |||
| <div class="column is-4 is-offset-4"> | |||
| <h3 class="title">Login</h3> | |||
| <div class="box"> | |||
| {% with messages = get_flashed_messages() %} | |||
| {% if messages %} | |||
| <div class="notification is-danger"> | |||
| {{ messages[0] }} | |||
| </div> | |||
| {% endif %} | |||
| {% endwith %} | |||
| <form method="POST" action="/login"> | |||
| <div class="field"> | |||
| <div class="control"> | |||
| <input class="input is-large" type="email" name="email" placeholder="Your Email" autofocus=""> | |||
| </div> | |||
| </div> | |||
| <div class="field"> | |||
| <div class="control"> | |||
| <input class="input is-large" type="password" name="password" placeholder="Your Password"> | |||
| </div> | |||
| </div> | |||
| <div class="field"> | |||
| <label class="checkbox"> | |||
| <input type="checkbox"> | |||
| Remember me | |||
| </label> | |||
| </div> | |||
| <button class="button is-block is-info is-large is-fullwidth">Login</button> | |||
| </form> | |||
| <div class="field"> | |||
| <a class="tag is-link" href="{{ url_for('auth.signup') }}">Crear una cuenta</a>. | |||
| </div> | |||
| </div> | |||
| </div> | |||
| {% endblock %} | |||
| @ -0,0 +1,39 @@ | |||
| <!-- templates/signup.html --> | |||
| {% extends "base.html" %} | |||
| {% block content %} | |||
| <div class="column is-4 is-offset-4"> | |||
| <h3 class="title">Sign Up</h3> | |||
| <div class="box"> | |||
| {% with messages = get_flashed_messages() %} | |||
| {% if messages %} | |||
| <div class="notification is-danger"> | |||
| {{ messages[0] }}. Go to <a href="{{ url_for('auth.login') }}">login page</a>. | |||
| </div> | |||
| {% endif %} | |||
| {% endwith %} | |||
| <form method="POST" action="/signup"> | |||
| <div class="field"> | |||
| <div class="control"> | |||
| <input class="input is-large" type="email" name="email" placeholder="Email" autofocus=""> | |||
| </div> | |||
| </div> | |||
| <div class="field"> | |||
| <div class="control"> | |||
| <input class="input is-large" type="text" name="name" placeholder="Name" autofocus=""> | |||
| </div> | |||
| </div> | |||
| <div class="field"> | |||
| <div class="control"> | |||
| <input class="input is-large" type="password" name="password" placeholder="Password"> | |||
| </div> | |||
| </div> | |||
| <button class="button is-block is-info is-large is-fullwidth">Sign Up</button> | |||
| </form> | |||
| </div> | |||
| </div> | |||
| {% endblock %} | |||