背景
在这个Flask + RESTplus server example中,我试图使用PostgreSQL后端而不是Sqlite。
我遇到了PasswordType db column类型的问题。为了让它工作,我必须在app/modules/users/models.py中更改以下代码

password = db.Column(
    column_types.PasswordType(
        max_length=128,
        schemes=('bcrypt', )
    ),
    nullable=False
)


password = db.Column(db.String(length=128), nullable=False)

这真的很糟糕,因为密码将以明文存储。。。我需要你的帮助!
line 13 to 15 in tasks/app/db_templates/flask/script.py.mako更改为
from alembic import op
import sqlalchemy as sa
import sqlalchemy_utils
${imports if imports else ""}

我得到以下错误消息,显然与passlib有关:
2016-08-31 23:18:52,751 [INFO] [alembic.runtime.migration] Context impl PostgresqlImpl.
2016-08-31 23:18:52,752 [INFO] [alembic.runtime.migration] Will assume transactional DDL.
2016-08-31 23:18:52,759 [INFO] [alembic.runtime.migration] Running upgrade  -> 99b329343a41, empty message
Traceback (most recent call last):
  File "/usr/local/lib/python3.5/site-packages/sqlalchemy/sql/type_api.py", line 359, in dialect_impl
    return dialect._type_memos[self]['impl']
  File "/usr/local/lib/python3.5/weakref.py", line 365, in __getitem__
    return self.data[ref(key)]
