关于todoism的initdb错误


#1

错误提示如下:

(FlaskProjects-BArbVR56) D:\FlaskProjects\FlaskHTTP\mytodoism>flask initdb
Traceback (most recent call last):
  File "D:\Phthon37\Lib\runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "D:\Phthon37\Lib\runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "C:\Users\张启宏\.virtualenvs\FlaskProjects-BArbVR56\Scripts\flask.exe\__main__.py", line 9, in <module>
  File "c:\users\张启宏\.virtualenvs\flaskprojects-barbvr56\lib\site-packages\flask\cli.py", line 894, in main
    cli.main(args=args, prog_name=name)
  File "c:\users\张启宏\.virtualenvs\flaskprojects-barbvr56\lib\site-packages\flask\cli.py", line 557, in main
    return super(FlaskGroup, self).main(*args, **kwargs)
  File "c:\users\张启宏\.virtualenvs\flaskprojects-barbvr56\lib\site-packages\click\core.py", line 717, in main
    rv = self.invoke(ctx)
  File "c:\users\张启宏\.virtualenvs\flaskprojects-barbvr56\lib\site-packages\click\core.py", line 1132, in invoke
    cmd_name, cmd, args = self.resolve_command(ctx, args)
  File "c:\users\张启宏\.virtualenvs\flaskprojects-barbvr56\lib\site-packages\click\core.py", line 1171, in resolve_command
    cmd = self.get_command(ctx, cmd_name)
  File "c:\users\张启宏\.virtualenvs\flaskprojects-barbvr56\lib\site-packages\flask\cli.py", line 515, in get_command
    rv = info.load_app().cli.get_command(ctx, name)
  File "c:\users\张启宏\.virtualenvs\flaskprojects-barbvr56\lib\site-packages\flask\cli.py", line 372, in load_app
    app = locate_app(self, import_name, name)
  File "c:\users\张启宏\.virtualenvs\flaskprojects-barbvr56\lib\site-packages\flask\cli.py", line 254, in locate_app
    return find_best_app(script_info, module)
  File "c:\users\张启宏\.virtualenvs\flaskprojects-barbvr56\lib\site-packages\flask\cli.py", line 76, in find_best_app
    app = call_factory(script_info, app_factory)
  File "c:\users\张启宏\.virtualenvs\flaskprojects-barbvr56\lib\site-packages\flask\cli.py", line 116, in call_factory
    return app_factory()
  File "D:\FlaskProjects\FlaskHTTP\mytodoism\mytodoism\__init__.py", line 24, in create_app
    register_blueprints(app)
  File "D:\FlaskProjects\FlaskHTTP\mytodoism\mytodoism\__init__.py", line 41, in register_blueprints
    app.register_blueprint(todo_bp)
  File "c:\users\张启宏\.virtualenvs\flaskprojects-barbvr56\lib\site-packages\flask\app.py", line 66, in wrapper_func
    return f(self, *args, **kwargs)
  File "c:\users\张启宏\.virtualenvs\flaskprojects-barbvr56\lib\site-packages\flask\app.py", line 1115, in register_blueprint
    blueprint.register(self, options, first_registration)
  File "c:\users\张启宏\.virtualenvs\flaskprojects-barbvr56\lib\site-packages\flask\blueprints.py", line 187, in register
    deferred(state)
  File "c:\users\张启宏\.virtualenvs\flaskprojects-barbvr56\lib\site-packages\flask\blueprints.py", line 208, in <lambda>
    s.add_url_rule(rule, endpoint, view_func, **options))
  File "c:\users\张启宏\.virtualenvs\flaskprojects-barbvr56\lib\site-packages\flask\blueprints.py", line 80, in add_url_rule
    view_func, defaults=defaults, **options)
  File "c:\users\张启宏\.virtualenvs\flaskprojects-barbvr56\lib\site-packages\flask\app.py", line 66, in wrapper_func
    return f(self, *args, **kwargs)
  File "c:\users\张启宏\.virtualenvs\flaskprojects-barbvr56\lib\site-packages\flask\app.py", line 1190, in add_url_rule
    raise TypeError('Allowed methods have to be iterables of strings, '
TypeError: Allowed methods have to be iterables of strings, for example: @app.route(..., methods=["POST"])

部分__init__.py源码如下:

import os
import click
from flask import Flask, render_template, jsonify, request
from flask_babel import _
from flask_login import current_user

# from mytodoism.apis.v1 import api_v1
from mytodoism.blueprints.auth import auth_bp
from mytodoism.blueprints.home import home_bp
from mytodoism.blueprints.todo import todo_bp
from mytodoism.extensions import db, login_manager, csrf, babel
from mytodoism.models import User, Item
from mytodoism.settings import config


def create_app(config_name=None):
    if config_name is None:
        config_name = os.getenv('FLASK_CONFIG', 'development')

    app = Flask('mytodoism')
    app.config.from_object(config[config_name])

    register_extensions(app)
    register_blueprints(app)
    register_commands(app)
    register_errors(app)
    register_template_context(app)
    return app


def register_extensions(app):
    db.init_app(app)
    login_manager.init_app(app)
    csrf.init_app(app)
    # csrf.exempt(api_v1)
    babel.init_app(app)


def register_blueprints(app):
    app.register_blueprint(auth_bp)
    app.register_blueprint(todo_bp)
    app.register_blueprint(home_bp)
    # app.register_blueprint(api_v1, url_prefix='/api/v1')
    # app.register_blueprint(api_v1, url_prefix='/v1', subdomain='api')
    # enable subdomain support


def register_template_context(app):
    @app.context_processor
    def make_template_context():
        if current_user.is_authenticated:
            active_items = Item.query.with_parent(current_user).filter_by(done=False).count()
        else:
            active_items = None
        return dict(active_items=active_items)

24行语句: register_blueprints(app)
41行语句:app.register_blueprint(todo_bp)
请各位帮忙分析下


#2

这一句很明显,你是不是改了或加了什么代码?


#3

没找到与源码不同的地方啊?
浏览器运行也提示:

builtins.TypeError
TypeError: Allowed methods have to be iterables of strings, for example: @app.route(..., methods=["POST"])

#4

todo_bp蓝本注册的视图函数代码放出来看看。


#5
@todo_bp.route('/items/new', methods=['POST'])      # 向指定资源提交数据进行处理的请求,用于添加新的内容
@login_required
def new_item():
    data = request.get_json()   # 从请求对象中获取并解析客户端发送的JSON数据
    if data is None or data['body'].strip() == '':
        return jsonify(message=_('Invalid item body.')), 400

    item = Item(body=data['body'], author=current_user._get_current_object())
    db.session.add(item)
    db.session.commit()
    return jsonify(html=render_template('_item.html', item=item), message='+1')


@todo_bp.route('/item/<int:item_id>/edit', methods='PUT')   # 向指定资源位置上传其最新的内容,用于修改某个内容。
@login_required
def edit_item(item_id):
    item = Item.query.get_or_404(item_id)
    if current_user != item.author:
        return jsonify(message=_('Permission denied.')), 403

    data = request.get_json()
    if data is None or data['body'].strip() == '':
        return jsonify(message=_('Invalid item body.')), 400

    item.body = data['body']
    db.session.commit()
    return jsonify(message=_('Item updated.'))


@todo_bp.route('/item/<int:item_id>/toggle', methods=['PATCH'])  # 是对PUT方法的补充,用来对已知资源进行局部更新,PATCH是幂等的。
@login_required
def toggle_item(item_id):
    item = Item.query.get_or_404(item_id)
    if current_user != item.author:
        return jsonify(message=_('Permission denied.')), 403

    item.done = not item.done
    db.session.commit()
    return jsonify(message=_('Item toggled.'))


@todo_bp.route('/item/<int:item_id>/delete', methods=['DELETE'])    # 请求服务器删除请求的URI所标识的资源,用于删除
@login_required
def delete_item(item_id):
    item = Item.query.get_or_404(item_id)
    if current_user != item.author:
        return jsonify(message=_('Permission denied.')), 403

    db.session.delete(item)
    db.session.commit()
    return jsonify(message=_('Item deleted.'))

谢谢指点!错误出在@todo_bp.route(’/item/int:item_id/edit’, methods=‘PUT’) 这句上,methods忘加中括号了