From 7b0b325ba32e889457375ae5997ed6bb4737309a Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 31 May 2018 18:26:22 +0200 Subject: [PATCH] fancy search --- .DS_Store | Bin 8196 -> 8196 bytes app/forms.py | 9 ++- app/models.py | 3 +- app/static/css/style.css | 28 ++++++++ app/templates/_formhelpers.html | 12 ++++ app/templates/add_book.html | 3 +- app/templates/red_link.html | 45 +++++++++++- app/templates/results.html | 91 ++++++++++++++++++++++++ app/templates/show_books.html | 8 +++ app/views.py | 120 +++++++++++++++++++++++--------- 10 files changed, 279 insertions(+), 40 deletions(-) create mode 100644 app/templates/_formhelpers.html create mode 100644 app/templates/results.html diff --git a/.DS_Store b/.DS_Store index 643cb1c4a60d30af42ced63e3621bd426f103ae8..fe71f8301ef586bb50c8badc3a3cc56c09bd3ba0 100644 GIT binary patch delta 1196 zcmd6kOGs2v7{|{)HP7v$o*5mzK4;R@vcY^M8u>_*@=^BC)E>%=_g0t2arBO3Dm9WV zA}fkpmQ=V4%Qj&e)vgytEh>hfXcI*cM4P~(O`Vx5w5fJMXK@ba`}3Xe@cSLDJX(3$ z5jN-a+~^sLJTn|M9Z8cY=Ja$nyd+_0sG!7d%g-y-r&ua3=#QBd z0x`^Fj*SyV{fQ~pZ)T<#DN#zMEQ7Z8In|y%)jJRfR>d^QCa@X0TjpXy~Lsv?IH zDNR~N>8@bCx>w=5Q5LhM6#{e6CQThwj3?}3uD~>*>4559Xw4T3DU*d}m&2*J0_N7> z_+qhyvU;J#XMER~5ht#tLThJtSC``UYDTR>T1VL&Z4XXvaA@8}kK+FIry5Gzg2_5r zR%E@$lHz9|l%$e8Qbp=WJMoYKGD^nC1i49O$Sk=>o{*R14f#MmlP_eRd?nuiEJ8RU z5RC*#NJ27}BOe7QL_Iy^;X)U>;eii+4C4q!Fp9G{hcQebaS~TC zh3mMB2Y84_c!uYAjd%E@kHpq-l~%4YzBcO*DwqFO<*R7JpCvxQmYI`VSW;G{kHj_m zMQbyMtQ>6aS7q=1Hiy=!xMkJ7uf?Zos?(*gNE7S=4M>Se$xG9%Ru&{_T(h#RA_G?~ zgwmDSJYBSqt;*wB7`JLH+`)Z3olcK`kLgHhKHUHBxcmu= TATUBRh_UoROYDEk=q-K%aegFW delta 1149 zcmd6kTS!zv9LDGCqH}O`XVqQTLuMch$3QmkkvX ziY`zbvJ27Wp~x-|VRnI@iZZH~Y9S(ei697~m!P7TW_P1rgr0)tVc`FL!_4se4S9w< zNBxt>1Kl@zhSQG?W{##)nPS{5=7W+w7ON<8R?e?Bukk{hFrV=0IB9<5r4q}O8&)>t zG&1v?)n-;$d)&Ow&^Bs8e?*UJUVlV0IHaptc}mgD((>xsB`e|Qe+0gfB+)t%sGP{hi=1x7Nazjcb6_rf(1^odn$W@8PEvv=z^J|#AIjZ#}P*O;$h?g{x zcG62?uA`2EckdFc=aH9(IPz?_n zu@>vG0UObZb_CD?6_8;0@m6 zlR1>LO2|^`8|v*Vf6JORk*wEQDML1Uo^z&qPSt|N%guecz5zCUb5u95$FH_ diff --git a/app/forms.py b/app/forms.py index 62cb3fe..211872c 100755 --- a/app/forms.py +++ b/app/forms.py @@ -11,13 +11,18 @@ class AuthorForm(NoCsrfForm): # this forms is never exposed so we can user the non CSRF version author_name = StringField('Author Name', validators=[DataRequired()]) -class UserForm(FlaskForm): +class UploadForm(FlaskForm): title = StringField('title', validators=[InputRequired()]) author = FieldList(FormField(AuthorForm, default=lambda: Author()), min_entries=1) category = StringField('category', validators=[InputRequired()]) file = FileField() + upload = SubmitField(label='Upload') + wish = SubmitField(label='''I don't have the file, but wish I did.''') -class UserForm_Edit(FlaskForm): +class EditForm(FlaskForm): title = StringField('title', validators=[InputRequired()]) author = FieldList(FormField(AuthorForm, default=lambda: Author()), min_entries=1) category = StringField('category', validators=[InputRequired()]) + +class SearchForm(FlaskForm): + search = StringField('', validators=[InputRequired()]) diff --git a/app/models.py b/app/models.py index 5c63322..ea199b3 100755 --- a/app/models.py +++ b/app/models.py @@ -27,13 +27,12 @@ class Book(db.Model): scapeX = db.Column(db.Numeric(10,2)) scapeY = db.Column(db.Numeric(10,2)) - def __init__(self, title, file, cover, fileformat, category, stack): + def __init__(self, title, file, cover, fileformat, category): self.title = title self.file = file self.cover = cover self.fileformat = fileformat self.category = category - self.stack = stack self.scapeX = 0 self.scapeY = 0 diff --git a/app/static/css/style.css b/app/static/css/style.css index f2d1914..f442e51 100755 --- a/app/static/css/style.css +++ b/app/static/css/style.css @@ -71,6 +71,34 @@ width: 500px; font-size: 16px; } +.search input{ +margin: 0; +float: left; +width: 400px; +height: 36px; +font-size: 20px; +font-weight: regular; +padding: 2px; +background:rgba(50, 50, 50, 0.2); +border:0px; +} + +.button { +height:40px; +font-size: 18px; +padding:6px 15px; +left:0px; +border:0px solid #dbdbdb; +background-color: grey; +color:#fafafa; +} + +.button:hover { +background-color:red; +color: #fafafa; +} + + .footer{ width: 100%; diff --git a/app/templates/_formhelpers.html b/app/templates/_formhelpers.html new file mode 100644 index 0000000..d4ad8c2 --- /dev/null +++ b/app/templates/_formhelpers.html @@ -0,0 +1,12 @@ +{% macro render_field(field) %} +
{{ field.label }} +
{{ field(**kwargs)|safe }} + {% if field.errors %} +
    + {% for error in field.errors %} +
  • {{ error }}
  • + {% endfor %} +
+ {% endif %} +
+{% endmacro %} \ No newline at end of file diff --git a/app/templates/add_book.html b/app/templates/add_book.html index 1fbb362..2121566 100755 --- a/app/templates/add_book.html +++ b/app/templates/add_book.html @@ -37,7 +37,8 @@
{{ form.category.label }} {{ form.category(size=20, class="form-control") }}
{{ form.file }} - + {{ form.upload }} + {{ form.wish }} diff --git a/app/templates/red_link.html b/app/templates/red_link.html index 95b940d..133e954 100755 --- a/app/templates/red_link.html +++ b/app/templates/red_link.html @@ -24,7 +24,48 @@ {% block header %}{% endblock %} {% block main %} -

ID: {{ id }}

-

red link page

+

We don't have any results for: {{ title }}

+

upload?

go back home?

+ + +
+

Add Book

+ {% with messages = get_flashed_messages() %} + {% if messages %} +
+
    + {% for message in messages %} +
  • {{ message }}
  • + {% endfor %} +
+
+ {% endif %} + {% endwith %} +
+ {{ form.csrf_token }} +
{{ form.title.label }} {{ form.title(size=20, class="form-control") }}
+
+
+ {{ form.author.label }} + + + + + + {% for author in form.author %} + + + + + {% endfor %} +
{{ author.author_name }}
+
+
+
{{ form.tag.label }} {{ form.tag(size=20, class="form-control") }}
+ {{ form.file }} + +
+
{% endblock %} diff --git a/app/templates/results.html b/app/templates/results.html new file mode 100644 index 0000000..9262d35 --- /dev/null +++ b/app/templates/results.html @@ -0,0 +1,91 @@ +{% extends 'base.html' %} + +{% block main %} + +
+ {% from "_formhelpers.html" import render_field %} +
+ + +
+ +
+ +
+

Search Results for: {{ query }}

+ {% with messages = get_flashed_messages() %} + {% if messages %} +
+
    + {% for message in messages %} +
  • {{ message }}
  • + {% endfor %} +
+
+ {% endif %} + {% endwith %} + + + + + + + + + + {% for book in books %} + + + + + + + + + {% endfor %} +
CoverTitleAuthorFiletypeTag
{{ book.title }} {% for author in book.authors %} + +
  • {{ author.author_name }}
  • + + {% endfor %}
    {{ book.fileformat }}{{ book.tag}}
    + +
    + +
    +
    +

    Other books

    + + + + + + + + + + {% for book in books_all %} + + + + + + + + + {% endfor %} +
    CoverTitleAuthorFiletypeTag
    {{ book.title }} {% for author in book.authors %} + +
  • {{ author.author_name }}
  • + + + {% endfor %}
    {{ book.fileformat }}{{ book.tag}}
    +

    + See all books +

    + +
    + +{% endblock %} + + diff --git a/app/templates/show_books.html b/app/templates/show_books.html index 420b911..7cfe4b1 100755 --- a/app/templates/show_books.html +++ b/app/templates/show_books.html @@ -2,6 +2,14 @@ {% block main %}
    + + {% from "_formhelpers.html" import render_field %} +
    + + +
    +

    All Books

    {% with messages = get_flashed_messages() %} {% if messages %} diff --git a/app/views.py b/app/views.py index 98bf49d..7909b86 100755 --- a/app/views.py +++ b/app/views.py @@ -8,7 +8,8 @@ This file creates your application. from app import app, db from flask import Flask, render_template, request, redirect, url_for, flash, send_from_directory, jsonify, abort import json -from app.forms import UserForm, UserForm_Edit +from sqlalchemy.sql.expression import func, select +from app.forms import UploadForm, EditForm, SearchForm from app.models import Book, BookSchema, Author, AuthorSchema, Stack, StackSchema from app.cover import get_cover @@ -54,10 +55,13 @@ def uploaded_file_cover(filename): return send_from_directory(app.config['UPLOAD_FOLDER_COVER'], filename) -@app.route('/books') +@app.route('/books', methods= ['POST','GET']) def show_books(): - books = db.session.query(Book).all() # or you could have used User.query.all() - return render_template('show_books.html', books=books) + books = db.session.query(Book).all() + search = SearchForm(request.form) + if request.method == 'POST': + return redirect((url_for('search_results', query=search.search.data))) + return render_template('show_books.html', books=books, form=search) @app.route('/scape', methods=['POST', 'GET']) def scape(): @@ -100,7 +104,7 @@ def remove_book_by_id(id): @app.route('/books//edit', methods=['POST', 'GET']) def edit_book_by_id(id): book_to_edit = Book.query.filter_by(id=id).first() - user_form = UserForm_Edit(title = book_to_edit.title, author =book_to_edit.authors, category = book_to_edit.category ) + user_form = EditForm(title = book_to_edit.title, author =book_to_edit.authors, category = book_to_edit.category ) if request.method == 'POST': if user_form.validate_on_submit(): @@ -148,30 +152,61 @@ def edit_book_by_id(id): @app.route('/add-book', methods=['POST', 'GET']) def add_book(): - user_form = UserForm() + upload_form = UploadForm() if request.method == 'POST': - if user_form.validate_on_submit(): - # check if the post request has the file part - if 'file' not in request.files: - flash('No file part') - return redirect(request.url) - file = request.files['file'] - # if user does not select file, browser also - # submit a empty part without filename - if file.filename == '': - flash('No selected file') - return redirect(request.url) - if file and allowed_file(file.filename): - filename = secure_filename(file.filename) - fullpath = os.path.join(app.config['UPLOAD_FOLDER'], filename) - name, file_extension = os.path.splitext(filename) - file.save(fullpath) - cover = get_cover(fullpath, name) - title = user_form.title.data # You could also have used request.form['name'] - authors = user_form.author.data # You could also have used - category = user_form.category.data + if upload_form.validate_on_submit(): + if upload_form.upload.data: + # check if the post request has the file part + if 'file' not in request.files: + flash('No file part') + return redirect(request.url) + file = request.files['file'] + # if user does not select file, browser also + # submit a empty part without filename + if file.filename == '': + flash('No selected file') + return redirect(request.url) + if file and allowed_file(file.filename): + filename = secure_filename(file.filename) + fullpath = os.path.join(app.config['UPLOAD_FOLDER'], filename) + name, file_extension = os.path.splitext(filename) + file.save(fullpath) + cover = get_cover(fullpath, name) + title = upload_form.title.data # You could also have used request.form['name'] + authors = upload_form.author.data # You could also have used + category = upload_form.category.data + #print(author) + #print(len(author)) + book = Book(title, filename, cover, file_extension, category) + db.session.add(book) + for author in authors: + author_name = author.get("author_name") + if author_name: + a = db.session.query(Author).filter_by(author_name=author_name).first() + if a == None: + a = Author(author_name=author_name) + db.session.add(a) + book.authors.append(a) + db.session.commit() + # save user to database + + + flash("%s added to the library" % (title)) + return redirect(url_for('show_books')) + else: + flash('allowed file formats: %s' % ALLOWED_EXTENSIONS) + + if upload_form.wish.data: + file = open('app/uploads/potential.pdf') + filename = 'potential.pdf' + file_extension = '.pdf' + cover = get_cover('app/uploads/potential.pdf', 'default') + + title = upload_form.title.data # You could also have used request.form['name'] + authors = upload_form.author.data # You could also have used + category = upload_form.category.data #print(author) #print(len(author)) book = Book(title, filename, cover, file_extension, category) @@ -185,16 +220,14 @@ def add_book(): db.session.add(a) book.authors.append(a) db.session.commit() - # save user to database + flash("%s added to the library" % (title)) + return redirect(url_for('show_books')) - flash("%s added to the library" % (title)) - return redirect(url_for('show_books')) - else: - flash('allowed file formats: %s' % ALLOWED_EXTENSIONS) - flash_errors(user_form) - return render_template('add_book.html', form=user_form) + flash_errors(upload_form) + return render_template('add_book.html', form=upload_form) + # Flash errors from the form if validation fails def flash_errors(form): @@ -235,6 +268,27 @@ def show_stack_by_id(id): else: return render_template('show_stack_detail.html', stack=stack) +## search + +@app.route('/search//', methods=['POST', 'GET']) +def search_results(query): + search = SearchForm(request.form) + books_all=Book.query.all() + random_order=Book.query.order_by(func.random()).limit(10) + results=Book.query.filter(Book.title.contains(query)).all() + + if not results: + upload_form = UploadForm(title= query, author='') + return render_template('red_link.html', form=upload_form, title=query) + + if request.method == 'POST': + query = search.search.data + results = [] + results=Book.query.filter(Book.title.contains(query)).all() + return redirect((url_for('search_results', query=search.search.data))) + + return render_template('results.html', form=search, books=results, books_all=random_order, query=query) + ### # The API