Implemented basic models

This commit is contained in:
Jurn Wubben 2025-05-19 22:47:45 +02:00
parent 6bceef1664
commit 3ba6099976
16 changed files with 257 additions and 24 deletions

1
.envrc
View file

@ -1 +1,2 @@
use flake
export FLASK_APP=app

1
.gitignore vendored
View file

@ -1 +1,2 @@
.direnv
__pycache__

View file

@ -2,12 +2,9 @@ from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
# Configuration of application, see configuration.py, choose one and uncomment.
# app.config.from_object('configuration.ProductionConfig')
app.config.from_object("app.configuration.DevelopmentConfig")
# app.config.from_object('configuration.TestingConfig')
db = SQLAlchemy(app) # flask-sqlalchemy
from app import views, models
with app.app_context():
db.create_all()

View file

@ -2,8 +2,7 @@ class Config(object):
DEBUG = False
TESTING = False
SQLALCHEMY_DATABASE_URI = "sqlite:///application.db"
BOOTSTRAP_FONTAWESOME = True
SECRET_KEY = "MINHACHAVESECRETA"
SECRET_KEY = "yessir"
CSRF_ENABLED = True
SQLALCHEMY_TRACK_MODIFICATIONS = True
@ -15,6 +14,5 @@ class Config(object):
class DevelopmentConfig(Config):
DEBUG = True
class TestingConfig(Config):
TESTING = True

30
app/forms.py Normal file
View file

@ -0,0 +1,30 @@
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField, IntegerField, HiddenField
from wtforms.validators import DataRequired
class NewWishlist(FlaskForm):
title = StringField("Title:", validators=[DataRequired()])
description = StringField("Description:", validators=[DataRequired()])
submit = SubmitField("Submit")
# Each submit needs a different page fot it to work on the same page.
class DeleteWishlist(FlaskForm):
wl_del_submit = SubmitField("Delete wishlist")
class EditWishlistInfo(FlaskForm):
title = StringField("Title:", validators=[DataRequired()])
description = StringField("Description:", validators=[DataRequired()])
wl_edit_submit = SubmitField("Submit")
class ResetWishlistUrls(FlaskForm):
wl_reset_submit = SubmitField("Reset urls")
class NewItem(FlaskForm):
title = StringField("Title:", validators=[DataRequired()])
description = StringField("Description:", validators=[DataRequired()])
price = IntegerField("Price:", validators=[DataRequired()])
it_new_submit = SubmitField("Submit")
class DeleteItem(FlaskForm):
index = HiddenField()
it_del_submit = SubmitField("Delete item")

View file

@ -1,20 +1,35 @@
from typing import List
from app import db
from sqlalchemy.orm import Mapped, mapped_column, RelationshipProperty
from sqlalchemy import Uuid, String, Text
from uuid import uuid4 as uuid
class Item(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(250))
description = db.Column(db.Text)
price = db.Column(db.Float)
bought = db.Column(db.Boolean)
def __init__(self, title: str, description: str, price: float):
self.wishlist_id = None
self.title = title
self.description = description
self.price = price
self.bought = False
id: Mapped[int] = mapped_column(primary_key=True)
wishlist_id: Mapped[int | None] = mapped_column(db.ForeignKey("wishlist.id"))
title: Mapped[str] = mapped_column(db.String(250))
description: Mapped[str] = mapped_column(db.Text)
price: Mapped[float] = mapped_column()
bought: Mapped[bool] = mapped_column()
class Wishlist(db.Model):
id = db.Column(db.Integer, primary_key=True)
editId = db.Column(db.Uuid)
viewId = db.Column(db.Uuid)
title = db.Column(db.String(250))
description = db.Column(db.Text)
def __init__(self, title: str, description: str):
self.editId = uuid()
self.viewId = uuid()
self.title = title
self.description = description
itemIds = db.Column(db.ARRAY(db.Integer)) # Store item IDs as an array
items = db.relationship("Item", primaryjoin="Wishlist.itemIds")
id: Mapped[int] = mapped_column(primary_key=True)
editId: Mapped[Uuid] = mapped_column(Uuid)
viewId: Mapped[Uuid] = mapped_column(Uuid)
title: Mapped[str] = mapped_column(String(250))
description: Mapped[str] = mapped_column(Text)
items: Mapped[List["Item"]] = db.relationship("Item", backref="post")

69
app/templates/edit.html Normal file
View file

@ -0,0 +1,69 @@
{% set cpath = url_for("edit", id=wishlist.editId) %}
<h1>Change name</h1>
<form action="{{ cpath }}" method="POST">
{{ form_wl_editinfo.hidden_tag() }}
{{ form_wl_editinfo.title.label }}
{{ form_wl_editinfo.title() }}
{{ form_wl_editinfo.description.label }}
{{ form_wl_editinfo.description() }}
{{ form_wl_editinfo.wl_edit_submit() }}
</form>
<h1>Reset urls</h1>
<ul>
<li>
View: {{ wishlist.viewId }}
</li>
<li>
Edit: {{ wishlist.editId }}
</li>
</ul>
<form action="{{ cpath }}" method="POST">
{{ form_wl_reseturls.hidden_tag() }}
{{ form_wl_reseturls.wl_reset_submit() }}
</form>
<br>
<h1>Delete wishlist</h1>
<form action="{{ cpath }}" method="POST">
{{ form_wl_delete.hidden_tag() }}
{{ form_wl_delete.wl_del_submit() }}
</form>
<br>
<h1>New item</h1>
<form action="{{ cpath }}" method="POST">
{{ form_it_new.hidden_tag() }}
{{ form_it_new.title.label }}
{{ form_it_new.title() }}
{{ form_it_new.description.label }}
{{ form_it_new.description() }}
{{ form_it_new.price.label }}
{{ form_it_new.price() }}
{{ form_it_new.it_new_submit() }}
</form>
<br>
<h1>Delete items</h1>
<ul>
{% for value in wishlist.items %}
<li>
<form action="{{ cpath }}" method="POST">
{{ form_it_delete.hidden_tag() }}
{{ form_it_delete.index(value=loop.index) }}
{{ form_it_delete.it_del_submit() }}
</form>
{{ value.title }}
</li>
{% endfor %}
</ul>

