docs: def get_model(model, engine_name=None, signal=True, reload=False):
      """
      Return a real model object, so if the model is already a Model class, then
      return it directly. If not then import it.
  
      if engine_name is None, then if there is multi engines defined, it'll use
      'default', but if there is only one engine defined, it'll use this one
  
      :param dispatch: Used to switch dispatch signal
      """
      if isinstance(model, type) and issubclass(model, Model):
          return model
      if not isinstance(model, (str, unicode)):
          raise Error("Model %r should be string or unicode type" % model)
      
      #make model name is lower case
      model = model.lower()
      model_item = __models__.get(model)
      if not model_item:
          model_item = dispatch.get(None, 'find_model', model_name=model)
      if model_item:
          if not engine_name:
              #search according model_item, and it should has only one engine defined
              engines = model_item['engines']
              if len(engines) > 1:
                  engine_name = __default_engine__
              else:
                  engine_name = engines[0]
          engine = engine_manager[engine_name]
  
          item = engine._models.get(model)
          #process duplication
          if not item and engine.options.duplication:
              _item = engine.models.get(model)
              if _item:
                  item = _item.copy()
                  item['model'] = None
                  engine._models[model] = item
          if item:
              loaded = False #True, model is already loaded, so consider if it needs be cached
              m = item['model']
              m_config = __models__[model].get('config', {})
              if isinstance(m, type) and issubclass(m, Model):
                  loaded = True
                  if reload:
                      loaded = False
                  #add get_model previous hook
                  if signal:
                      model_inst = dispatch.get(None, 'get_model', model_name=model, model_inst=m,
                                        model_info=item, model_config=m_config) or m
                      if m is not model_inst:
                          loaded = False
                  else:
                      model_inst = m
              else:
                  #add get_model previous hook
                  if signal:
                      model_inst = dispatch.get(None, 'get_model', model_name=model, model_inst=None,
                                        model_info=item, model_config=m_config)
                  else:
                      model_inst = None
                  if not model_inst:
                      if item['model_path']:
                          mod_path, name = item['model_path'].rsplit('.', 1)
                          mod = __import__(mod_path, fromlist=['*'])
                          model_inst = getattr(mod, name)
                      #empty model_path means dynamic model
                  if not model_inst:
                      raise ModelNotFound("Can't found the model %s in engine %s" % (model, engine_name))
  
              if not loaded:
                  if model_inst._bound_classname == model and not reload:
                      model_inst = model_inst._use(engine_name)
                      item['model'] = model_inst
                  else:
                      config = __models__[model].get('config', {})
                      if config:
                          for k, v in config.items():
                              setattr(model_inst, k, v)
                      item['model'] = model_inst
                      model_inst._alias = model
                      model_inst._engine_name = engine_name
  
                      if __lazy_model_init__:
                          for k, v in model_inst.properties.items():
                              v.__property_config__(model_inst, k)
  
                  #add bind process
                  if reload:
                      reset = True
                  else:
                      reset = False
                  model_inst.bind(engine.metadata, reset=reset)
  
              #post get_model
              if signal:
                  dispatch.call(None, 'post_get_model', model_name=model, model_inst=model_inst,
                                        model_info=item, model_config=m_config)
              return model_inst
              
      raise ModelNotFound("Can't found the model %s in engine %s" % (model, engine_name))