Comment faire pour exécuter Flacon de Connexion, en Flacon de BrowserID et en Flacon de SQLAlchemy en harmonie?
-
21-12-2019 - |
Question
Le Point De L'Ensemble
Je suis d'essayer de faire un assez site web de base avec Flacon (noob!) et suis en cours d'exécution des ennuis avec le login de l'utilisateur du système.J'ai décidé que je veux utiliser en Flacon de Connexion, en Flacon de BrowserID (Mozilla Persona) et SQLAlchemy.Je vais avoir Persona être la partie qui prend soin de stocker les mots de passe utilisateur et de ce fait, je vais utiliser en Flacon de Connexion une fois que l'utilisateur a été authentifié pour garder une trace de leurs séances et je vais utiliser SQLAlchemy pour stocker le tout dans un sqlite3 db.J'ai fait beaucoup de rebondir et je pense que j'ai presque fini de ces fonctionnalités, mais je n'arrive pas à obtenir de nouveau une erreur spécifique.
Mise à jour 1
Basé sur le commentaire par davidism, j'ai dû ajouter de la db.Modèle de l'Utilisateur de la classe.Malheureusement, qui a résolu la première erreur, mais maintenant il ya une nouvelle à traiter.Traceback trouvé ci-dessous.
La Question
Ce qui donne?Je suis évidemment manquer quelque chose, mais je n'arrive pas à trouver ce que c'est.
Ressources que j'ai travaillé avec
- En Flacon De BrowserID: https://github.com/garbados/flask-browserid/wiki
- Flacon De Connexion: http://flask-login.readthedocs.org/en/latest/
- En Flacon De SQLAlchemy: http://pythonhosted.org/Flask-SQLAlchemy/quickstart.html#a-minimal-application
- Est-il possible de stocker Python les objets de la classe dans SQLite?
- SQLAlchemy Docs: http://docs.sqlalchemy.org/en/rel_0_9/orm/tutorial.html
- TRAVAIL en Flacon de BrowserID: https://github.com/garbados/flask-browserid/blob/master/tests/init.py
Des Informations Supplémentaires
Voici mon main.py et index.html je l'utilise avec le Flacon et le Traceback j'obtiens:
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'
La solution
La réponse à la question d'origine
L' User
le modèle doit être une sous-classe de db.Model
(ou un mappage de classe) pour travailler avec SQLAlchemy.
class User(UserMixin, db.Model):
...
La réponse à la première mise à jour
Vous ne semblez pas comprendre ce qui est arriver retourné par session.de la requête.Si vous interrogez un modèle unique, les "lignes" qui sont retournées sont des instances du modèle.Les lignes ne seront jamais Aucun.Lorsque vous êtes à la vérification de l'existence, vous devriez utiliser .first()
si vous êtes en appliquant des filtres, ou .get(primary_key)
si vous êtes le filtrage par clé primaire.Il obtient le premier résultat uniquement parce que les utilisateurs sont uniques de toute façon
C'est ce que votre get_user_by_id
devrait ressembler à:
def get_user_by_id(id):
return User.query.get(id)
C'est ce que votre get_user
devrait ressembler à:
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