Table des matières

Flask, Bootstrap, SolR, pròba de concèpte

Flask e Bootstrap e Solr

La tòca es d'integrar una requesta cap a SolR, dins un site Web enregat per Flask, un sitonel escrich en Python. Puèi lo vestit del site es adornat amb Bootstrap, la libraria javascript e las fuèlhas d'estíl polidas e estandard.
Las formas son geridas per la libraria WTForms, los comptes d'usagièrs son creats dins una basa de donadas SqlLite3. Es possible de se marcar mas i a pas de securitat contra los webots marrits e sannaires (pas encara de reCAPTCHA). Un administrator dins la reira botiga pòt eventualament enregistrar los mantenaires amb un accès dirèct a la basa.

La forma de cèrca

Es tras que simple, lo gabarit «templates/solr.html» es apelat amb una rota e un objècte solrForm li es passat. Aprèp lo gabarit foncciona amb lo formalisme de Flask ex:

{% %} per ecriure una estructura de blòc 
{{ variabla }} per invocar una variabla Python passada 

         {% for result in form.search(): %}
          <li class="list-group-item">{{ result['title'] }}</li>
          {% endfor %}

App.py code Python

#!/usr/home/admin/envs/monflaskr/bin/python
# -*- coding: utf-8 -*-
"""
    Server
    ~~~~~~

"""

import os
import sys
import pysolr
from flask import Flask, render_template, request, redirect, url_for,  session,g
from flask_bootstrap import Bootstrap
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user
from flask_wtf import FlaskForm
from wtforms import StringField, BooleanField, PasswordField
from wtforms.validators import InputRequired, Email, Length, AnyOf
from urlparse import urlparse, urljoin
from werkzeug.security import generate_password_hash, check_password_hash

###############################################################################
# C O N F I G
#
reload(sys)
sys.setdefaultencoding('utf8')

app = Flask(__name__)
app.config['SECRET_KEY'] = 'Agadou dou dou PousselananaEtMoulKfé'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////usr/home/admin/flask/dca/login.db'
app.config['SOLR_URI'] = 'http://vertigo.acc.fr:8983/solr/gettingstarted/'

Bootstrap(app)

###############################################################################
# instanciation & initialization
#

db = SQLAlchemy(app)
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = 'login'

###############################################################################
# O B J E C T S
#
class Solr:
    db = pysolr.Solr('http://vertigo.acc.fr:8983/solr/gettingstarted/', timeout=10)
    def search(self, textToSearch):
        return self.db.search(textToSearch)
    def getResults(self, text):
        results = self.solrSearch(text)
        return "{0}".format(len(results))

class User(UserMixin, db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(15),unique = True)
    email = db.Column(db.String(15), unique= True)
    password = db.Column(db.String(80))

@login_manager.user_loader
def load_user(user_id):
    return User.query.get(int(user_id))
###############################################################################
# F O R M S
#
#
class LoginForm(FlaskForm):
    username = StringField('nom ou surnom', validators=[InputRequired(), Length(min=4, max=15)] )
    password = PasswordField('mot de passe', validators=[InputRequired(), Length(min=4, max=80)] )
    remember = BooleanField('se rappeler de moi')

class RegisterForm(FlaskForm):
    email = StringField('email', validators=[InputRequired(), Email(message='adresse de courriel incorrecte'), Length(max=50)])
    username = StringField('nom ou surnom', validators=[InputRequired(), Length(min=4, max=15)] )
    password = PasswordField('mot de passe', validators=[InputRequired(), Length(min=8, max=80)] )

class SolrForm(FlaskForm):
    textToFind = StringField('mot ou phrase', validators=[InputRequired(), Length(min=4, max=512)] )
    solr = Solr()
    def search(self):
        return self.solr.search(self.textToFind.data)


###############################################################################
# R O U T E S
#

#######
# /
#
@app.route('/')
def index():
    return render_template('index.html')

