roundabout,
created on Wednesday, 14 August 2024, 11:42:02 (1723635722),
received on Thursday, 15 August 2024, 07:42:21 (1723707741)
Author identity: vlad <vlad.muntoiu@gmail.com>
5a5988e04bd78522f4a7aec6b9f9a7cfff476be1
.gitignore
@@ -1,2 +1,3 @@
.venv/ secrets.env data/
app.py
@@ -1,3 +1,6 @@
from datetime import datetime from email.policy import defaultimport flask from flask_sqlalchemy import SQLAlchemy from flask_bcrypt import Bcrypt
@@ -5,6 +8,9 @@ from flask_httpauth import HTTPBasicAuth
from markupsafe import escape, Markup from flask_migrate import Migrate from jinja2_fragments.flask import render_block from sqlalchemy.orm import backref import sqlalchemy.dialects.postgresqlimport config import markdown
@@ -26,17 +32,154 @@ def split(value, separator=None, maxsplit=-1):
return value.split(separator, maxsplit) with app.app_context(): class User(db.Model): username = db.Column(db.String(32), unique=True, nullable=False, primary_key=True) password_hashed = db.Column(db.String(60), nullable=False) def __init__(self, username, real_name, password):def __init__(self, username, password):self.username = username self.real_name = real_nameself.password_hashed = bcrypt.generate_password_hash(password).decode("utf-8") class Licence(db.Model): id = db.Column(db.String(32), primary_key=True) # SPDX identifier title = db.Column(db.UnicodeText, nullable=False) # the official name of the licence description = db.Column(db.UnicodeText, nullable=False) # brief description of its permissions and restrictions legal_text = db.Column(db.UnicodeText, nullable=False) # the full legal text of the licence url = db.Column(db.String(2048), nullable=True) # the URL to a page with the full text of the licence and more information pictures = db.relationship("PictureLicence", back_populates="licence") def __init__(self, id, title, description, legal_text, url): self.id = id self.title = title self.description = description self.legal_text = legal_text self.url = url class PictureLicence(db.Model): resource_id = db.Column(db.Integer, db.ForeignKey("picture_resource.id"), primary_key=True) licence_id = db.Column(db.String(32), db.ForeignKey("licence.id"), primary_key=True) resource = db.relationship("PictureResource", back_populates="licences") licence = db.relationship("Licence", back_populates="pictures") def __init__(self, resource_id, licence_id): self.resource_id = resource_id self.licence_id = licence_id class Resource(db.Model): __abstract__ = True id = db.Column(db.Integer, primary_key=True, autoincrement=True) title = db.Column(db.UnicodeText, nullable=False) description = db.Column(db.UnicodeText, nullable=False) timestamp = db.Column(db.DateTime, nullable=False, default=datetime.utcnow) origin_url = db.Column(db.String(2048), nullable=True) # should be left empty if it's original or the source is unknown but public domain class PictureNature(db.Model): # Examples: # "photo", "paper-scan", "2d-art-photo", "sculpture-photo", "computer-3d", "computer-painting", # "computer-line-art", "diagram", "infographic", "text", "map", "chart-graph", "screen-capture", # "screen-photo", "pattern", "collage", "ai", and so on id = db.Column(db.String(64), primary_key=True) description = db.Column(db.UnicodeText, nullable=False) resources = db.relationship("PictureResource", backref="nature") def __init__(self, id, description): self.id = id self.description = description class PictureObjectInheritance(db.Model): parent_id = db.Column(db.String(64), db.ForeignKey("picture_object.id"), primary_key=True) child_id = db.Column(db.String(64), db.ForeignKey("picture_object.id"), primary_key=True) parent = db.relationship("PictureObject", foreign_keys=[parent_id], backref="child_links") child = db.relationship("PictureObject", foreign_keys=[child_id], backref="parent_links") def __init__(self, parent, child): self.parent = parent self.child = child class PictureObject(db.Model): id = db.Column(db.String(64), primary_key=True) description = db.Column(db.UnicodeText, nullable=False) child_links = db.relationship("PictureObjectInheritance", foreign_keys=[PictureObjectInheritance.parent_id], backref="parent") parent_links = db.relationship("PictureObjectInheritance", foreign_keys=[PictureObjectInheritance.child_id], backref="child") def __init__(self, id, description): self.id = id self.description = description class PictureRegion(db.Model): # This is for picture region annotations id = db.Column(db.Integer, primary_key=True, autoincrement=True) json = db.Column(sqlalchemy.dialects.postgresql.JSONB, nullable=False) resource_id = db.Column(db.Integer, db.ForeignKey("picture_resource.id"), nullable=False) object_id = db.Column(db.String(64), db.ForeignKey("picture_object.id"), nullable=False) resource = db.relationship("PictureResource", backref="regions") object = db.relationship("PictureObject", backref="regions") def __init__(self, json, resource, object): self.json = json self.resource = resource self.object = object class PictureResource(Resource): # This is only for bitmap pictures. Vectors will be stored under a different model # File name is the ID in the picture directory under data, without an extension file_format = db.Column(db.String(64), nullable=False) # MIME type width = db.Column(db.Integer, nullable=False) height = db.Column(db.Integer, nullable=False) nature_id = db.Column(db.String(32), db.ForeignKey("picture_nature.id"), nullable=False) nature = db.relationship("PictureNature", back_populates="resources") replaces_id = db.Column(db.Integer, db.ForeignKey("picture_resource.id"), nullable=True) replaced_by_id = db.Column(db.Integer, db.ForeignKey("picture_resource.id"), nullable=True) # if this is set, this resource is obsolete and hidden from search results, only available if asked for replaces = db.relationship("PictureResource", foreign_keys=[replaces_id], backref="replaced_by") replaced_by = db.relationship("PictureResource", foreign_keys=[replaced_by_id], backref="replaces") licences = db.relationship("ResourceLicence", # a work can be under multiple licences; at least one must be free, but others can be proprietary back_populates="resource") def __init__(self, title, description, origin_url, licence_ids, mime, size, nature, replaces=None): self.title = title self.description = description self.origin_url = origin_url self.file_format = mime self.width, self.height = size self.nature = nature db.session.add(self) db.session.commit() for licence_id in licence_ids: joiner = PictureLicence(self.id, licence_id) db.session.add(joiner) if replaces is not None: self.replaces = replaces replaces.replaced_by = self @app.route("/") def index(): return flask.render_template("home.html")
config.py
@@ -5,3 +5,4 @@ dotenv.load_dotenv("secrets.env")
DB_PASSWORD = environ["DB_PASSWORD"] DB_URI = f"postgresql://gigadata:{DB_PASSWORD}@localhost:5432/gigadata" DATA_PATH = "./data"