@ -9,12 +9,14 @@ from app import app, db, socketio, DOMAIN
from flask import Flask , Response , session , render_template , request , redirect , url_for , flash , send_from_directory , jsonify , abort
import json
from sqlalchemy . sql . expression import func , select
from sqlalchemy . sql import except_
from app . forms import UploadForm , EditForm , SearchForm , ChatForm , StackForm , AddtoStackForm , EditStackForm
from app . models import Book , BookSchema , Author , AuthorSchema , Stack , StackSchema , UserIns , Chat , ChatSchema , Instance
from app . models import Book , BookSchema , Author , AuthorSchema , Stack , StackSchema , UserIns , Chat , ChatSchema , Instance , Potential
from app . cover import get_cover
from app . extractText import extract_text
from os import environ
from flask_socketio import SocketIO , emit
from weasyprint import HTML
import datetime
import time
from csv import DictWriter , DictReader
@ -49,6 +51,7 @@ def allowed_file(filename):
def home ( ) :
chat_form = ChatForm ( )
chat_messages = db . session . query ( Chat ) . all ( )
username = ' librarian '
# if request.method == 'POST':
# if chat_form.validate_on_submit():
@ -63,7 +66,7 @@ def home():
else :
client = request . environ [ ' HTTP_X_FORWARDED_FOR ' ]
return render_template ( ' home.html ' , domain = DOMAIN , chat = chat_messages , channel = 1 , username = " librarian " , client = client , server = server )
return render_template ( ' home.html ' , domain = DOMAIN , chat = chat_messages , channel = 1 , username = username , client = client , server = server )
@app.route ( ' /hello/<name> ' )
def hello ( name ) :
@ -133,6 +136,15 @@ def show_books_grid():
def show_book_by_id ( id ) :
book = Book . query . get ( id )
all_instances = db . session . query ( Instance ) . all ( )
previousbook = Book . query . filter_by ( id = id - 1 ) . first ( )
nextbook = Book . query . filter_by ( id = id + 1 ) . first ( )
allbooks = db . session . query ( Book ) . all ( )
edge = len ( allbooks )
if id == 1 :
previousbook = None
if id == edge :
nextbook = None
userin = UserIns . query . filter_by ( title = " lastViewed " ) . first ( )
if userin != None :
userin . info = book . title
@ -144,7 +156,7 @@ def show_book_by_id(id):
if not book :
return render_template ( ' red_link.html ' , id = id )
else :
return render_template ( ' show_book_detail.html ' , book = book , all_instances= all_instances )
return render_template ( ' show_book_detail.html ' , book = book , previousbook = previousbook , nextbook = nextbook , all_instances= all_instances )
@app.route ( ' /books/<int:id>/delete ' , methods = [ ' POST ' , ' GET ' ] )
@ -160,24 +172,23 @@ def remove_book_by_id(id):
@app.route ( ' /books/<int:id>/edit ' , methods = [ ' POST ' , ' GET ' ] )
def edit_book_by_id ( id ) :
book_to_edit = Book . query . filter_by ( id = id ) . first ( )
user_form = EditForm ( title = book_to_edit . title , author = book_to_edit . authors , category = book_to_edit . category , year_published = book_to_edit . year_published )
user_form = EditForm ( title = book_to_edit . title , author = book_to_edit . authors , category = book_to_edit . category , year_published = book_to_edit . year_published , message = book_to_edit . message )
if request . method == ' POST ' :
if user_form . validate_on_submit ( ) :
# check if the post request has the file part
title = user_form . title . data # You could also have used request.form['name']
input_authors = user_form . author . data # You could also have used request.form['email']
# on submit, check fields
title = user_form . title . data
input_authors = user_form . author . data
category = user_form . category . data
year_published = user_form . year_published . data
message = user_form . message . data
if year_published == " " :
year_published = None
# save user to database
#book = Book(title, author, filename, cover, file_extension)
book = Book . query . filter_by ( id = id ) . first ( )
book . title = title
book . category = category
book . year_published = year_published
book . message = message
#authors update
book . authors . clear ( )
@ -194,6 +205,26 @@ def edit_book_by_id(id):
if existing_ip :
i . name = existing_ip . name
book . instances . append ( i )
# editing / uploading new file
if user_form . file . data :
file = request . files [ ' file ' ]
if file . filename == ' ' :
flash ( ' No selected file ' )
return redirect ( request . url )
if file and allowed_file ( file . filename ) :
allbooks = db . session . query ( Book ) . all ( )
id = book . id
filename = str ( id ) + " _ " + secure_filename ( file . filename )
fullpath = os . path . join ( app . config [ ' UPLOAD_FOLDER ' ] , filename )
name , file_extension = os . path . splitext ( filename )
file . save ( fullpath )
book . cover = get_cover ( fullpath , name )
book . file = filename
else :
flash ( ' allowed file formats: %s ' % ALLOWED_EXTENSIONS )
db . session . commit ( )
flash ( " %s updated " % ( title ) )
return redirect ( url_for ( ' show_book_by_id ' , id = id ) )
@ -204,6 +235,17 @@ def edit_book_by_id(id):
@app.route ( ' /add-book ' , methods = [ ' POST ' , ' GET ' ] )
def add_book ( ) :
upload_form = UploadForm ( )
allbooks = db . session . query ( Book ) . all ( )
books_all = len ( allbooks )
allauthors = db . session . query ( Author ) . all ( )
authors_all = len ( allauthors )
stacks_all = [ s . stack_name for s in db . session . query ( Stack . stack_name ) ]
categories = [ r . category for r in db . session . query ( Book . category ) . distinct ( ) ]
allpotential = db . session . query ( Book ) . filter ( Book . file . contains ( ' potential.pdf ' ) ) . all ( )
books_potential = len ( allpotential )
earliest = db . session . query ( func . min ( Book . year_published ) ) . scalar ( )
latest = db . session . query ( func . max ( Book . year_published ) ) . scalar ( )
if request . method == ' POST ' :
if upload_form . validate_on_submit ( ) :
@ -211,7 +253,14 @@ def add_book():
title = upload_form . title . data
authors = upload_form . author . data
category = upload_form . category . data
message = upload_form . message . data
year_published = upload_form . year_published . data
sameness = upload_form . sameness . data
gender = upload_form . gender . data
diversity = upload_form . diversity . data
time = upload_form . time . data
who = upload_form . who . data
if year_published == " " :
year_published = None
@ -228,12 +277,12 @@ def add_book():
flash ( ' No selected file ' )
return redirect ( request . url )
if file and allowed_file ( file . filename ) :
filename = secure_filename ( file . filename )
allbooks = db . session . query ( Book ) . all ( )
id = len ( allbooks ) + 1
new_filename = str ( id ) + " _ " + filename
fullpath = os . path . join ( app . config [ ' UPLOAD_FOLDER ' ] , new_filename )
name , file_extension = os . path . splitext ( new_filename )
filename = str ( id ) + " _ " + secure_filename ( file . filename )
fullpath = os . path . join ( app . config [ ' UPLOAD_FOLDER ' ] , filename )
name , file_extension = os . path . splitext ( filename )
file . save ( fullpath )
try :
cover = get_cover ( fullpath , name )
@ -246,15 +295,22 @@ def add_book():
flash ( ' allowed file formats: %s ' % ALLOWED_EXTENSIONS )
#if upload without file -> wishform, with potential PDF
if upload_form . wish . data :
#TO DO: make pdf generator
#file = open('app/uploads/potential.pdf')
#filename = 'potential.pdf'
#file_extension = '.pdf'
filename = ' '
file_extension = ' '
#pdf generator
filename = ' potential.pdf '
file_extension = ' .pdf '
cover = ' '
book = Book ( title , filename , cover , file_extension , category , year_published )
ptitle = upload_form . title . data
pbook = Potential ( ptitle )
db . session . add ( pbook )
db . session . commit ( )
pbooks = Potential . query . all ( )
template = ' app/templates/potential_pdf.html '
html_string = render_template ( ' potential_pdf.html ' , pbooks = pbooks )
html = HTML ( string = html_string )
html . write_pdf ( target = ' app/uploads/potential.pdf ' ) ;
print ( ' potential_pdf ' )
book = Book ( title , filename , cover , file_extension , category , year_published , message , sameness , diversity , gender , who , time )
db . session . add ( book )
for author in authors :
author_name = author . get ( " author_name " )
@ -275,7 +331,7 @@ def add_book():
return redirect ( url_for ( ' show_books ' ) )
flash_errors ( upload_form )
return render_template ( ' add_book.html ' , form = upload_form )
return render_template ( ' add_book.html ' , form = upload_form , books_all = books_all , authors_all = authors_all , categories = categories , stacks_all = stacks_all , books_potential = books_potential , earliest = earliest , latest = latest )
# Flash errors from the form if validation fails
@ -317,9 +373,10 @@ def add_stack():
if form . validate_on_submit ( ) :
stack_name = form . stack_name . data
stack_description = form . stack_description . data
stack = Stack ( stack_name , stack_description )
stack_author = form . stack_author . data
stack = Stack ( stack_name , stack_description , stack_author )
if form . stack_name . data :
stack = Stack ( stack_name , stack_description )
stack = Stack ( stack_name , stack_description , stack_author )
db . session . add ( stack )
stacks = db . session . query ( Stack ) . all ( )
return redirect ( url_for ( ' show_stacks ' ) )
@ -395,52 +452,136 @@ def show_instances():
db . session . commit ( )
return render_template ( ' show_instances.html ' , instances = instances )
@app.route ( ' /stacks/<int:stackid>/remove/<int:bookid> ' , methods = [ ' POST ' , ' GET ' ] )
def remove_from_stack ( bookid , stackid ) :
book = Book . query . get ( bookid )
stack = Stack . query . get ( stackid )
if book not in stack . books :
return render_template ( ' show_book_detail.html ' , book = book )
stack . books . remove ( book )
db . session . commit ( )
return render_template ( ' show_book_detail.html ' , book = book )
## search
view = [ ' 1 ' ]
@app.route ( ' /books ' , methods = [ ' POST ' , ' GET ' ] )
def show_books ( ) :
#autocomplete.load() #Train markov model once, for autocomplete in search
books = db . session . query ( Book ) . all ( )
books = db . session . query ( Book ) . order_by ( Book . title )
search = SearchForm ( request . form )
view . append ( ' 1 ' )
viewby = ' 1 '
if search . grid . data :
viewby = ' 2 '
view . append ( ' 2 ' )
return render_template ( ' show_books_grid.html ' , books = books , form = search )
if search . listview . data :
viewby = ' 1 '
view . append ( ' 1 ' )
return render_template ( ' show_books.html ' , books = books , form = search )
if request . method == ' POST ' :
return redirect ( ( url_for ( ' search_results ' , searchtype = search . select . data , query = search . search . data ) ) )
newmsg = ' searched for: ' + search . search . data
socketio . emit ( ' channel- ' + str ( 1 ) , {
' username ' : ' Search form ' ,
' text ' : search . search . data ,
' time ' : str ( datetime . datetime . utcnow ( ) . strftime ( " %d . % m. % Y % H: % M " ) ) } , broadcast = True )
# Save message
my_new_chat = Chat ( message = newmsg )
db . session . add ( my_new_chat )
try :
db . session . commit ( )
except :
db . session . rollback ( )
return redirect ( ( url_for ( ' search_results ' , searchtype = search . select . data , query = search . search . data , viewby = viewby ) ) )
return render_template ( ' show_books.html ' , books = books , form = search )
@app.route ( ' /search/<searchtype>/<query>/ ' , methods = [ ' POST ' , ' GET ' ] )
def search_results ( searchtype , query ) :
search = SearchForm ( request . form )
random_order = Book . query . order_by ( func . random ( ) ) . limit ( 10 )
results = Book . query . filter ( Book . title . contains ( query ) ) . all ( )
@app.route ( ' /search/<searchtype>/<viewby>/<query> ' , methods = [ ' POST ' , ' GET ' ] )
def search_results ( searchtype , query , viewby ) :
search = SearchForm ( request . form , search = query )
results = Book . query . filter ( Book . title . contains ( query ) ) . order_by ( Book . title )
allbooks = set ( Book . query . all ( ) )
viewby = view [ - 1 ]
if searchtype == ' Title ' :
results = Book . query . filter ( Book . title . contains ( query ) ) . all ( )
results = Book . query . filter ( Book . title . contains ( query ) ) . order_by( Book . title )
if searchtype == ' Category ' :
results = Book . query . filter ( Book . category . contains ( query ) ) . all( )
results = Book . query . filter ( Book . category . contains ( query ) ) . order_by( Book . title )
if searchtype == ' A ll ' :
results = Book. query . whoosh_search ( query ) . all ( )
if searchtype == ' A uthor ' :
results = db. session . query ( Book ) . join ( Book . authors ) . filter ( Author . author_name . contains ( query ) ) . order_by ( Book . title )
if not results :
if searchtype == ' Stack ' :
results = db . session . query ( Book ) . join ( Book . stacks ) . filter ( Stack . stack_name . contains ( query ) ) . order_by ( Book . title )
if searchtype == ' All ' :
# results=Book.query.whoosh_search(query)
results = Book . query . filter ( Book . title . contains ( query ) )
results = results . union ( Book . query . filter ( Book . category . contains ( query ) ) )
results = results . union ( Book . query . filter ( Book . year_published . contains ( query ) ) )
results = results . union ( db . session . query ( Book ) . join ( Book . authors ) . filter ( Author . author_name . contains ( query ) ) )
results = results . union ( db . session . query ( Book ) . join ( Book . stacks ) . filter ( Stack . stack_name . contains ( query ) ) )
results = results . union ( db . session . query ( Book ) . join ( Book . stacks ) . filter ( Stack . stack_description . contains ( query ) ) ) . order_by ( Book . title )
if results . count ( ) == 0 :
books = Book . query . filter ( Book . file . like ( ' potential.pdf ' ) )
upload_form = UploadForm ( title = query , author = ' ' )
return render_template ( ' red_link.html ' , form = upload_form , title = query )
return render_template ( ' red_link.html ' , form = upload_form , title = query , books = books )
count = results . count ( )
whole = Book . query . count ( )
percentage = float ( count / whole * 100 )
fbooks = set ( results )
books_all = allbooks - fbooks
if search . listview . data :
view . append ( ' 1 ' )
return render_template ( ' results.html ' , books = results , form = search , query = query , books_all = books_all , searchtype = search . select . data , count = count , whole = whole , percentage = percentage )
if search . grid . data :
view . append ( ' 2 ' )
return render_template ( ' results_grid.html ' , books = results , form = search , query = query , books_all = books_all , searchtype = search . select . data , count = count , whole = whole , percentage = percentage )
if request . method == ' POST ' :
newmsg = ' searched for: ' + search . search . data
socketio . emit ( ' channel- ' + str ( 1 ) , {
' username ' : ' Search form ' ,
' text ' : search . search . data ,
' time ' : str ( datetime . datetime . utcnow ( ) . strftime ( " %d . % m. % Y % H: % M " ) ) } , broadcast = True )
# Save message
my_new_chat = Chat ( message = newmsg )
db . session . add ( my_new_chat )
try :
db . session . commit ( )
except :
db . session . rollback ( )
query = search . search . data
results = [ ]
return redirect ( ( url_for ( ' search_results ' , searchtype = search . select . data , query = search . search . data ) ) )
if viewby == ' 1 ' :
print ( view [ - 1 ] )
return redirect ( ( url_for ( ' search_results ' , searchtype = search . select . data , query = search . search . data , viewby = viewby ) ) )
else :
return redirect ( ( url_for ( ' search_results ' , searchtype = search . select . data , query = search . search . data , viewby = viewby ) ) )
if viewby == ' 2 ' :
return render_template ( ' results_grid.html ' , form = search , books = results , books_all = books_all , searchtype = search . select . data , query = query , count = count , whole = whole , percentage = percentage )
else :
return render_template ( ' results.html ' , form = search , books = results , books_all = books_all , searchtype = search . select . data , query = query , count = count , whole = whole , percentage = percentage )
return render_template ( ' results.html ' , form = search , books = results , books_all = random_order , searchtype = search . select . data , query = query )
## Search - autocomplete
# # # Search - autocomplete
# autocomplete_suggestions = []
#autocomplete.load() #Train markov model once, for autocomplete in search
# @app.route('/autocomplete_suggestions', methods=['GET', 'POST'])
# def test1():
# if request.method == 'POST':
# autocomplete.load()
# query = request.form['search']
# query_tokenized = query.lower().split()
# print(query_tokenized)
@ -555,7 +696,7 @@ def import_csv():
return render_template ( ' import_csv.html ' , numberadded = numberadded )
@app.route ( ' /empty_catalogue ' , methods = [ ' POST ' , ' GET ' ] )
@app.route ( ' /empty_catalogue 487352698237465 ' , methods = [ ' POST ' , ' GET ' ] )
def empty_catalogue ( ) :
meta = db . metadata
for table in reversed ( meta . sorted_tables ) :
@ -565,6 +706,7 @@ def empty_catalogue():
db . create_all ( )
db . session . commit ( )
return " ALL CLEARED "
###
# The API
###
@ -648,7 +790,6 @@ def new_message(message):
db . session . rollback ( )
if __name__ == ' __main__ ' :
socketio . run ( app )
#app.run(debug=True,host="0.0.0.0",port="8080")