# coding: utf-8

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import class_mapper, Query
from sqlalchemy.orm.exc import UnmappedClassError, NoResultFound, MultipleResultsFound

class SQLAlchemy(object):
    ''' Get the sqlalchemy session
    '''
    def __init__(self):
        self.db_session = None
    
    def init_app(self, app=None):
        if app:
            self.db_session = app.db_session
            self.reverse_uri = app.reverse_url

sql_db = SQLAlchemy()

class BaseQuery(Query):
    ''' common custom query
    '''
    def get_by_key(self, tid):
        try:
            obj = self.filter_by(id=tid, block=False).one()
        except (NoResultFound, MultipleResultsFound):
            obj = None
        return obj


class _QueryProperty(object):
    ''' User.query.
    '''
    def __get__(self, obj, obj_cls):
        try:
            mapper = class_mapper(obj_cls)
            if mapper:
                return obj_cls.query_class(mapper, session=sql_db.db_session)
        except UnmappedClassError:
            return None

# this way create class vars is ok, the subclass also can inherit it
Base = declarative_base()
Base.query_class = BaseQuery
Base.query = _QueryProperty()

def obj_to_dict(self, include=[]):
    ''' convent the object to the dcit type
    not contain the relating objects
    '''
    #exclude.append('_sa_instance_state')
    dict_obj = vars(self).copy()
    [dict_obj.pop(e) for e in dict_obj.keys() if e not in include]
       
    return dict_obj

def obj_from_dict(self, data):
    # PS: not contain the user and not method name
    attrs = [e for e in dir(self) if not e.startswith('_') and not callable(getattr(self, e))]
    [setattr(self, e, data[e]) for e in data.keys() if e in attrs]

def obj_save(self):
    if self.can_save():
        if not self.id: sql_db.db_session.add(self)
        sql_db.db_session.commit()
        return True

def fake_get_urn_id(self):
    return "urn:%s:%s" % (self.__tablename__, self.id)
        

Base.reverse_uri = sql_db.reverse_uri
Base.to_dict = obj_to_dict
Base.from_dict = obj_from_dict
Base.save = obj_save
Base.get_urn_id = fake_get_urn_id

@@ -8,16 +8,141 @@
 g: utf-8
+%0A''' Custom the Base Model class.%0A1. create class query db session%0A2. create db -%3E db_sesssion%0A3. add some method to Base%0A'''
 %0A%0Afrom s
@@ -326,16 +326,105 @@
 sFound%0A%0A
+# create the Base class%0ABase = declarative_base()%0A%0A# transfer app for get the db_session%0A
 class SQ
@@ -651,20 +651,57 @@
         
+Base.db = app.db_session%0A            Ba
 se
-lf
 .reverse
@@ -1394,34 +1394,8 @@
  it%0A
-Base = declarative_base()%0A
 Base
@@ -2059,32 +2059,22 @@
 lf.id: s
-ql_db.db_session
+elf.db
 .add(sel
@@ -2085,32 +2085,22 @@
        s
-ql_db.db_session
+elf.db
 .commit(
@@ -2218,46 +2218,8 @@
   %0A%0A
-Base.reverse_uri = sql_db.reverse_uri%0A
 Base

fix bug