【问题标题】:Can't catch exception inside create_view() in no-debug mode在非调试模式下无法在 create_view() 中捕获异常
【发布时间】:2019-07-26 15:38:37
【问题描述】:

我已经在 mongoengine.ModelView 中覆盖了 create_view() 方法:

from mongoengine.errors import NotUniqueError
from pymongo.errors import DuplicateKeyError


class MyView(mongoengine.ModelView):
@expose('/create/', methods=('GET', 'POST'))
    def create_view(self):
        try:
            return super(MyView, self).create_view()
        except (NotUniqueError, DuplicateKeyError):
            flash('Duplicated search word! Redirected to existing record.', 'error')

            # redirect logic here
            location = "/"
            return redirect(location)

在使用app.run(debug=True) 运行服务器时,我能够捕获该NotUniqueError 异常。

但是如果debug=False 那个try:except 块被忽略:

Traceback (most recent call last):
  File "/home/pata/venvs/lib/python3.6/site-packages/mongoengine/document.py", line 389, in save
    object_id = self._save_create(doc, force_insert, write_concern)
  File "/home/pata/venvs/lib/python3.6/site-packages/mongoengine/document.py", line 452, in _save_create
    object_id = wc_collection.insert_one(doc).inserted_id
  File "/home/pata/venvs/lib/python3.6/site-packages/pymongo/collection.py", line 693, in insert_one
    session=session),
  File "/home/pata/venvs/lib/python3.6/site-packages/pymongo/collection.py", line 607, in _insert
    bypass_doc_val, session)
  File "/home/pata/venvs/lib/python3.6/site-packages/pymongo/collection.py", line 595, in _insert_one
    acknowledged, _insert_command, session)
  File "/home/pata/venvs/lib/python3.6/site-packages/pymongo/mongo_client.py", line 1248, in _retryable_write
    return self._retry_with_session(retryable, func, s, None)
  File "/home/pata/venvs/lib/python3.6/site-packages/pymongo/mongo_client.py", line 1201, in _retry_with_session
    return func(session, sock_info, retryable)
  File "/home/pata/venvs/lib/python3.6/site-packages/pymongo/collection.py", line 592, in _insert_command
    _check_write_command_response(result)
  File "/home/pata/venvs/lib/python3.6/site-packages/pymongo/helpers.py", line 217, in _check_write_command_response
    _raise_last_write_error(write_errors)
  File "/home/pata/venvs/lib/python3.6/site-packages/pymongo/helpers.py", line 198, in _raise_last_write_error
    raise DuplicateKeyError(error.get("errmsg"), 11000, error)
pymongo.errors.DuplicateKeyError: E11000 duplicate key error collection: test_db.search_word index: word_1 dup key: { : "word" }

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/pata/venvs/lib/python3.6/site-packages/flask_admin/contrib/mongoengine/view.py", line 566, in create_model
    model.save()
  File "/home/pata/venvs/lib/python3.6/site-packages/mongoengine/document.py", line 412, in save
    raise NotUniqueError(message % six.text_type(err))
mongoengine.errors.NotUniqueError: Tried to save duplicate unique keys (E11000 duplicate key error collection: test_db.search_word index: word_1 dup key: { : "word" })

【问题讨论】:

    标签: python mongoengine flask-admin


    【解决方案1】:

    异常不在方法create_view 中发生,而是在方法create_model 中发生。它在堆栈跟踪中告诉您:

    Traceback (most recent call last):
      File "/home/pata/venvs/lib/python3.6/site-packages/flask_admin/contrib/mongoengine/view.py", line 566, in create_model
        model.save()
    

    还要注意 Flask-Admin 在调试和生产环境中处理 mongoengine exceptions 的不同方式。

    您需要做的是覆盖create_model 并在那里处理您的特定异常情况,例如

    class MyView(mongoengine.ModelView):
    
        def create_model(self, form):
            """
                Create model helper
                :param form:
                    Form instance
            """
            try:
                model = self.model()
                form.populate_obj(model)
                self._on_model_change(form, model, True)
                model.save()
            except (NotUniqueError, DuplicateKeyError):
    
                # Your code here
    
            except Exception as ex:
                if not self.handle_view_exception(ex):
                    flash(gettext('Failed to create record. %(error)s',
                                  error=format_error(ex)),
                          'error')
                    log.exception('Failed to create record.')
    
                return False
            else:
                self.after_model_change(form, model, True)
    
            return model
    

    【讨论】:

    • 是的,这行得通,谢谢。但是从create_model()return redirect(url) 是不可能的。
    • 我必须同时使用create_view(self)create_model(self, form),在create_model 内手动提升NotUniqueError 并在create_view 内捕获它。这看起来很丑)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-03
    • 2019-04-09
    • 1970-01-01
    • 1970-01-01
    • 2016-10-11
    • 2021-08-07
    相关资源
    最近更新 更多