Como executar o Frasco-Login, Frasco-BrowserID e Balão-o SQLAlchemy em harmonia?
-
21-12-2019 - |
Pergunta
O Ponto Inteiro
Eu estou tentando fazer um simples site com Balão (noob!) e estou a ter problemas com o login do usuário do sistema.Eu decidi que eu quero usar o Frasco de Login, Frasco-BrowserID (Mozilla Persona) e o SQLAlchemy.Eu vou ter Persona ser a parte que cuida de armazenar senhas de usuário e tal, eu vou usar Frasco-início de sessão depois que o usuário foi autenticado para manter o controle das suas sessões e que eu vou usar o SQLAlchemy para armazenar tudo em um sqlite3 db.Eu fiz um monte de saltar ao redor e eu acho que eu tenho quase a terminar estas características, mas eu não consigo ter de volta um erro específico.
Atualização 1
Com base no comentário por davidism, tive que adicionar db.Modelo para a classe de Usuário.Infelizmente, o que resolveu o primeiro erro, mas agora há um novo para lidar com eles.Traço encontrado abaixo.
A Pergunta
O que dá?Estou, obviamente, falta algo, mas eu não consigo encontrar o que que é.
Recursos que eu tenho vindo a trabalhar com
- Frasco-BrowserID: https://github.com/garbados/flask-browserid/wiki
- Frasco-Login: http://flask-login.readthedocs.org/en/latest/
- Balão-O SQLAlchemy: http://pythonhosted.org/Flask-SQLAlchemy/quickstart.html#a-minimal-application
- É possível armazenar Python classe de objetos no SQLite?
- O SQLAlchemy Docs: http://docs.sqlalchemy.org/en/rel_0_9/orm/tutorial.html
- TRABALHO Frasco-BrowserID: https://github.com/garbados/flask-browserid/blob/master/tests/init.py
Informações Adicionais
Aqui é o meu main.py e index.html eu estou usando com Balão e o Traceback eu estou ficando:
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'
Solução
Resposta à pergunta original
O User
o modelo precisa ser uma subclasse de db.Model
(ou uma classe mapeada) para trabalhar com o SQLAlchemy.
class User(UserMixin, db.Model):
...
Resposta para a primeira atualização
Você não parece compreender o que está sendo retornado pela sessão.consulta.Se você consulta um único modelo, as "linhas" que são retornados são instâncias do modelo.As linhas nunca vai ser Ninguém.Quando você estiver verificando a existência, você deve apenas usar .first()
se você estiver aplicando filtros, ou .get(primary_key)
se você está filtrando por chave primária.Este recebe o primeiro resultado só, pois os usuários são exclusivos de qualquer maneira
Isto é o que o seu get_user_by_id
deve parecer com:
def get_user_by_id(id):
return User.query.get(id)
Isto é o que o seu get_user
deve parecer com:
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