viewer now works for files_ip, still have broken bits everywhere - files_rbp, change_opts, do I want a back button? lots of dead/old code, probably cam move more js into *_support, and do I want to keep files_support separate to view_support
This commit is contained in:
123
files.py
123
files.py
@@ -1,8 +1,10 @@
|
||||
from flask_wtf import FlaskForm
|
||||
from flask import request, render_template, redirect, send_from_directory, url_for, jsonify, make_response
|
||||
from marshmallow import Schema, fields
|
||||
from main import db, app, ma
|
||||
from sqlalchemy import Sequence, text, select
|
||||
from sqlalchemy.exc import SQLAlchemyError
|
||||
from sqlalchemy.orm import joinedload
|
||||
import os
|
||||
import glob
|
||||
import json
|
||||
@@ -172,16 +174,43 @@ class FileTypeSchema(ma.SQLAlchemyAutoSchema):
|
||||
class Meta: model = FileType
|
||||
load_instance = True
|
||||
|
||||
class FileSchema(ma.SQLAlchemyAutoSchema):
|
||||
class Meta: model = File
|
||||
load_instance = True
|
||||
|
||||
class DirSchema(ma.SQLAlchemyAutoSchema):
|
||||
class Meta: model = Dir
|
||||
load_instance = True
|
||||
eid = ma.auto_field() # Explicitly include eid
|
||||
in_path = ma.Nested(PathSchema)
|
||||
|
||||
class FaceFileLinkSchema(ma.SQLAlchemyAutoSchema):
|
||||
class Meta: model = FaceFileLink
|
||||
load_instance = True
|
||||
|
||||
class PersonSchema(ma.SQLAlchemyAutoSchema):
|
||||
class Meta: model=Person
|
||||
load_instance = True
|
||||
|
||||
class RefimgSchema(ma.SQLAlchemyAutoSchema):
|
||||
class Meta:
|
||||
model = Refimg
|
||||
exclude = ('face',)
|
||||
load_instance = True
|
||||
person = ma.Nested(PersonSchema)
|
||||
|
||||
class FaceRefimgLinkSchema(ma.SQLAlchemyAutoSchema):
|
||||
class Meta: model = FaceRefimgLink
|
||||
load_instance = True
|
||||
|
||||
class FaceSchema(ma.SQLAlchemyAutoSchema):
|
||||
class Meta:
|
||||
model=Face
|
||||
exclude = ('face',)
|
||||
load_instance = True
|
||||
refimg = ma.Nested(RefimgSchema,allow_none=True)
|
||||
|
||||
class FileSchema(ma.SQLAlchemyAutoSchema):
|
||||
class Meta: model = File
|
||||
load_instance = True
|
||||
faces = ma.Nested(FaceSchema,many=True,allow_none=True)
|
||||
|
||||
################################################################################
|
||||
# Schema for Entry so we can json for data to the client
|
||||
################################################################################
|
||||
@@ -191,11 +220,19 @@ class EntrySchema(ma.SQLAlchemyAutoSchema):
|
||||
load_instance = True
|
||||
|
||||
type = ma.Nested(FileTypeSchema)
|
||||
file_details = ma.Nested(FileSchema)
|
||||
file_details = ma.Nested(FileSchema,allow_none=True)
|
||||
# noting dir_details needs in_path to work
|
||||
dir_details = ma.Nested(DirSchema)
|
||||
# noting in_dir needs in_path and in_path.type to work
|
||||
in_dir = ma.Nested(DirSchema)
|
||||
# allow us to use FullPathOnFS()
|
||||
FullPathOnFS = fields.Method("get_full_path")
|
||||
|
||||
def get_full_path(self, obj):
|
||||
return obj.FullPathOnFS()
|
||||
|
||||
# global - this will be use more than once below, so do it once for efficiency
|
||||
entries_schema = EntrySchema(many=True)
|
||||
|
||||
################################################################################
|
||||
# util function to just update the current/first/last positions needed for
|
||||
@@ -396,14 +433,26 @@ def process_ids():
|
||||
# DDP: debate here, do I get query_id, do I validate whether we are asking
|
||||
# for ids not in the query? OR, dont even make/store/have query?
|
||||
|
||||
# marshmallow will allow us to json the data the way we need for the client
|
||||
entries_schema = EntrySchema(many=True)
|
||||
|
||||
# Query DB for matching entries
|
||||
entries = Entry.query.filter(Entry.id.in_(ids)).all()
|
||||
stmt = (
|
||||
select(Entry)
|
||||
.options(
|
||||
joinedload(Entry.file_details).joinedload(File.faces),
|
||||
joinedload(Entry.file_details).joinedload(File.faces).joinedload(Face.refimg).joinedload(Refimg.person)
|
||||
)
|
||||
.where(Entry.id.in_(ids))
|
||||
)
|
||||
|
||||
# return entries as json
|
||||
return jsonify(entries_schema.dump(entries))
|
||||
# unique as the ORM query returns a Cartesian product for the joins. E.g if file has 3 faces, the result has 3 rows of the same entry and file data, but different face data
|
||||
data=db.session.execute(stmt).unique().scalars().all()
|
||||
|
||||
# data is now in whatever order the DB returns- faster in python than DB supposedly. So, create a mapping from id to entry for quick lookup
|
||||
entry_map = {entry.id: entry for entry in data}
|
||||
|
||||
# Sort the entries according to the order of ids
|
||||
sorted_data = [entry_map[id_] for id_ in ids if id_ in entry_map]
|
||||
|
||||
return jsonify(entries_schema.dump(sorted_data))
|
||||
|
||||
|
||||
################################################################################
|
||||
@@ -806,6 +855,40 @@ def view_list():
|
||||
|
||||
return make_response( resp )
|
||||
|
||||
|
||||
@login_required
|
||||
@app.route("/newview/", methods=["POST"])
|
||||
def newview():
|
||||
data = request.get_json() # Parse JSON body
|
||||
eid = data.get('eid', 0) # Extract list of ids
|
||||
|
||||
# need appropriate schema? to get FaceData with entry, lists should just be
|
||||
# what we have in entryList so it can help with next/prev
|
||||
|
||||
# include Entry for name/path, ffl (model_used), frl (distance), Face (for w/h, etc), Person (id,tag)
|
||||
#stmt=select(Entry).filter(Entry.id==eid)
|
||||
|
||||
stmt = (
|
||||
select(Entry)
|
||||
.options(
|
||||
joinedload(Entry.file_details).joinedload(File.faces),
|
||||
joinedload(Entry.file_details).joinedload(File.faces).joinedload(Face.refimg).joinedload(Refimg.person)
|
||||
)
|
||||
.where(Entry.id == eid)
|
||||
)
|
||||
|
||||
print( stmt )
|
||||
# this needs unique because:
|
||||
# entry (one row for id=660)
|
||||
# file (one row, since file_details is a one-to-one relationship)
|
||||
# face (many rows, since a file can have many faces)
|
||||
# refimg and person (one row per face, via the link tables)
|
||||
# The SQL query returns a Cartesian product for the joins involving collections (like faces). For example, if your file has 3 faces,
|
||||
# the result set will have 3 rows, each with the same entry and file data, but different face, refimg, and person data.
|
||||
data=db.session.execute(stmt).unique().scalars().all()
|
||||
print( data )
|
||||
return jsonify(entries_schema.dump(data))
|
||||
|
||||
################################################################################
|
||||
# /view/id -> grabs data from DB and views it (GET)
|
||||
################################################################################
|
||||
@@ -836,14 +919,16 @@ def view(id):
|
||||
eids=eids.rstrip(",")
|
||||
# jic, sometimes we trip this, and rather than show broken pages / destroy
|
||||
if id not in eids:
|
||||
SetFELog( message=f"ERROR: viewing an id, but its not in eids OPT={OPT}, id={id}, eids={eids}", level="danger", persistent=True, cant_close=False)
|
||||
msg="Sorry, viewing data is confused, cannot view this image now"
|
||||
if os.environ['ENV'] == "production":
|
||||
msg += "Clearing out all states. This means browser back buttons will not work, please start a new tab and try again"
|
||||
PA_UserState.query.delete()
|
||||
db.session.commit()
|
||||
SetFELog( msg, "warning", persistent=True, cant_close=False )
|
||||
return redirect("/")
|
||||
# SetFELog( message=f"ERROR: viewing an id, but its not in eids OPT={OPT}, id={id}, eids={eids}", level="danger", persistent=True, cant_close=False)
|
||||
# msg="Sorry, viewing data is confused, cannot view this image now"
|
||||
# if os.environ['ENV'] == "production":
|
||||
# msg += "Clearing out all states. This means browser back buttons will not work, please start a new tab and try again"
|
||||
# PA_UserState.query.delete()
|
||||
# db.session.commit()
|
||||
# SetFELog( msg, "warning", persistent=True, cant_close=False )
|
||||
# return redirect("/")
|
||||
print( f"id={id}, eids={eids}" )
|
||||
return "200"
|
||||
else:
|
||||
NMO_data = FaceOverrideType.query.all()
|
||||
setting = Settings.query.first()
|
||||
|
||||
Reference in New Issue
Block a user