metadata的使用以及简单的orm模式

使用sqllite3和metadata简单的封装了个简单的orm

#!/usr/bim/python
#-*-coding: utf-8 -*-

import threading
import sqlite3

import sys

__module__ = sys.modules[__name__]

def setup_database(database):
    Mapper.initialize(database)

def bind_mapper(mapper_name, model_cls, mapper_cls = None):

    if mapper_cls is None:
        mapper_cls = Mapper
    mapper = mapper_cls(model_cls)
    setattr(__module__, mapper_name, mapper)

class FieldError(Exception):

    def __init__(self, message,  *args, **kwargs):
        Exception.__init__(self, message, *args, **kwargs)

class Field:

    def __init__(self, name, affinity=None, validator=None, required=False, default=None,  **kwargs):

        self.affinity = affinity
        self.validator = validator
        self.default = default
        self.required = required
        self.name = name
        self.kwargs = kwargs

    def get_value(self):
        if hasattr(self, "data"):
            return self.data
        else:
            raise FieldError("Field is not initilize")

    def set_value(self, value):
        self.value = self.process_formdata(value)

    value = property(get_value, set_value)

    def validate(self):
        if self.required and self.data is None:
            raise FieldError("Field is required!")
        if self.value == self.default:
            return
        if self.validator:
            self.validator(self)

    def process_formdata(self, value):
        if value or self.required == False:
            try:
                self.data = value
            except ValueError:
                self.data = None
                raise ValueError(‘Not a valid integer value‘)

    def _pre_validate(self):
        pass

    def __call__(self):
        if hasattr(self, "value"):
            return self.value
        else:
            raise FieldError("Filed is not initilize")

class IntegerField(Field):

    """
    A text field, except all input is coerced to an integer.  Erroneous input
    is ignored and will not be accepted as a value.
    """

    def __init__(self, name, affinity=None, validator=None, required=False, defalut=None,  **kwargs):
        Field.__init__(self, name, validator, required, defalut,  **kwargs)

    def process_formdata(self, value):
        if value:
            try:
                self.value = int(value)
            except ValueError:
                self.value = None
                raise ValueError(‘Not a valid integer value‘)

def with_metaclass(meta, bases=(object,)):
    return meta("NewBase", bases, {})

class ModelMeta(type):

    def __new__(metacls, cls_name, bases, attrs):
        fields = {}
        new_attrs = {}
        for k, v in attrs.iteritems():
            if isinstance(v, Field):
                fields[k] = v
            else:
                new_attrs[k] = v

        cls = type.__new__(metacls, cls_name, bases, new_attrs)
        cls.fields = cls.fields.copy()
        cls.fields.update(fields)
        return cls

class ModelMinix(object):

    fields = {}

    def __str__(self):
        return ‘<‘ + self.__class__.__name__ +             ‘ : {‘ + ", ".join(["%s=%s" % (field.name, getattr(self, column))
                                for column, field in self.fields.items()]) + ‘}>‘

    def save(self):
        return self.__mapper__.save(self)

class Model(with_metaclass(ModelMeta, (ModelMinix,))):

    def __init__(self, **kwargs):
        for k in kwargs:
            try:
                if k in self.fields:
                    setattr(self, k, kwargs[k])
            except:
                raise ValueError("not found filed %s" % (k))

    def __json__(self):
        raise NotImplemented("subclass of Model must implement __json__")

    @classmethod
    def create_table(cls):
        raise NotImplemented("subclass of Model must implement create_table")

