fancy search
This commit is contained in:
parent
676b111e59
commit
7b0b325ba3
@ -11,13 +11,18 @@ class AuthorForm(NoCsrfForm):
|
|||||||
# this forms is never exposed so we can user the non CSRF version
|
# this forms is never exposed so we can user the non CSRF version
|
||||||
author_name = StringField('Author Name', validators=[DataRequired()])
|
author_name = StringField('Author Name', validators=[DataRequired()])
|
||||||
|
|
||||||
class UserForm(FlaskForm):
|
class UploadForm(FlaskForm):
|
||||||
title = StringField('title', validators=[InputRequired()])
|
title = StringField('title', validators=[InputRequired()])
|
||||||
author = FieldList(FormField(AuthorForm, default=lambda: Author()), min_entries=1)
|
author = FieldList(FormField(AuthorForm, default=lambda: Author()), min_entries=1)
|
||||||
category = StringField('category', validators=[InputRequired()])
|
category = StringField('category', validators=[InputRequired()])
|
||||||
file = FileField()
|
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()])
|
title = StringField('title', validators=[InputRequired()])
|
||||||
author = FieldList(FormField(AuthorForm, default=lambda: Author()), min_entries=1)
|
author = FieldList(FormField(AuthorForm, default=lambda: Author()), min_entries=1)
|
||||||
category = StringField('category', validators=[InputRequired()])
|
category = StringField('category', validators=[InputRequired()])
|
||||||
|
|
||||||
|
class SearchForm(FlaskForm):
|
||||||
|
search = StringField('', validators=[InputRequired()])
|
||||||
|
@ -27,13 +27,12 @@ class Book(db.Model):
|
|||||||
scapeX = db.Column(db.Numeric(10,2))
|
scapeX = db.Column(db.Numeric(10,2))
|
||||||
scapeY = 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.title = title
|
||||||
self.file = file
|
self.file = file
|
||||||
self.cover = cover
|
self.cover = cover
|
||||||
self.fileformat = fileformat
|
self.fileformat = fileformat
|
||||||
self.category = category
|
self.category = category
|
||||||
self.stack = stack
|
|
||||||
self.scapeX = 0
|
self.scapeX = 0
|
||||||
self.scapeY = 0
|
self.scapeY = 0
|
||||||
|
|
||||||
|
@ -71,6 +71,34 @@ width: 500px;
|
|||||||
font-size: 16px;
|
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{
|
.footer{
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
12
app/templates/_formhelpers.html
Normal file
12
app/templates/_formhelpers.html
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{% macro render_field(field) %}
|
||||||
|
<dt>{{ field.label }}
|
||||||
|
<dd>{{ field(**kwargs)|safe }}
|
||||||
|
{% if field.errors %}
|
||||||
|
<ul class=errors>
|
||||||
|
{% for error in field.errors %}
|
||||||
|
<li>{{ error }}</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
{% endif %}
|
||||||
|
</dd>
|
||||||
|
{% endmacro %}
|
@ -37,7 +37,8 @@
|
|||||||
<br>
|
<br>
|
||||||
<div class="form-group">{{ form.category.label }} {{ form.category(size=20, class="form-control") }}</div>
|
<div class="form-group">{{ form.category.label }} {{ form.category(size=20, class="form-control") }}</div>
|
||||||
{{ form.file }}
|
{{ form.file }}
|
||||||
<button type="submit" class="btn btn-primary">Upload</button>
|
{{ form.upload }}
|
||||||
|
{{ form.wish }}
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -24,7 +24,48 @@
|
|||||||
{% block header %}{% endblock %}
|
{% block header %}{% endblock %}
|
||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
<h1>ID: {{ id }}</h1>
|
<h1>We don't have any results for: {{ title }}</h1>
|
||||||
<p>red link page</p>
|
<p><a href="{{ url_for('add_book') }}">upload</a>?</p>
|
||||||
<p><a href="{{ url_for('home') }}">go back home</a>?</p>
|
<p><a href="{{ url_for('home') }}">go back home</a>?</p>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<h1 class="page-header">Add Book</h1>
|
||||||
|
{% with messages = get_flashed_messages() %}
|
||||||
|
{% if messages %}
|
||||||
|
<div class="alert alert-danger">
|
||||||
|
<ul>
|
||||||
|
{% for message in messages %}
|
||||||
|
<li>{{ message }}</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% endwith %}
|
||||||
|
<form method="POST" action="{{ url_for('add_book') }}" enctype=multipart/form-data>
|
||||||
|
{{ form.csrf_token }}
|
||||||
|
<div class="form-group">{{ form.title.label }} {{ form.title(size=20, class="form-control") }}</div>
|
||||||
|
<br>
|
||||||
|
<div data-toggle="fieldset" id="phone-fieldset">
|
||||||
|
{{ form.author.label }} <button type="button" data-toggle="fieldset-add-row"
|
||||||
|
data-target="#phone-fieldset">+</button>
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th></th>
|
||||||
|
<th></th>
|
||||||
|
</tr>
|
||||||
|
{% for author in form.author %}
|
||||||
|
<tr data-toggle="fieldset-entry">
|
||||||
|
<td>{{ author.author_name }}</td>
|
||||||
|
<td><button type="button" data-toggle="fieldset-remove-row" id="phone-{{loop.index0}}-remove">-</button></td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<div class="form-group">{{ form.tag.label }} {{ form.tag(size=20, class="form-control") }}</div>
|
||||||
|
{{ form.file }}
|
||||||
|
<button type="submit" class="btn btn-primary">Upload</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
91
app/templates/results.html
Normal file
91
app/templates/results.html
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
|
||||||
|
{% block main %}
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
{% from "_formhelpers.html" import render_field %}
|
||||||
|
<form method="POST">
|
||||||
|
<div class="search">
|
||||||
|
{{ render_field(form.search) }} </div>
|
||||||
|
<button type="submit" class="button">Search</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<h1 class="page-header">Search Results for: {{ query }}</h1>
|
||||||
|
{% with messages = get_flashed_messages() %}
|
||||||
|
{% if messages %}
|
||||||
|
<div class="alert alert-success">
|
||||||
|
<ul>
|
||||||
|
{% for message in messages %}
|
||||||
|
<li>{{ message }}</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% endwith %}
|
||||||
|
|
||||||
|
<table style="width:100%">
|
||||||
|
<tr>
|
||||||
|
<th>Cover</th>
|
||||||
|
<th>Title</th>
|
||||||
|
<th>Author</th>
|
||||||
|
<th>Filetype</th>
|
||||||
|
<th>Tag</th>
|
||||||
|
</tr>
|
||||||
|
{% for book in books %}
|
||||||
|
<tr>
|
||||||
|
<td><img src="/uploads/cover/{{ book.cover }}" width="80"></td>
|
||||||
|
<td><a href="{{url_for('show_book_by_id', id=book.id)}}">{{ book.title }}</a></td>
|
||||||
|
|
||||||
|
<td> {% for author in book.authors %}
|
||||||
|
|
||||||
|
<li><a href="{{url_for('show_author_by_id', id=author.id)}}">{{ author.author_name }}</a> </li>
|
||||||
|
|
||||||
|
{% endfor %}</td>
|
||||||
|
<td>{{ book.fileformat }}</td>
|
||||||
|
<td>{{ book.tag}}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container" >
|
||||||
|
<hr>
|
||||||
|
<h2> Other books </h2>
|
||||||
|
|
||||||
|
<table style="width:100%; ">
|
||||||
|
<tr>
|
||||||
|
<th>Cover</th>
|
||||||
|
<th>Title</th>
|
||||||
|
<th>Author</th>
|
||||||
|
<th>Filetype</th>
|
||||||
|
<th>Tag</th>
|
||||||
|
</tr>
|
||||||
|
{% for book in books_all %}
|
||||||
|
<tr>
|
||||||
|
<td><img src="/uploads/cover/{{ book.cover }}" width="80"></td>
|
||||||
|
<td><a href="{{url_for('show_book_by_id', id=book.id)}}">{{ book.title }}</a></td>
|
||||||
|
|
||||||
|
<td> {% for author in book.authors %}
|
||||||
|
|
||||||
|
<li><a href="{{url_for('show_author_by_id', id=author.id)}}">{{ author.author_name }}</a> </li>
|
||||||
|
|
||||||
|
|
||||||
|
{% endfor %}</td>
|
||||||
|
<td>{{ book.fileformat }}</td>
|
||||||
|
<td>{{ book.tag}}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
<p>
|
||||||
|
<a href="/books"> See all books </a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
|
@ -2,6 +2,14 @@
|
|||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
<div class="container">
|
<div class="container">
|
||||||
|
|
||||||
|
{% from "_formhelpers.html" import render_field %}
|
||||||
|
<form method="POST">
|
||||||
|
<div class="search">
|
||||||
|
{{ render_field(form.search) }} </div>
|
||||||
|
<button type="submit" class="button">Search</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
<h1 class="page-header">All Books</h1>
|
<h1 class="page-header">All Books</h1>
|
||||||
{% with messages = get_flashed_messages() %}
|
{% with messages = get_flashed_messages() %}
|
||||||
{% if messages %}
|
{% if messages %}
|
||||||
|
120
app/views.py
120
app/views.py
@ -8,7 +8,8 @@ This file creates your application.
|
|||||||
from app import app, db
|
from app import app, db
|
||||||
from flask import Flask, render_template, request, redirect, url_for, flash, send_from_directory, jsonify, abort
|
from flask import Flask, render_template, request, redirect, url_for, flash, send_from_directory, jsonify, abort
|
||||||
import json
|
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.models import Book, BookSchema, Author, AuthorSchema, Stack, StackSchema
|
||||||
from app.cover import get_cover
|
from app.cover import get_cover
|
||||||
|
|
||||||
@ -54,10 +55,13 @@ def uploaded_file_cover(filename):
|
|||||||
return send_from_directory(app.config['UPLOAD_FOLDER_COVER'],
|
return send_from_directory(app.config['UPLOAD_FOLDER_COVER'],
|
||||||
filename)
|
filename)
|
||||||
|
|
||||||
@app.route('/books')
|
@app.route('/books', methods= ['POST','GET'])
|
||||||
def show_books():
|
def show_books():
|
||||||
books = db.session.query(Book).all() # or you could have used User.query.all()
|
books = db.session.query(Book).all()
|
||||||
return render_template('show_books.html', books=books)
|
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'])
|
@app.route('/scape', methods=['POST', 'GET'])
|
||||||
def scape():
|
def scape():
|
||||||
@ -100,7 +104,7 @@ def remove_book_by_id(id):
|
|||||||
@app.route('/books/<int:id>/edit', methods=['POST', 'GET'])
|
@app.route('/books/<int:id>/edit', methods=['POST', 'GET'])
|
||||||
def edit_book_by_id(id):
|
def edit_book_by_id(id):
|
||||||
book_to_edit = Book.query.filter_by(id=id).first()
|
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 request.method == 'POST':
|
||||||
if user_form.validate_on_submit():
|
if user_form.validate_on_submit():
|
||||||
@ -148,30 +152,61 @@ def edit_book_by_id(id):
|
|||||||
|
|
||||||
@app.route('/add-book', methods=['POST', 'GET'])
|
@app.route('/add-book', methods=['POST', 'GET'])
|
||||||
def add_book():
|
def add_book():
|
||||||
user_form = UserForm()
|
upload_form = UploadForm()
|
||||||
|
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
|
|
||||||
if user_form.validate_on_submit():
|
if upload_form.validate_on_submit():
|
||||||
# check if the post request has the file part
|
if upload_form.upload.data:
|
||||||
if 'file' not in request.files:
|
# check if the post request has the file part
|
||||||
flash('No file part')
|
if 'file' not in request.files:
|
||||||
return redirect(request.url)
|
flash('No file part')
|
||||||
file = request.files['file']
|
return redirect(request.url)
|
||||||
# if user does not select file, browser also
|
file = request.files['file']
|
||||||
# submit a empty part without filename
|
# if user does not select file, browser also
|
||||||
if file.filename == '':
|
# submit a empty part without filename
|
||||||
flash('No selected file')
|
if file.filename == '':
|
||||||
return redirect(request.url)
|
flash('No selected file')
|
||||||
if file and allowed_file(file.filename):
|
return redirect(request.url)
|
||||||
filename = secure_filename(file.filename)
|
if file and allowed_file(file.filename):
|
||||||
fullpath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
|
filename = secure_filename(file.filename)
|
||||||
name, file_extension = os.path.splitext(filename)
|
fullpath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
|
||||||
file.save(fullpath)
|
name, file_extension = os.path.splitext(filename)
|
||||||
cover = get_cover(fullpath, name)
|
file.save(fullpath)
|
||||||
title = user_form.title.data # You could also have used request.form['name']
|
cover = get_cover(fullpath, name)
|
||||||
authors = user_form.author.data # You could also have used
|
title = upload_form.title.data # You could also have used request.form['name']
|
||||||
category = user_form.category.data
|
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(author)
|
||||||
#print(len(author))
|
#print(len(author))
|
||||||
book = Book(title, filename, cover, file_extension, category)
|
book = Book(title, filename, cover, file_extension, category)
|
||||||
@ -185,16 +220,14 @@ def add_book():
|
|||||||
db.session.add(a)
|
db.session.add(a)
|
||||||
book.authors.append(a)
|
book.authors.append(a)
|
||||||
db.session.commit()
|
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))
|
flash_errors(upload_form)
|
||||||
return redirect(url_for('show_books'))
|
return render_template('add_book.html', form=upload_form)
|
||||||
else:
|
|
||||||
flash('allowed file formats: %s' % ALLOWED_EXTENSIONS)
|
|
||||||
|
|
||||||
flash_errors(user_form)
|
|
||||||
return render_template('add_book.html', form=user_form)
|
|
||||||
|
|
||||||
# Flash errors from the form if validation fails
|
# Flash errors from the form if validation fails
|
||||||
def flash_errors(form):
|
def flash_errors(form):
|
||||||
@ -235,6 +268,27 @@ def show_stack_by_id(id):
|
|||||||
else:
|
else:
|
||||||
return render_template('show_stack_detail.html', stack=stack)
|
return render_template('show_stack_detail.html', stack=stack)
|
||||||
|
|
||||||
|
## search
|
||||||
|
|
||||||
|
@app.route('/search/<query>/', 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
|
# The API
|
||||||
|
Loading…
Reference in New Issue
Block a user