美文网首页
Flask Admin 模型CRUD源代码

Flask Admin 模型CRUD源代码

作者: 友仁恒敬 | 来源:发表于2020-02-02 13:03 被阅读0次

    为了学习统一处理model的CRUD,所以学习一下 flask-admin的实现方式

    使用visual studio 打开 flask-admin , 找到了model/base.py 发现了BaseModelView类,其中

        def create_model(self, form):
             raise NotImplementedError()
        def update_model(self, form, model):
              raise NotImplementedError()
        def delete_model(self, model):
              raise NotImplementedError()
    

    可见基类没有实现,实现在子类中,查找一下BaseModelView有哪些子类

    crontrib/appengine/view.py
        NdbModelView  # google 云数据库 Ndb 我们被墙,所以不用考虑
        DbModelView # google 云数据库 Db
    crontrib/pymongo/view.py
        ModelView # mongodb实现,即nosql型 数据库的实现
    crontrib/sqla/view.py
        ModelView # 通用的sql数据库实现
    

    所以我们仅看一下 sqla下的实现

    def create_model(self, form):
            """
                Create model from form.
                :param form:
                    Form instance
            """
            try:
                model = self._manager.new_instance() # self._manager = manager_of_class(self.model)  , 相当于self.model._sa_class_manager.new_instance() 是sqlachemy中的方法
                # TODO: We need a better way to create model instances and stay compatible with
                # SQLAlchemy __init__() behavior
                state = instance_state(model) # self.model._sa_instance_state
                self._manager.dispatch.init(state, [], {})
    
                form.populate_obj(model) # 关键是这行代码,稍后分析
                self.session.add(model)
                self._on_model_change(form, model, True) # 调用的父类的事件,其实父类事件也是调用self.on_model_change但依旧未实现,子类可以实现。
                self.session.commit()
            except Exception as ex:
                if not self.handle_view_exception(ex):
                    flash(gettext('Failed to create record. %(error)s', error=str(ex)), 'error')
                    log.exception('Failed to create record.')
    
                self.session.rollback() # 重要,回滚操作
                return False
            else: # 这个else很有意思,是try->except->else
                self.after_model_change(form, model, True) # 默认是空,可自定义
    
            return model
    

    ** form.populate_obj(model) **

      # model/fields.py InlineModelFormField
       def populate_obj(self, obj, name):
            for name, field in iteritems(self.form._fields):
                if name != self._pk:
                    field.populate_obj(obj, name)
    
    # model/fields.py InlineModelFormList
    def populate_obj(self, obj, name):
            values = getattr(obj, name, None)
    
            if values is None:
                return
    
            # Create primary key map
            pk_map = dict((get_obj_pk(v, self._pk), v) for v in values)
    
            # Handle request data
            for field in self.entries:
                field_id = get_field_id(field)
    
                is_created = field_id not in pk_map
                if not is_created:
                    model = pk_map[field_id]
    
                    if self.should_delete(field):
                        self.session.delete(model)
                        continue
                else:
                    model = self.model()
                    values.append(model)
    
                field.populate_obj(model, None)
    
                self.inline_view._on_model_change(field, model, is_created)
    

    似乎更多的是view(页面显示)逻辑,而本身逻辑很简单就是getattr

    相关文章

      网友评论

          本文标题:Flask Admin 模型CRUD源代码

          本文链接:https://www.haomeiwen.com/subject/osafxhtx.html