Подтвердить что ты не робот

Flask-Security user_registered Сигнал не получен в Python 3.3, но работает в 2.7

Я пытаюсь использовать user_registered сигнал, чтобы настроить роли по умолчанию для пользователей, когда они регистрируются с использованием флай-безопасности, как в следующей ссылке: Установка роли по умолчанию в защите от флагов

В моих поисках я вижу, что была ошибка, которая уже была исправлена ​​для этого в flask-security: Не получать сигнал от флеш-безопасности, Fix - проблема с пользовательской регистрацией

Я пробовал следующее, чтобы доказать, что сигнал получен обработчиком без везения:

@user_registered.connect_via(app)
def user_registered_sighandler(sender, **extra):
    print("print-user_registered_sighandler:", extra)

Это, однако, никогда не вызывается, даже если пользователь регистрируется и сигнал должен быть отправлен.

Если это помогает, я установил конфигурацию с флеш-защитой следующим образом:

app.config['SECURITY_REGISTERABLE'] = True
app.config['SECURITY_CONFIRMABLE'] = False
app.config['SECURITY_SEND_REGISTER_EMAIL'] = False
app.config['SECURITY_CHANGEABLE'] = True
app.config['SECURITY_SEND_PASSWORD_CHANGE_EMAIL'] = False

Сигналы от Flask-Login и Flask-Principal работают для меня, поскольку мне удалось подтвердить, что следующие коды кода успешно печатаются при отправке сигналов:

@user_logged_out.connect_via(app)
def on_user_logged_out(sender, user):
    print('USER LOG OUT: made it in',user)

@identity_changed.connect_via(app)
def identity_changed_ok(sender,identity):
    print('Identity changed:',identity)

Для моей установки я использую python 3.3 (anaconda) и используя следующее: Колба == 0.10.1, колба логином == 0.2.11, колба-принципал == 0.4.0 == колбовую безопасности 1.7.4, мигалка == 1,3. Посмотрев на сигналы в обоих флажках-входах и флеш-безопасности, я не уверен, почему сигналы с защитой от фляг не будут работать.

EDIT:

Если я добавлю print(user_registered.receivers) в маршрут в моем приложении, он покажет, что у меня есть приемник: {139923381372400: <function user_registered_sighandler at 0x7f42737145f0>}. Если я поставлю этот же оператор печати в файле registerable.py с флажком перед user_registered.send(app._get_current_object(),user=user, confirm_token=token), тогда он не будет перечислять получателей: {}

EDIT2:

Проблема, похоже, связана с использованием python 3.3. Я создал среду python 2.7, и код user_registered работал должным образом.

Полный код для воспроизведения:

from flask import Flask,render_template
from playhouse.flask_utils import FlaskDB
import os
from flask.ext.security import Security, PeeweeUserDatastore
from flask.ext.security.signals import user_registered
from flask.ext.login import user_logged_out
from peewee import *
from playhouse.signals import Model
from flask.ext.security import UserMixin,RoleMixin

app = Flask(__name__)

app.config['ADMIN_PASSWORD']='secret'
app.config['APP_DIR']=os.path.dirname(os.path.realpath(__file__))
app.config['DATABASE']='sqliteext:///%s' % os.path.join(app.config['APP_DIR'], 'blog.db')
app.config['SECRET_KEY'] = 'shhh, secret!'
app.config['SECURITY_REGISTERABLE'] = True
app.config['SECURITY_CONFIRMABLE'] = False
app.config['SECURITY_SEND_REGISTER_EMAIL'] = False

flask_db = FlaskDB()
flask_db.init_app(app)
database = flask_db.database

class BaseModel(Model):
    class Meta:
        database=flask_db.database


class User(BaseModel, UserMixin):
    email=CharField()
    password=CharField()
    active = BooleanField(default=True)
    confirmed_at = DateTimeField(null=True)

    def is_active(self):
        return True

    def is_anonymous(self):
        return False

    def is_authenticated(self):
        return True


class Role(BaseModel, RoleMixin):
    name = CharField(unique=True)
    description = TextField(null=True)


class UserRoles(BaseModel):
    user = ForeignKeyField(User, related_name='roles')
    role = ForeignKeyField(Role, related_name='users')
    name = property(lambda self: self.role.name)
    description = property(lambda self: self.role.description)


user_datastore = PeeweeUserDatastore(database, User, Role, UserRoles)
security = Security(app, user_datastore)

@user_registered.connect_via(app)
def user_registered_sighandler(sender,**extra):
    print("print-user_registered_sighandler")

@user_logged_out.connect_via(app)
def on_user_logged_out(sender, user):
    print('USER LOG OUT: made it in',user)

@app.route('/')
def index():
    print(user_registered.receivers)
    return render_template('base.html')

database.create_tables([User,Role,UserRoles], safe=True)
app.run(debug=True)

base.html шаблон:

<!doctype html>
<html>
  <head>
    <title>Blog</title>
  </head>
  <body>
          <ul>
            {% if current_user.is_authenticated() %}
              <li><a href="{{ url_for('security.logout',next='/') }}">Log out</a></li>
              <li><a href="{{ url_for('security.register') }}">Register</a></li>
        {% else %}
        <li><a href="{{ url_for('security.login',next='/') }}">Login</a></li>
        <li><a href="{{ url_for('security.register') }}">Register</a></li>
            {% endif %}
            {% block extra_header %}{% endblock %}
          </ul>
  </body>
</html>
4b9b3361

Ответ 1

Если импорт для user_registered изменен на следующее:

from flask.ext.security import user_registered

тогда сигнал будет работать как ожидается в python 3.3 и вызовет функцию user_registered_sighandler, когда пользователь зарегистрирован.

Сигнал user_registered импортируется в файле __init__.py для флеш-безопасности, поэтому он также доступен на верхнем уровне пакета.

Ответ 2

Я смог сделать это с чем-то вроде:

security = Security(app, user_datastore,
         register_form=ExtendedRegisterForm)


@user_registered.connect_via(app)
def user_registered_sighandler(app, user, confirm_token):
    default_role = user_datastore.find_role("Pending")
    user_datastore.add_role_to_user(user, default_role)
    db.session.commit()