Come eseguire Flask-Login, Black-Browserid e Flask-SQLalchemy in Armonia?
-
21-12-2019 - |
Domanda
L'intero punto
Sto tentando di creare un sito Web abbastanza semplice con pallone (noob!) e sto correndo nei guai con il sistema di login dell'utente. Ho deciso che voglio usare Flask-Login, Black-Browserid (Mozilla Persona) e SQLalchemy. Ho intenzione di avere la persona che parte che si prende cura di memorizzare le password degli utenti e tali, ho intenzione di utilizzare il flacone-login una volta che l'utente è stato autenticato per tenere traccia delle loro sessioni e ho intenzione di usare SQLalchemy per memorizzare tutto un db sqlite3. Ho fatto molto rimbalzare e penso di aver quasi terminato queste caratteristiche, ma non riesco a riportare un errore specifico.
Aggiornamento 1
In base al commento di Davidism, ho dovuto aggiungere db.model alla classe utente. Sfortunatamente, questo ha risolto il primo errore, ma ora ce n'è uno nuovo da affrontare. Traceback trovato qui sotto.
La domanda
Cosa dà? Ovviamente mi manca qualcosa, ma non riesco a trovare ciò che è.
Risorse Ho lavorato con
- .
- Black-browserid: https://github.com/garbados/flank-browserid/wiki
- Flask-login: http://flask-login.readthedocs.org/en/ Ultime /
- flacone-sqlalchemy: http://pythonhosted.org/Flak -SqLaLchemy / QuickStart.html # A-minimal-application
- è possibile memorizzare oggetti di classe Python in SQLite?
- SQLalchemy Docs: http://docs.sqlalchemy.org/en/ rel_0_9 / orm / tutorial.html
- flacone-browserid-browserid: https:// GitHub. Com / Garbados / Black-Browserid / Blob / Blob / Master / Test / Init .ppy
Informazioni aggiuntive
Ecco il mio main.py e index.html che sto usando con pallone e la traceback sto ottenendo:
main.py
import sqlite3
from flask import Flask, request, session, g, redirect, url_for, abort, render_template, flash
from contextlib import closing
import time
from flask.ext.login import LoginManager, UserMixin
from flaskext.browserid import BrowserID
from flask.ext.sqlalchemy import SQLAlchemy
## SETUP
DEBUG = True
SECRET_KEY = 'development key'
USERNAME = 'admin'
PASSWORD = 'default'
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/flaskr.db'
db = SQLAlchemy(app)
app.config.from_object(__name__)
app.config['BROWSERID_LOGIN_URL'] = "/login"
app.config['BROWSERID_LOGOUT_URL'] = "/logout"
app.config['SECRET_KEY'] = "deterministic"
app.config['TESTING'] = True
class User(UserMixin, db.Model):
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.UnicodeText, unique=True)
firstname = db.Column(db.Unicode(40))
lastname = db.Column(db.Unicode(40))
date_register = db.Column(db.Integer)
bio = db.Column(db.Text)
facebook = db.Column(db.Unicode(1000))
twitter = db.Column(db.Unicode(1000))
website = db.Column(db.Unicode(1000))
image = db.Column(db.LargeBinary)
def __init__(self, email, firstname=None, lastname=None, date_register=None, bio=None, facebook=None, twitter=None,
website=None, image=None):
self.email = email
self.firstname = firstname
self.lastname = lastname
self.date_register = time.time()
self.bio = bio
self.facebook = facebook
self.twitter = twitter
self.website = website
self.image = image
self.email = email
def __repr__(self):
return '<User %r>' % self.email
### Login Functions ###
def get_user_by_id(id):
"""
Given a unicode ID, returns the user that matches it.
"""
for row in db.session.query(User).filter(User.id == id):
if row is not None:
return row.User
return None
def create_browserid_user(kwargs):
"""
Takes browserid response and creates a user.
"""
if kwargs['status'] == 'okay':
user = User(kwargs['email'])
db.session.add(user)
db.session.commit()
return user
else:
return None
def get_user(kwargs):
"""
Given the response from BrowserID, finds or creates a user.
If a user can neither be found nor created, returns None.
"""
import pdb; pdb.set_trace()
# try to find the user
for row in db.session.query(User).filter(User.email == kwargs.get('email')):
if row is not None:
return row.User
for row in db.session.query(User).filter(User.id == kwargs.get('id')):
if row is not None:
return row.User
# try to create the user
return create_browserid_user(kwargs)
login_manager = LoginManager()
login_manager.user_loader(get_user_by_id)
login_manager.init_app(app)
browserid = BrowserID()
browserid.user_loader(get_user)
browserid.init_app(app)
### Routing ###
@app.route('/')
def home():
return render_template('index.html')
if __name__ == '__main__':
app.run()
.
index.html
<html>
<head>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script src="https://login.persona.org/include.js" type="text/javascript"></script>
<script type="text/javascript">{{ auth_script|safe }}</script>
</head>
<body>
{% if current_user.is_authenticated() %}
<button id="browserid-logout">Logout</button>
{% else %}
<button id="browserid-login">Login</button>
{% endif %}
</body>
</html>
.
Traceback
Traceback (most recent call last):
File "/Library/Python/2.7/site-packages/flask/app.py", line 1701, in __call__
return self.wsgi_app(environ, start_response)
File "/Library/Python/2.7/site-packages/flask/app.py", line 1689, in wsgi_app
response = self.make_response(self.handle_exception(e))
File "/Library/Python/2.7/site-packages/flask/app.py", line 1687, in wsgi_app
response = self.full_dispatch_request()
File "/Library/Python/2.7/site-packages/flask/app.py", line 1360, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/Library/Python/2.7/site-packages/flask/app.py", line 1358, in full_dispatch_request
rv = self.dispatch_request()
File "/Library/Python/2.7/site-packages/flask/app.py", line 1344, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/Users/jzeller/Classes/CS494/main.py", line 106, in home
return render_template('test.html')
File "/Library/Python/2.7/site-packages/flask/templating.py", line 123, in render_template
ctx.app.update_template_context(context)
File "/Library/Python/2.7/site-packages/flask/app.py", line 692, in update_template_context
context.update(func())
File "/Library/Python/2.7/site-packages/flask_login.py", line 799, in _user_context_processor
return dict(current_user=_get_user())
File "/Library/Python/2.7/site-packages/flask_login.py", line 768, in _get_user
current_app.login_manager._load_user()
File "/Library/Python/2.7/site-packages/flask_login.py", line 348, in _load_user
return self.reload_user()
File "/Library/Python/2.7/site-packages/flask_login.py", line 312, in reload_user
user = self.user_callback(user_id)
File "/Users/jzeller/Classes/CS494/main.py", line 60, in get_user_by_id
print "get_user_by_id - " + str(type(row.User)) + " - " + str(row.User)
AttributeError: 'User' object has no attribute 'User'
. Soluzione
Risposta alla domanda originale
Il modello User
deve essere una sottoclasse di db.Model
(o una classe mappata) per funzionare con SQLalchemy.
class User(UserMixin, db.Model):
...
.
Risposta al primo aggiornamento
Non sembra capire cosa viene restituito da Session.Query.Se si interroga un singolo modello, le "righe" restituite sono istanze del modello.Le righe non saranno mai nessuno.Quando stai controllando dell'esistenza, è necessario utilizzare .first()
se si sta applicando i filtri o .get(primary_key)
se stai filtrando per chiave primaria.Questo ottiene il primo risultato solo dal momento che gli utenti sono comunque
Questo è ciò che il tuo get_user_by_id
dovrebbe apparire come:
def get_user_by_id(id):
return User.query.get(id)
.
Questo è ciò che il tuo get_user
dovrebbe apparire come:
def get_user(kwargs):
u = User.query.filter(db.or_(
User.id == kwargs.get('id'),
User.email == kwargs.get('email')
)).first()
if u is None: # user didn't exist in db
return create_browserid_user(kwargs)
return u
.