class Mapper:

    _local = threading.local()

    """Database Mapper"""
    def __init__(self, model_cls):
         self.model = model_cls
         self.model.__mapper__ = self

    @staticmethod
    def initialize(database):
        if not hasattr(Model, "__database__ "):
            Mapper.__database__ = database

    def execute(self, sql):
        with self.connect() as conn:
            try:
                cursor = conn.cursor()
                cursor.execute(sql)
                conn.commit()
            except sqlite3.Error, e:
                print "SQLite Error: %s" % e.args[0]
                conn.rollback()

    @staticmethod
    def initialized():
        """Returns true if the class variable __database__ has been setted."""
        print Mapper.__database__
        return hasattr(Mapper, "__database__")

    @classmethod
    def connect(cls):
        """create a thread local connection if there isn‘t one yet"""
        # print(‘connect‘,cls)
        if not hasattr(cls._local, ‘conn‘):
            try:
                cls._local.conn = sqlite3.connect(cls.__database__)
                #cls._local.conn.execute(‘pragma integrity_check‘)
                cls._local.conn.row_factory = sqlite3.Row
            except sqlite3.Error, e:
                print "Error %s:" % e.args[0]
        return cls._local.conn

    def create_table(self):
        sql = ‘CREATE TABLE IF NOT EXISTS ‘ + self.model.__tablename__ + ‘ (‘ +             ‘name varchar(50),‘ +             ‘email varchar(20)‘ + ‘)‘

        with self.connect() as conn:
            try:
                cursor = conn.cursor()
                cursor.execute(sql)
                conn.commit()
                print ‘Create table %s‘  % (self.model.__tablename__)
            except sqlite3.Error, e:
                print "SQLite Error: %s" % e.args[0]
                conn.rollback() 

    def drop_table(self):
        sql = ‘DROP TABLE IF EXISTS ‘ + self.model.__tablename__
        print ‘Drop table ‘ + self.model.__tablename__
        self.execute(sql)

    def deleteby(self, paterns=None, **kwargs):
        dels = []
        vals = []
        for k, v in kwargs.iteritems():
            if k in self.model.fields:
                dels.append(k + ‘=?‘)
                vals.append(v)
        sql = ‘DELETE FROM %s WHERE %s‘ % (self.model.__tablename__, ‘ AND ‘.join(dels))
        with self.connect() as conn:
            try:
                cursor = conn.cursor()
                cursor.execute(sql, vals)
                conn.commit()
                return True
            except sqlite3.Error, e:
                print "SQLite Error: %s" % e.args[0]
                conn.rollback()
        return False

    def save(self, model):
        cols = model.fields.keys()
        vals = [getattr(model, c) for c in self.model.fields]
        sql = ‘INSERT INTO ‘ + self.model.__tablename__ +             ‘ (‘  + ‘, ‘.join(cols) + ‘)‘ +             ‘ VALUES (‘ + ‘, ‘ .join([‘?‘] * len(cols)) + ‘)‘
        with self.connect() as conn:
            try:
                cursor = conn.cursor()
                cursor.execute(sql, vals)
                conn.commit()
                print ‘save %s‘ % model
                return True
            except sqlite3.Error, e:
                print "SQLite Error: %s" % e.args[0]
                conn.rollback()
        return False

import db
import unittest
import threading

class  ModelTest(unittest.TestCase):
    """docstring for  ModelTest"""

    def setUp(self):
        class User(db.Model):
            __tablename__ = "users"
            name = db.Field("name", "varchar(50)")
            email = db.Field("email", "varchar(20)", validator=lambda x: 7 < len(x) < 21)

        db.setup_database(‘conf/test.sqlite‘)
        db.bind_mapper(‘UserMapper‘, User)
        db.UserMapper.create_table()
        self.user = User(name=‘test‘, email=‘[email protected]‘)

    def tearDown(self):
        res = db.UserMapper.deleteby(name=self.user.name, email=self.user.email)
        #db.UserMapper.drop_table()
        self.assertEqual(True, res)

    def test_model_save(self):
        self.assertEqual(True, self.user.save())

    def test_mapper_save(self):
        self.assertEqual(True, db.UserMapper.save(self.user))

    def test_in_threads(self):
        n = 10
        ts = []
        for i in range(n):
            t = threading.Thread(target=self.user.save)
            ts.append(t)
        for t in ts:
            t.start()
        for t in ts:
            t.join()

if __name__ == "__main__":
    unittest.main()
 
时间: 2024-10-09 22:00:51

metadata的使用以及简单的orm模式的相关文章

简单的工厂模式

从今天开始 每天进步一点点.开始了解并学习设计模式,就从简单的工厂模式开始吧.... 简单工厂模式(Simple Factory):不利于产生系列产品 简单工厂模式又称静态工厂方法模式.重命名上就可以看出这个模式一定很简单.它存在的目的很简单:定义一个用于创建对象的接口. 在简单工厂模式中,一个工厂类处于对产品类实例化调用的中心位置上,它决定那一个产品类应当被实例化, 如同一个交通警察站在来往的车辆流中,决定放行那一个方向的车辆向那一个方向流动一样. 先来看看它的组成: 1) 工厂类角色:这是本

D2010 RTTI + Attribute 简单实现ORM

