docs: def save(self, insert=False, changed=None, saved=None,
              send_dispatch=True, version=False, version_fieldname=None, 
              version_exception=True):
          """
          If insert=True, then it'll use insert() indead of update()
          
          changed will be callback function, only when the non manytomany properties
          are saved, the signature is:
              
              def changed(obj, created, old_data, diff_data):
                  if flag is true, then it means the record is changed
                  you can change new_data, and the new_data will be saved to database
                  
          version = Optimistic Concurrency Control
          version_fieldname default is 'version'
          if check_many, it'll auto check if manytomany value need to save, 
          only available in UPDATE
          """
          _saved = False
          created = False
          version_fieldname = version_fieldname or 'version'
          d = self._get_data()
          #fix when d is empty, orm will not insert record bug 2013/04/07
          if d or not self._saved or insert:
              _id = d.get(self._primary_field, None)
              if insert or not self._saved or not _id:
                  created = True
                  old = d.copy()
                  
                  if get_dispatch_send() and self.__dispatch_enabled__:
                      dispatch.call(self.__class__, 'pre_save', instance=self, created=True, data=d, old_data=self._old_values, signal=self.tablename)
                  
                  #process auto_now_add
                  _manytomany = {}
                  for k, v in self.properties.items():
                      if v.property_type == 'compound':
                          continue
                      if not isinstance(v, ManyToMany):
                          if isinstance(v, DateTimeProperty) and v.auto_now_add and k not in d:
                              d[k] = v.now()
                          elif (not k in d) and v.auto_add:
                              d[k] = v.default_value()
                      else:
                          if k in d:
                              _manytomany[k] = d.pop(k)
                  if d:
                      if callable(changed):
                          changed(self, created, self._old_values, d)
                          old.update(d)
                      obj = do_(self.table.insert().values(**d), self.get_session())
                      _saved = True
  
                      if obj.inserted_primary_key and self._primary_field:
                          setattr(self, self._primary_field, obj.inserted_primary_key[0])
  
                  if _manytomany:
                      for k, v in _manytomany.items():
                          if v:
                              _saved = getattr(self, k).update(v) or _saved
                  
              else:
                  _id = d.pop(self._primary_field)
                  if d:
                      old = d.copy()
                      if get_dispatch_send() and self.__dispatch_enabled__:
                          dispatch.call(self.__class__, 'pre_save', instance=self, created=False, data=d, old_data=self._old_values, signal=self.tablename)
  
                      #process auto_now
                      _manytomany = {}
                      for k, v in self.properties.items():
                          if v.property_type == 'compound' or k == self._primary_field:
                              continue
                          if not isinstance(v, ManyToMany):
                              if isinstance(v, DateTimeProperty) and v.auto_now and k not in d:
                                  d[k] = v.now()
                              elif (not k in d) and v.auto:
                                  d[k] = v.default_value()
                          else:
                              if k in d:
                                  _manytomany[k] = d.pop(k)
                      if d:
                          _cond = self.table.c[self._primary_field] == self._key
                          if version:
                              version_field = self.table.c.get(version_fieldname)
                              if version_field is None:
                                  raise KindError("version_fieldname %s is not existed in Model %s" % (version_fieldname, self.__class__.__name__))
                              _version_value = getattr(self, version_fieldname, 0)
                              # setattr(self, version_fieldname, _version_value+1)
                              d[version_fieldname] = _version_value+1
                              _cond = (version_field == _version_value) & _cond
                              
                          if callable(changed):
                              changed(self, created, self._old_values, d)
                              old.update(d)
                          result = do_(self.table.update(_cond).values(**d), self.get_session())
                          _saved = True
                          if version:
                              if result.rowcount == 0:
                                  _saved = False
                                  if version_exception:
                                      raise SaveError("The record {0}:{1} has been saved by others, current version is {2}".format(
                                          self.tablename, self._key, _version_value))
                              else:
                                  setattr(self, version_fieldname, d[version_fieldname])
                          elif result.rowcount == 0:
                              _saved = False
                              # raise NotFound("The record can't be found!", self.tablename, self._key)
                        
                      if _manytomany:
                          for k, v in _manytomany.items():
                              if v is not None:
                                  _saved = getattr(self, k).update(v) or _saved
  
                  # else:
                  #     #check if the field is primary_key, true will raise Exception
                  #     #2015/11/20 limodou
                  #     raise ValueError("You can't only change primary key '{}'.".format(self._primary_field))
  
  
              if _saved:
                  for k, v in d.items():
                      x = self.properties[k].get_value_for_datastore(self)
                      if self.field_str(x) != self.field_str(v):
                          setattr(self, k, v)
                  if send_dispatch and get_dispatch_send() and self.__dispatch_enabled__:
                      dispatch.call(self.__class__, 'post_save', instance=self, created=created, data=old, old_data=self._old_values, signal=self.tablename)
                  self.set_saved()
                  
                  if callable(saved):
                      saved(self, created, self._old_values, old)
  
          return _saved