11
app/templates/new.html Normal file
View file

@ -0,0 +1,11 @@
<form action="/new" method="POST">
{{ form.hidden_tag() }}
{{ form.title.label }}
{{ form.title() }}
{{ form.description.label }}
{{ form.description() }}
{{ form.submit() }}
</form>

10
app/templates/view.html Normal file
View file

@ -0,0 +1,10 @@
<h1>{{wishlist.title}}</h1>
<sub>{{wishlist.description}}</sub>
<a href="{{url_for('edit', id=wishlist.editId)}}">edit</a>
<ul>
{% for item in wishlist.items %}
<li><input type=checkbox {{ "checked" if item.bought }} {{ item.title }}: {{ item.description }}</li>
{% endfor %}
</ul>

View file

@ -1,7 +1,108 @@
from flask import url_for, redirect, render_template, flash, g, session
from app import app
from flask import url_for, redirect, render_template
from app import app, db
from app.forms import (
NewWishlist,
DeleteWishlist,
EditWishlistInfo,
ResetWishlistUrls,
NewItem,
DeleteItem,
)
from app.models import Wishlist, Item
from uuid import UUID, uuid4 as uuid
@app.route("/")
def index():
return "hello"
@app.route("/new", methods=["GET", "POST"])
def new():
form = NewWishlist()
if form.validate_on_submit():
wishlist = Wishlist(form.title.data, form.description.data)
db.session.add(wishlist)
db.session.commit()
return redirect(url_for("view", id=wishlist.viewId))
return render_template("new.html", form=form)
@app.route("/edit/<id>", methods=["GET", "POST"])
def edit(id: str):
wishlist: Wishlist = db.one_or_404(
db.select(Wishlist).filter_by(editId=UUID(id)),
description="Failed to get wishlist. Are you sure this is the correct url?",
)
form_wl_delete = DeleteWishlist()
form_wl_editinfo = EditWishlistInfo()
form_wl_reseturls = ResetWishlistUrls()
form_it_new = NewItem()
form_it_delete = DeleteItem()
# Each submit needs a different page fot it to work on the same page.
if form_wl_delete.validate_on_submit() and form_wl_delete.wl_del_submit.data:
for i in wishlist.items:
db.session.delete(i)
db.session.delete(wishlist)
db.session.commit()
return redirect(url_for("index"))
elif form_wl_editinfo.validate_on_submit() and form_wl_editinfo.wl_edit_submit.data:
wishlist.title = form_wl_editinfo.title.data
wishlist.description = form_wl_editinfo.description.data
db.session.commit()
return redirect(url_for("edit", id=id))
elif form_wl_reseturls.validate_on_submit() and form_wl_reseturls.wl_reset_submit.data:
wishlist.editId = uuid()
wishlist.viewId = uuid()
db.session.commit()
return redirect(url_for("edit", id=wishlist.editId))
elif form_it_new.validate_on_submit() and form_it_new.it_new_submit.data:
f = form_it_new
item = Item(
f.title.data,
f.description.data,
f.price.data
)
wishlist.items.append(item)
db.session.commit()
return redirect(url_for("edit", id=id))
elif form_it_delete.validate_on_submit() and form_it_delete.it_del_submit.data:
print(form_it_delete.index.data)
data = form_it_delete.index.data
i = int(data) if data != None else 0
if i + 1 > len(wishlist.items):
return "Invalid item to delete", 400
wishlist.items.remove(wishlist.items[i])
db.session.commit()
return redirect(url_for("edit", id=id))
return render_template(
"edit.html",
wishlist=wishlist,
form_wl_delete=form_wl_delete,
form_wl_editinfo=form_wl_editinfo,
form_wl_reseturls=form_wl_reseturls,
form_it_new=form_it_new,
form_it_delete=form_it_delete,
)
@app.route("/view/<id>")
def view(id: str):
wishlist = db.one_or_404(
db.select(Wishlist).filter_by(viewId=UUID(id)),
description="Failed to get wishlist. Are you sure this is the correct url?",
)
return render_template("view.html", wishlist=wishlist)

View file

@ -14,7 +14,7 @@
{
nativeBuildInputs = [
(pkgs.python3.withPackages
(x: [x.flask x.flask-wtf x.wtforms x.flask-sqlalchemy]))
(x: [x.flask x.flask-wtf x.wtforms x.flask-sqlalchemy x.uuid]))
pkgs.entr
];
};

BIN
instance/application.db Normal file

Binary file not shown.