背景
在这个Flask+RESTplus服务器示例中,我尝试使用PostgreSQL后端而不是Sqlite。
我遇到了PasswordType数据库列类型的问题。为了使它发挥作用,我不得不在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)
这真的很糟糕,因为密码将以明文形式存储。。。我需要你的帮助!
在tasks/app/db_templates/sflak/script.py.mako中将第13行改为第15行之后至
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
(它不存在于我的Flask RESTplus示例服务器中(。请检查您的新迁移,并删除与PasswordType相关的所有内容。这是SQLAlchemy Utils中的一个错误,它在Alembic中不太好用:https://github.com/kvesteri/sqlalchemy-utils/issues/106
更新:我已经提交了一份PR来解决这个问题:https://github.com/kvesteri/sqlalchemy-utils/pull/254
sqlalchemy_utils.types.password.PasswordType(length=1094), nullable=True),
我们需要将自动生成的字段类型更改为以下类型
sqlalchemy_utils.types.password.PasswordType(max_length=1094), nullable=True),