#######
# login
#
@app.route('/login', methods=['GET', 'POST'])
def login():
    form = LoginForm()
    if form.validate_on_submit():
        user = User.query.filter_by(username=form.username.data).first()
        if user:
            if check_password_hash(user.password,form.password.data):
                login_user(user, remember=form.remember.data)
                return redirect(url_for('dashboard'))
            return '<h1>Invalid user name or password</h1>'
        #        return '<h1>' + form.username.data + ' ' + form.password.data + '</h1>'

    return render_template('login.html', form=form)

#######
# signup
#
@app.route('/signup', methods=['GET','POST'])
def signup():
    form = RegisterForm()

    if form.validate_on_submit():
        hashed_password = generate_password_hash(form.password.data, method='sha256')
        new_user = User(username=form.username.data, password=hashed_password, email=form.email.data)
        db.session.add(new_user)
        db.session.commit()
        return '<h1>Un nouvel utilisateur a été créé !</h1>'

    return render_template('signup.html', form=form)

#######
# logout
#
@app.route('/logout')
def logout():
    logout_user()
    return redirect(url_for('index'))

#######
# dashboard
#
@app.route('/dashboard')
@login_required
def dashboard():
    return render_template('dashboard.html', name = current_user.username)

#######
# solrrouted
#
@app.route('/solrrouted', methods=['GET', 'POST'])
@login_required
def solrrouted():
    form = SolrForm()
    if form.validate_on_submit():
        return render_template('solr.html',form=form)
    else:
        return render_template('solr.html',form=form)

###############################################################################
#
# R U N   A P P L I C A T I O N
#
if __name__ == '__main__':
    app.run(host='0.0.0.0' ,debug=True)

solr.html

{% extends "bootstrap/base.html" %}
{% import "bootstrap/wtf.html" as wtf %}

{% block title %}
SolR
{% endblock %}

{% block styles %}
{{super()}}
<link rel="stylesheet" href="{{url_for('.static', filename='solr.css')}}">
{% endblock %}

{% block content %}
    <nav class="navbar navbar-inverse navbar-fixed-top">
      <div class="container-fluid">
        <div class="navbar-header">
          <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
            <span class="sr-only">Toggle navigation</span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
          </button>
          <a class="navbar-brand" href="/">Rajòl</a>
        </div>
        <div id="navbar" class="navbar-collapse collapse">
          <ul class="nav navbar-nav navbar-right">
            <li><a href="/">Accueil</a></li>
            <li><a href="{{ url_for('dashboard') }}">Dashboard</a></li>
            <li><a href="{{ url_for('logout') }}">Se déconnecter</a></li>
          </ul>
          <!--
          <form class="navbar-form navbar-right">
            <input type="text" class="form-control" placeholder="Cercar ...">
          </form>
          -->
        </div>
      </div>
    </nav>

    <div class="container-fluid">
      <form class="form-signin solr_size", method="POST", action="/solrrouted">
        <h2 class="form-signin-heading">Entrez un mot</h2>
        {{ form.hidden_tag() }}
        {{ wtf.form_field(form.textToFind) }}
        <button class="btn btn-lg btn-primary btn-block" type="submit">Soumettre</button>
      </form>

      <ul class="list-group solr_size">
          {% for result in form.search(): %}
          <li class="list-group-item">{{ result['title'] }}</li>
          {% endfor %}
      </ul>
    </div>
{% endblock %}

Execucion

Dintrar dins l'environament virtual python

[admin@vertigo] ~% source envs/monflaskr/bin/activate.csh

Enregar lo servidor

[monflaskr] [admin@vertigo] ~/flask/dca/start% python app.py
....
  'SQLALCHEMY_TRACK_MODIFICATIONS adds significant overhead and '
 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
 * Restarting with stat
/usr/home/admin/envs/monflaskr/lib/python2.7/site-packages/flask_sqlalchemy/__init__.py:839: FSADeprecationWarning: SQLALCHEMY_TRACK_MODIFICATIONS adds significant overhead and will be disabled by default in the future.  Set it to True or False to suppress this warning.
  'SQLALCHEMY_TRACK_MODIFICATIONS adds significant overhead and '
 * Debugger is active!
 * Debugger pin code: 203-655-219

URL del site

Lo pòrt es 5000. Als administrators de se petaçar per fargar un environament de produccion.

http://monexemple.com:5000