还记得David I 今年四月来盛大时,被问及“反射机制能再做得好一点吗?我们想放弃RTTI”,David I 回答“这的确是需要考虑的地方,当然RTTI我们不会放弃的”.(这个白胡子的老哥哥还真很可爱,当年Borland几经起落,唯一能看得顺眼的就是David I). 我还以为RTTI在D2010最多只是改良,炒冷饭而已.没想到,RTTI不仅能反射Public.protected.Private里的信息,还能动态执行该类里的方法,更惊奇的是,还支持Attribute.D2010 New RTT

一个简单的ORM制作(SQL帮助类)

一个简单的ORM制作大概需要以下几个类: SQL执行类 CURD操作类 其他酱油类 先从SQL执行类说起,可能会涉及数据库的迁移等问题,所以需要定义一个接口以方便迁移到其他数据库, 事务没提供命名,若需要命名可修改为可变参数,IHelper代码如下: internal interface IHelper:IDisposable { int ExecuteQuery(string txt, IEnumerable<IDataParameter> ps, bool issp);//用于执行INSE

C#基础笔记---浅谈XML读取以及简单的ORM实现

背景: 在开发ASP.NETMVC4 项目中,虽然web.config配置满足了大部分需求,不过对于某些特定业务,我们有时候需要添加新的配置文件来记录配置信息,那么XML文件配置无疑是我们选择的一个方案之一.下面简单谈谈XML的读取.  一. xml.linq读取xml 1.新建一个data.XML文件 1 <Customers> 2 <Customer> 3 <Name>Frank</Name> 4 <City>成都</City>

大话设计模式之简单的工厂模式

第一章:代码无错就是优-简单的工厂模式 先建立一个计算类Operation Operation.h文件 @interface Operation : NSObject @property(nonatomic,assign)double numberA; @property(nonatomic,assign)double numberB; @end Operation.m文件 @implementation Operation @end 然后分别创建他们的子类Add,Sub,Mul,Div Add

神马是代码简单的cmd模式,这就是!

小狼正在研究 “怎么查找连在一起的同色方块?”算法问题 ,突然感觉我是不是需要一种开发模式,不然感觉自己的代码好乱的. 可能是研究算法吧,导致小狼的思路特别清晰,加上也用了差不多1年的nodejs.seajs,对cmd的api非常清楚,不多说,看代码 用法和seajs的用法一样,符合cmd的模式, var require,define; (function(){ var module={} require=function(name){ return module[name] } define=

简单工厂+策略模式-下

前言: 虽然做了个Demo但是实际应用的时候发现一开始对简单工厂与策略的理解有误差.开始想输入时间和基础数据就根据不同的算法算出来.后来发现不是.其实时间也是计算的数据.真正选择算法的是像固定用户和临时用户.或者说打折促销.根据这个. 深夜食堂 一个在深夜12点到凌晨7点开张的小食店.被大家称谓深夜食堂.菜单上只有一样菜.但是.无论你要点什么.只要老板会做.即使菜单上没有的菜也可以点.所以.客人还真不少呢. 日式滑动的木门被打开.进来的是一个浑身又绿色.有着硬壳的家伙.没错.他是富兰克林.老板,

PowerShell DSC(一)简单的推模式

最近因为公司业务需要一直在学习开源平台的内容,比如OpenStack和Docker等等,看着看着就对puppet和chef产生了一些兴趣,随之顺其自然的就发现其实在Windows平台也有自己原生的自动化运维解决方案,它就是PowerShell DSC(desired state configuration),按照字面理解就是"期望的配置状态",我本人对puppet和chef没有太多深入的研究,但是对比了一下两者与PowerShell DSC的实现机制发现的确是大同小异,在此也不讨论谁先

Java设计模式从精通到入门四 简单工厂方法模式

简单工厂方法模式 属于23中设计模式中创建型类型. 核心思想:工厂提供创建对象的接口,由子类决定实例化哪一个子类. 来源 ? 设计模式之禅中的例子,女娲造人,通过八卦炉来进行造人,没有烧熟的为白人,烧太熟的为黑人,刚好的为黄种人的例子进行程序展示 女娲作为client,八卦炉为工厂类,人类为具体实现类,有皮肤的区别. UML类图 图一 Factory: 工厂类的接口,根据类类型,提供只能创建Human子类,或者子孙类的方法. HumanFactory: 工厂类的具体实现,通过反射获取该对象. H