broke
This commit is contained in:
94
plugins/utility/search.py
Normal file
94
plugins/utility/search.py
Normal file
@ -0,0 +1,94 @@
|
||||
from flask import Blueprint, render_template, request, redirect, url_for, jsonify
|
||||
from flask_login import login_required, current_user
|
||||
from app import db
|
||||
from sqlalchemy import or_
|
||||
from plugins.plant.models import Plant, PlantCommonName, PlantScientificName, Tag
|
||||
from flask_wtf import FlaskForm
|
||||
from wtforms import StringField, SelectMultipleField, SubmitField
|
||||
from wtforms.validators import Optional, Length, Regexp
|
||||
|
||||
bp = Blueprint(
|
||||
'search',
|
||||
__name__,
|
||||
url_prefix='/search',
|
||||
template_folder='templates/search'
|
||||
)
|
||||
|
||||
class SearchForm(FlaskForm):
|
||||
query = StringField(
|
||||
'Search',
|
||||
validators=[
|
||||
Optional(),
|
||||
Length(min=2, max=100, message="Search term must be between 2 and 100 characters."),
|
||||
Regexp(r'^[\w\s\-]+$', message="Search can only include letters, numbers, spaces, and dashes.")
|
||||
]
|
||||
)
|
||||
tags = SelectMultipleField('Tags', coerce=int)
|
||||
submit = SubmitField('Search')
|
||||
|
||||
@bp.route('', methods=['GET', 'POST'])
|
||||
@bp.route('/', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
def search():
|
||||
form = SearchForm()
|
||||
form.tags.choices = [(t.id, t.name) for t in Tag.query.order_by(Tag.name).all()]
|
||||
if form.validate_on_submit():
|
||||
q = form.query.data or ''
|
||||
selected = form.tags.data or []
|
||||
tags_param = ','.join(map(str, selected)) if selected else ''
|
||||
return redirect(url_for('search.results', q=q, tags=tags_param))
|
||||
return render_template('search/search.html', form=form)
|
||||
|
||||
@bp.route('/results', methods=['GET'])
|
||||
@login_required
|
||||
def results():
|
||||
q = request.args.get('q', '').strip()
|
||||
tags_param = request.args.get('tags', '')
|
||||
tags = [int(t) for t in tags_param.split(',') if t] if tags_param else []
|
||||
like_term = f"%{q}%"
|
||||
|
||||
# Base query, joining name tables for text search
|
||||
query = (
|
||||
db.session.query(Plant)
|
||||
.join(Plant.common_name)
|
||||
.join(Plant.scientific_name)
|
||||
)
|
||||
|
||||
if q:
|
||||
query = query.filter(
|
||||
or_(
|
||||
PlantCommonName.name.ilike(like_term),
|
||||
PlantScientificName.name.ilike(like_term),
|
||||
Plant.plant_type.ilike(like_term),
|
||||
)
|
||||
)
|
||||
|
||||
if tags:
|
||||
query = query.filter(Plant.tags.any(Tag.id.in_(tags)))
|
||||
|
||||
# Only include active plants…
|
||||
query = query.filter(Plant.is_active.is_(True))
|
||||
|
||||
# …and either public plants or those owned by the current user
|
||||
query = query.filter(
|
||||
or_(
|
||||
Plant.is_public.is_(True),
|
||||
Plant.owner_id == current_user.id
|
||||
)
|
||||
)
|
||||
|
||||
results = query.all()
|
||||
return render_template(
|
||||
'search/results.html',
|
||||
results=results,
|
||||
query=q,
|
||||
tags=tags
|
||||
)
|
||||
|
||||
@bp.route('/tags')
|
||||
@login_required
|
||||
def search_tags():
|
||||
term = request.args.get('term', '')
|
||||
like_term = f"%{term}%"
|
||||
matches = Tag.query.filter(Tag.name.ilike(like_term)).limit(10).all()
|
||||
return jsonify([t.name for t in matches])
|
Reference in New Issue
Block a user