From b0a7efb13855ddde1cddcf6d1bb7ee8f8a9e8401 Mon Sep 17 00:00:00 2001 From: Celestino Rey Date: Tue, 25 Jun 2024 08:37:57 +0200 Subject: [PATCH] =?UTF-8?q?N=C3=BAmeros=20de=20pista=20actualizados?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- LyricsPy/servicios/instance/songs.db | Bin 69632 -> 69632 bytes PyRepostajes/__init__.py | 0 PyRepostajes/app.py | 49 ++++++++ PyRepostajes/forms.py | 17 +++ PyRepostajes/initdb.sh | 4 + PyRepostajes/migrations/README | 1 + PyRepostajes/migrations/alembic.ini | 50 ++++++++ PyRepostajes/migrations/env.py | 113 ++++++++++++++++++ PyRepostajes/migrations/script.py.mako | 24 ++++ .../55bdc15a1654_initial_migration.py | 46 +++++++ PyRepostajes/models.py | 24 ++++ PyRepostajes/templates/add_repostaje.html | 26 ++++ PyRepostajes/templates/add_vehicle.html | 14 +++ PyRepostajes/templates/index.html | 46 +++++++ PyRepostajes/templates/layout.html | 12 ++ RepostajesPy/requirements.txt | 17 +++ RepostajesPy/templates/index.html | 3 +- instance/vehicles.db | Bin 0 -> 24576 bytes 18 files changed, 445 insertions(+), 1 deletion(-) create mode 100644 PyRepostajes/__init__.py create mode 100644 PyRepostajes/app.py create mode 100644 PyRepostajes/forms.py create mode 100644 PyRepostajes/initdb.sh create mode 100644 PyRepostajes/migrations/README create mode 100644 PyRepostajes/migrations/alembic.ini create mode 100644 PyRepostajes/migrations/env.py create mode 100644 PyRepostajes/migrations/script.py.mako create mode 100644 PyRepostajes/migrations/versions/55bdc15a1654_initial_migration.py create mode 100644 PyRepostajes/models.py create mode 100644 PyRepostajes/templates/add_repostaje.html create mode 100644 PyRepostajes/templates/add_vehicle.html create mode 100644 PyRepostajes/templates/index.html create mode 100644 PyRepostajes/templates/layout.html create mode 100644 RepostajesPy/requirements.txt create mode 100644 instance/vehicles.db diff --git a/LyricsPy/servicios/instance/songs.db b/LyricsPy/servicios/instance/songs.db index 3d4b1651abaee4dd597d6fe59ecb22f8affc5743..0f774b5e901cae73a38be42afbb9bed90e654648 100644 GIT binary patch delta 717 zcmZXSPe>F|9LImZnKv`4CY9t z1|!a{WLX4aU9A=XC?#p*T;Zdq z2!+Ff-RVKOKlO%aDggQ5+G~W5)M*qt1RGDGq+L6SMf`rs5NMy3A=mCx_>Bt&g<8RG z2T_inOR1(lQK3^1g3X^r`K{XwaIN?VwHRnI*WRn~$#zPiMzDo6%BH^6K-BP4Aq+;` zyZ$?4p#X(W!DgDhf`i;JnbX2391v{Iqe=`vqZa*_umLO&8;-rkont12HcvzZauGudV?iPDI^6hHlSR6-eg+3 zUsc%xWs6U_c0u9Jp0eTqIC~Lg`rTb>8Y4aBero0_N_>5qc&m9<6xalhVbifc@rh7~ zLY=^Q&*7hS9x%yh-wp~@0<(>nZ6B_b(JyaF(66gP8t5-A0BOfg@zHP1?zEnw}LE!jql-1u0-h^XN;iu0eP_myt^ld7m7mQxlP8-|_R2RP$&UWGB0Rx99 F(!T*-s@(tp delta 634 zcmXw%O-NK>6o$`t|IWSVj^kgBk=8IHCbsYsVi;7yWT3*ZG#4!f3JnPnl8>~INNiy` z;m_Pg%aCA30wGMgeT5srh1jN55k(l$CbV1>g$zMh&Wx=O?|a_&IcF%T4JEaB8S^{k zkwQPzG=9hf0L2@E{8n#B78b1K$&mMTK-&a$(-ogoxmoevPOLPZG*$s4Y}FM@jPBf2 z5dz$rj>uT^HJzM#1)-9&xv+fIBu!7&)7Sw!XzaM+r$M6u9ifd|lTrC4dO)LCR70ra z*4@jp`rKPBCs2k#|E3JPVnCtWorvJ))_A@g>x`;2Rcs(|Zq0YdUtJ!e%m${{f?n&2 z!#Yj3m?bm*$WIC zU_F5iN34?*@gTJ977EDk@nw_7T5W_7XEW`I0e_|Z_~3|P)Br9(jU$3Ial?zy$k{`` z3?=)J;%#|Z9LX;EV!qkTh1C{8TXe-EjqaVzM`++|;j~7-#g;;&T}4@a{JKo7U(m=oRG5LuQay6#&Hevnw!tRYcEnej zD%yuo!P$Jb{PWo+id`*6DCH~>PMjI>$?C0lnm5B!gR#w|LrX?(CG>pHu8@ZV`8*8=+i`(4qqOW53>c@dU6zch&KmiZ6( Cm8rr2 diff --git a/PyRepostajes/__init__.py b/PyRepostajes/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/PyRepostajes/app.py b/PyRepostajes/app.py new file mode 100644 index 0000000..b4c785d --- /dev/null +++ b/PyRepostajes/app.py @@ -0,0 +1,49 @@ +from flask import Flask, render_template, redirect, url_for +from flask_sqlalchemy import SQLAlchemy +from flask_migrate import Migrate +from .models import db, Vehicle, Repostaje +from .forms import VehicleForm, RepostajeForm + +app = Flask(__name__) +app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///vehicles.db' +app.config['SECRET_KEY'] = 'mysecret' + +db.init_app(app) +migrate = Migrate(app, db) + +@app.route('/') +def index(): + vehicles = Vehicle.query.all() + repostajes = Repostaje.query.all() + return render_template('index.html', vehicles=vehicles, repostajes=repostajes) + +@app.route('/add_vehicle', methods=['GET', 'POST']) +def add_vehicle(): + form = VehicleForm() + if form.validate_on_submit(): + vehicle = Vehicle(license_plate=form.license_plate.data, model=form.model.data) + db.session.add(vehicle) + db.session.commit() + return redirect(url_for('index')) + return render_template('add_vehicle.html', form=form) + +@app.route('/add_repostaje', methods=['GET', 'POST']) +def add_repostaje(): + form = RepostajeForm() + form.vehicle_id.choices = [(v.id, v.license_plate) for v in Vehicle.query.all()] + if form.validate_on_submit(): + repostaje = Repostaje( + vehicle_id=form.vehicle_id.data, + amount=form.amount.data, + date=form.date.data, + kilometers=form.kilometers.data, + liters=form.liters.data, + total_amount=form.total_amount.data + ) + db.session.add(repostaje) + db.session.commit() + return redirect(url_for('index')) + return render_template('add_repostaje.html', form=form) + +if __name__ == '__main__': + app.run(debug=True) diff --git a/PyRepostajes/forms.py b/PyRepostajes/forms.py new file mode 100644 index 0000000..6bbe37c --- /dev/null +++ b/PyRepostajes/forms.py @@ -0,0 +1,17 @@ +from flask_wtf import FlaskForm +from wtforms import StringField, FloatField, DateField, SelectField, SubmitField +from wtforms.validators import DataRequired + +class VehicleForm(FlaskForm): + license_plate = StringField('License Plate', validators=[DataRequired()]) + model = StringField('Model', validators=[DataRequired()]) + submit = SubmitField('Submit') + +class RepostajeForm(FlaskForm): + vehicle_id = SelectField('Vehicle', coerce=int, validators=[DataRequired()]) + amount = FloatField('Amount', validators=[DataRequired()]) + date = DateField('Date', format='%Y-%m-%d', validators=[DataRequired()]) + kilometers = FloatField('Kilometers', validators=[DataRequired()]) + liters = FloatField('Liters', validators=[DataRequired()]) + total_amount = FloatField('Total Amount', validators=[DataRequired()]) + submit = SubmitField('Submit') diff --git a/PyRepostajes/initdb.sh b/PyRepostajes/initdb.sh new file mode 100644 index 0000000..b935b2a --- /dev/null +++ b/PyRepostajes/initdb.sh @@ -0,0 +1,4 @@ +export FLASK_APP=app.py +flask db init +flask db migrate -m "Initial migration." +flask db upgrade diff --git a/PyRepostajes/migrations/README b/PyRepostajes/migrations/README new file mode 100644 index 0000000..0e04844 --- /dev/null +++ b/PyRepostajes/migrations/README @@ -0,0 +1 @@ +Single-database configuration for Flask. diff --git a/PyRepostajes/migrations/alembic.ini b/PyRepostajes/migrations/alembic.ini new file mode 100644 index 0000000..ec9d45c --- /dev/null +++ b/PyRepostajes/migrations/alembic.ini @@ -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 diff --git a/PyRepostajes/migrations/env.py b/PyRepostajes/migrations/env.py new file mode 100644 index 0000000..4c97092 --- /dev/null +++ b/PyRepostajes/migrations/env.py @@ -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() diff --git a/PyRepostajes/migrations/script.py.mako b/PyRepostajes/migrations/script.py.mako new file mode 100644 index 0000000..2c01563 --- /dev/null +++ b/PyRepostajes/migrations/script.py.mako @@ -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"} diff --git a/PyRepostajes/migrations/versions/55bdc15a1654_initial_migration.py b/PyRepostajes/migrations/versions/55bdc15a1654_initial_migration.py new file mode 100644 index 0000000..3a2840e --- /dev/null +++ b/PyRepostajes/migrations/versions/55bdc15a1654_initial_migration.py @@ -0,0 +1,46 @@ +"""Initial migration. + +Revision ID: 55bdc15a1654 +Revises: +Create Date: 2024-06-13 11:33:22.248968 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '55bdc15a1654' +down_revision = None +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('vehicle', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('license_plate', sa.String(length=10), nullable=False), + sa.Column('model', sa.String(length=50), nullable=False), + sa.PrimaryKeyConstraint('id'), + sa.UniqueConstraint('license_plate') + ) + op.create_table('repostaje', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('vehicle_id', sa.Integer(), nullable=False), + sa.Column('amount', sa.Float(), nullable=False), + sa.Column('date', sa.Date(), nullable=False), + sa.Column('kilometers', sa.Float(), nullable=False), + sa.Column('liters', sa.Float(), nullable=False), + sa.Column('total_amount', sa.Float(), nullable=False), + sa.ForeignKeyConstraint(['vehicle_id'], ['vehicle.id'], ), + sa.PrimaryKeyConstraint('id') + ) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_table('repostaje') + op.drop_table('vehicle') + # ### end Alembic commands ### diff --git a/PyRepostajes/models.py b/PyRepostajes/models.py new file mode 100644 index 0000000..fb8d8f0 --- /dev/null +++ b/PyRepostajes/models.py @@ -0,0 +1,24 @@ +from flask_sqlalchemy import SQLAlchemy + +db = SQLAlchemy() + +class Vehicle(db.Model): + id = db.Column(db.Integer, primary_key=True) + license_plate = db.Column(db.String(10), nullable=False, unique=True) + model = db.Column(db.String(50), nullable=False) + repostajes = db.relationship('Repostaje', backref='vehicle', lazy=True) + + def __repr__(self): + return f'' + +class Repostaje(db.Model): + id = db.Column(db.Integer, primary_key=True) + vehicle_id = db.Column(db.Integer, db.ForeignKey('vehicle.id'), nullable=False) + amount = db.Column(db.Float, nullable=False) + date = db.Column(db.Date, nullable=False) + kilometers = db.Column(db.Float, nullable=False) + liters = db.Column(db.Float, nullable=False) + total_amount = db.Column(db.Float, nullable=False) + + def __repr__(self): + return f'' diff --git a/PyRepostajes/templates/add_repostaje.html b/PyRepostajes/templates/add_repostaje.html new file mode 100644 index 0000000..c3c8fcb --- /dev/null +++ b/PyRepostajes/templates/add_repostaje.html @@ -0,0 +1,26 @@ +{% extends "layout.html" %} +{% block content %} +

Add Repostaje

+
+ {{ form.hidden_tag() }} +
+ {{ form.vehicle_id.label }} {{ form.vehicle_id(class_="form-control") }} +
+
+ {{ form.amount.label }} {{ form.amount(class_="form-control") }} +
+
+ {{ form.date.label }} {{ form.date(class_="form-control") }} +
+
+ {{ form.kilometers.label }} {{ form.kilometers(class_="form-control") }} +
+
+ {{ form.liters.label }} {{ form.liters(class_="form-control") }} +
+
+ {{ form.total_amount.label }} {{ form.total_amount(class_="form-control") }} +
+ {{ form.submit(class_="btn btn-primary") }} +
+{% endblock %} diff --git a/PyRepostajes/templates/add_vehicle.html b/PyRepostajes/templates/add_vehicle.html new file mode 100644 index 0000000..dc4fafd --- /dev/null +++ b/PyRepostajes/templates/add_vehicle.html @@ -0,0 +1,14 @@ +{% extends "layout.html" %} +{% block content %} +

Add Vehicle

+
+ {{ form.hidden_tag() }} +
+ {{ form.license_plate.label }} {{ form.license_plate(class_="form-control") }} +
+
+ {{ form.model.label }} {{ form.model(class_="form-control") }} +
+ {{ form.submit(class_="btn btn-primary") }} +
+{% endblock %} diff --git a/PyRepostajes/templates/index.html b/PyRepostajes/templates/index.html new file mode 100644 index 0000000..23d8e16 --- /dev/null +++ b/PyRepostajes/templates/index.html @@ -0,0 +1,46 @@ +{% extends "layout.html" %} +{% block content %} +

Vehicles and Repostajes

+Add Vehicle +Add Repostaje +

Vehicles

+ + + + + + + + + + {% for vehicle in vehicles %} + + + + + + {% endfor %} + +
IDLicense PlateModel
{{ vehicle.id }}{{ vehicle.license_plate }}{{ vehicle.model }}
+

Repostajes

+ + + + + + + + + + + {% for repostaje in repostajes %} + + + + + + + {% endfor %} + +
IDVehicleAmountDate
{{ repostaje.id }}{{ repostaje.vehicle.license_plate }}{{ repostaje.amount }}{{ repostaje.date }}
+{% endblock %} diff --git a/PyRepostajes/templates/layout.html b/PyRepostajes/templates/layout.html new file mode 100644 index 0000000..25452d5 --- /dev/null +++ b/PyRepostajes/templates/layout.html @@ -0,0 +1,12 @@ + + + + Vehicle Repostajes + + + +
+ {% block content %}{% endblock %} +
+ + diff --git a/RepostajesPy/requirements.txt b/RepostajesPy/requirements.txt new file mode 100644 index 0000000..0af5dae --- /dev/null +++ b/RepostajesPy/requirements.txt @@ -0,0 +1,17 @@ +alembic==1.13.1 +blinker==1.8.2 +click==8.1.7 +Flask==3.0.3 +Flask-Login==0.6.3 +Flask-Migrate==4.0.7 +Flask-SQLAlchemy==3.1.1 +Flask-WTF==1.2.1 +greenlet==3.0.3 +itsdangerous==2.2.0 +Jinja2==3.1.4 +Mako==1.3.5 +MarkupSafe==2.1.5 +SQLAlchemy==2.0.30 +typing_extensions==4.12.2 +Werkzeug==3.0.3 +WTForms==3.1.2 diff --git a/RepostajesPy/templates/index.html b/RepostajesPy/templates/index.html index eee64fe..3f5a51b 100644 --- a/RepostajesPy/templates/index.html +++ b/RepostajesPy/templates/index.html @@ -1,8 +1,9 @@ {% extends "base.html" %} {% block content %}

Lista de repostajes

-Añadir repostaje +Añadir repostaje + diff --git a/instance/vehicles.db b/instance/vehicles.db new file mode 100644 index 0000000000000000000000000000000000000000..eb07336e7888eb71c7fa81d53d50ede5943965f6 GIT binary patch literal 24576 zcmeI)O^?z*7zglac@q?>C$izN<6#pT)KHOiV`8++mK9;kQos$TrqCMe7K%`e9+&u~ z{2G1$k0u^WyqI`&N*b0DIC@y}pU`$X4>Rraqa3CUv|A0^v*=rQGBi9|B6kVLk(ZPb zLgK-~Hj5Hr>u6B-H{42nTQyD|UA#^Ue@X1l48f?0C;vZ|Z_0o3Sq2*bV>4q*2 zo1twCc&=wS`qo38Yqc|3>(RQ>qj}pD{nM^CHKlf{`fd5^6hx{iRYgi zym}T%WOF%gUSH4!!C(^&u`N4pMRV+dHJV!b*zpzK$XexIGk#wskS?s%q}pxHiACB9MDj%E90@$ zp7Zf+tFSG#^}(dI27fMp%m1>a*}@6G345VH00Izz00bZa0SG_<0uX=z1R$^@0vV1! zD3|-@Kq?#3Vfjgl<%RkGj(oUC0|F3$00bZa0SG_<0uX=z1RxLy2$6&2>ipk-{?7~F zi13T8P#^#S2tWV=5P$##AOHafKmY;|xFG_2e3azGr-!9tqo;M;&+IoMwBk-&$1(14 zEVL&TrK9@!$?@3*ZI}G#|Ge;%2!GfL1p*L&00bZa0SG_<0uX=z1Rwx`n=NoVlH-D# p0(>fxO9poV{OAAdPybLL009U<00Izz00bZa0SG_<0ub0?fqy~H8z}$) literal 0 HcmV?d00001
ID