KeyError: <weakref at 0x7fde70d524a8; to 'PasswordType' at 0x7fde70a840b8>

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/bin/invoke", line 11, in <module>
    sys.exit(program.run())
  File "/usr/local/lib/python3.5/site-packages/invoke/program.py", line 270, in run
    self.execute()
  File "/usr/local/lib/python3.5/site-packages/invoke/program.py", line 381, in execute
    executor.execute(*self.tasks)
  File "/usr/local/lib/python3.5/site-packages/invoke/executor.py", line 113, in execute
    result = call.task(*args, **call.kwargs)
  File "/usr/local/lib/python3.5/site-packages/invoke/tasks.py", line 111, in __call__
    result = self.body(*args, **kwargs)
  File "/usr/src/app/tasks/app/run.py", line 35, in run
    context.invoke_execute(context, 'app.db.upgrade')
  File "/usr/src/app/tasks/__init__.py", line 72, in invoke_execute
    results = Executor(namespace, config=context.config).execute((command_name, kwargs))
  File "/usr/local/lib/python3.5/site-packages/invoke/executor.py", line 113, in execute
    result = call.task(*args, **call.kwargs)
  File "/usr/local/lib/python3.5/site-packages/invoke/tasks.py", line 111, in __call__
    result = self.body(*args, **kwargs)
  File "/usr/src/app/tasks/app/db.py", line 177, in upgrade
    command.upgrade(config, revision, sql=sql, tag=tag)
  File "/usr/local/lib/python3.5/site-packages/alembic/command.py", line 174, in upgrade
    script.run_env()
  File "/usr/local/lib/python3.5/site-packages/alembic/script/base.py", line 407, in run_env
    util.load_python_file(self.dir, 'env.py')
  File "/usr/local/lib/python3.5/site-packages/alembic/util/pyfiles.py", line 93, in load_python_file
    module = load_module_py(module_id, path)
  File "/usr/local/lib/python3.5/site-packages/alembic/util/compat.py", line 68, in load_module_py
    module_id, path).load_module(module_id)
  File "<frozen importlib._bootstrap_external>", line 385, in _check_name_wrapper
  File "<frozen importlib._bootstrap_external>", line 806, in load_module
  File "<frozen importlib._bootstrap_external>", line 665, in load_module
  File "<frozen importlib._bootstrap>", line 268, in _load_module_shim
  File "<frozen importlib._bootstrap>", line 693, in _load
  File "<frozen importlib._bootstrap>", line 673, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 662, in exec_module
  File "<frozen importlib._bootstrap>", line 222, in _call_with_frames_removed
  File "migrations/env.py", line 93, in <module>
    run_migrations_online()
  File "migrations/env.py", line 86, in run_migrations_online
    context.run_migrations()
  File "<string>", line 8, in run_migrations
  File "/usr/local/lib/python3.5/site-packages/alembic/runtime/environment.py", line 797, in run_migrations
    self.get_context().run_migrations(**kw)
  File "/usr/local/lib/python3.5/site-packages/alembic/runtime/migration.py", line 312, in run_migrations
    step.migration_fn(**kw)
  File "/usr/src/app/migrations/versions/99b329343a41_.py", line 47, in upgrade
    sa.UniqueConstraint('username')
  File "<string>", line 8, in create_table
  File "<string>", line 3, in create_table
  File "/usr/local/lib/python3.5/site-packages/alembic/operations/ops.py", line 1098, in create_table
    return operations.invoke(op)
  File "/usr/local/lib/python3.5/site-packages/alembic/operations/base.py", line 318, in invoke
    return fn(self, operation)
  File "/usr/local/lib/python3.5/site-packages/alembic/operations/toimpl.py", line 101, in create_table
    operations.impl.create_table(table)
  File "/usr/local/lib/python3.5/site-packages/alembic/ddl/impl.py", line 194, in create_table
    self._exec(schema.CreateTable(table))
  File "/usr/local/lib/python3.5/site-packages/alembic/ddl/impl.py", line 118, in _exec
    return conn.execute(construct, *multiparams, **params)
  File "/usr/local/lib/python3.5/site-packages/sqlalchemy/engine/base.py", line 914, in execute
    return meth(self, multiparams, params)
  File "/usr/local/lib/python3.5/site-packages/sqlalchemy/sql/ddl.py", line 68, in _execute_on_connection
    return connection._execute_ddl(self, multiparams, params)
  File "/usr/local/lib/python3.5/site-packages/sqlalchemy/engine/base.py", line 962, in _execute_ddl
    compiled = ddl.compile(dialect=dialect)
  File "<string>", line 1, in <lambda>
  File "/usr/local/lib/python3.5/site-packages/sqlalchemy/sql/elements.py", line 494, in compile
    return self._compiler(dialect, bind=bind, **kw)
  File "/usr/local/lib/python3.5/site-packages/sqlalchemy/sql/ddl.py", line 26, in _compiler
    return dialect.ddl_compiler(dialect, self, **kw)
  File "/usr/local/lib/python3.5/site-packages/sqlalchemy/sql/compiler.py", line 190, in __init__
    self.string = self.process(self.statement, **compile_kwargs)
  File "/usr/local/lib/python3.5/site-packages/sqlalchemy/sql/compiler.py", line 213, in process
    return obj._compiler_dispatch(self, **kwargs)
  File "/usr/local/lib/python3.5/site-packages/sqlalchemy/sql/visitors.py", line 81, in _compiler_dispatch
    return meth(self, **kw)
  File "/usr/local/lib/python3.5/site-packages/sqlalchemy/sql/compiler.py", line 2157, in visit_create_table
    and not first_pk)
  File "/usr/local/lib/python3.5/site-packages/sqlalchemy/sql/compiler.py", line 213, in process
    return obj._compiler_dispatch(self, **kwargs)
  File "/usr/local/lib/python3.5/site-packages/sqlalchemy/sql/visitors.py", line 81, in _compiler_dispatch
    return meth(self, **kw)
  File "/usr/local/lib/python3.5/site-packages/sqlalchemy/sql/compiler.py", line 2188, in visit_create_column
    first_pk=first_pk
  File "/usr/local/lib/python3.5/site-packages/sqlalchemy/dialects/postgresql/base.py", line 1580, in get_column_specification
    impl_type = column.type.dialect_impl(self.dialect)
  File "/usr/local/lib/python3.5/site-packages/sqlalchemy/sql/type_api.py", line 361, in dialect_impl
    return self._dialect_info(dialect)['impl']
  File "/usr/local/lib/python3.5/site-packages/sqlalchemy/sql/type_api.py", line 403, in _dialect_info
    impl = self._gen_dialect_impl(dialect)
  File "/usr/local/lib/python3.5/site-packages/sqlalchemy/sql/type_api.py", line 763, in _gen_dialect_impl
    typedesc = self.load_dialect_impl(dialect).dialect_impl(dialect)
  File "/usr/local/lib/python3.5/site-packages/sqlalchemy_utils/types/password.py", line 194, in load_dialect_impl
    impl = postgresql.BYTEA(self.length)
  File "/usr/local/lib/python3.5/site-packages/sqlalchemy_utils/types/password.py", line 168, in length
    self._max_length = self.calculate_max_length()
  File "/usr/local/lib/python3.5/site-packages/sqlalchemy_utils/types/password.py", line 176, in calculate_max_length
    for name in self.context.schemes():
  File "/usr/local/lib/python3.5/site-packages/passlib/context.py", line 2714, in __getattribute__
    self._lazy_init()
  File "/usr/local/lib/python3.5/site-packages/passlib/context.py", line 2708, in _lazy_init
    super(LazyCryptContext, self).__init__(**kwds)
  File "/usr/local/lib/python3.5/site-packages/passlib/context.py", line 1707, in __init__
    self.load(kwds)
  File "/usr/local/lib/python3.5/site-packages/passlib/context.py", line 1896, in load
    config = _CryptConfig(source)
  File "/usr/local/lib/python3.5/site-packages/passlib/context.py", line 1019, in __init__
    self._init_options(source)
  File "/usr/local/lib/python3.5/site-packages/passlib/context.py", line 1097, in _init_options
    key, value = norm_context_option(key, value)
  File "/usr/local/lib/python3.5/site-packages/passlib/context.py", line 1162, in _norm_context_option
    raise KeyError("unknown CryptContext keyword: %r" % (key,))
KeyError: "unknown CryptContext keyword: 'length'"

知道吗?提前谢谢你的帮助!

最佳答案

我看到你有一个新的迁移99b329343a41_.py(它不存在于我的烧瓶RESPLUS示例服务器中)。请检查您的新迁移并删除与PasswordType相关的所有内容。这是SQLAlchemy实用程序中的一个错误,它不能很好地与Alembic一起使用:https://github.com/kvesteri/sqlalchemy-utils/issues/106
更新:我已提交PR以解决此问题:https://github.com/kvesteri/sqlalchemy-utils/pull/254

关于python - Alembic不处理column_types.PasswordType:Flask + SQLAlchemy + Alembic,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39260850/

10-13 08:52