欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

使用Python的web.py框架實(shí)現(xiàn)類(lèi)似Django的ORM查詢(xún)的教程

 更新時(shí)間:2015年05月02日 15:36:15   作者:diabloneo  
這篇文章主要介紹了使用Python的web.py框架實(shí)現(xiàn)類(lèi)似Django的ORM查詢(xún)的教程,集成的ORM操作數(shù)據(jù)庫(kù)向來(lái)是Python最強(qiáng)大的功能之一,本文則探討如何在web.py框架上實(shí)現(xiàn),需要的朋友可以參考下

Django中的對(duì)象查詢(xún)

Django框架自帶了ORM,實(shí)現(xiàn)了一些比較強(qiáng)大而且方便的查詢(xún)功能,這些功能和表無(wú)關(guān)。比如下面這個(gè)例子:

class Question(models.Model):
  question_text = models.CharField(max_length=200)
  pub_date = models.DateTimeField('date published')


>>> Question.objects.all()
>>> Question.objects.get(pk=1)

從例子可以看出,objects.all和objects.get這些功能都不是在class Question中定義的,可能在其父類(lèi)models.Model中定義,也可能不是。那么我們?cè)趙eb.py中如何實(shí)現(xiàn)這樣的功能呢?(如果你選擇使用SQLAlchemy就不需要自己實(shí)現(xiàn)了)。
實(shí)現(xiàn)
思路

我們注意到Question.objects.all()這樣的調(diào)用是直接訪問(wèn)了類(lèi)屬性objects,并調(diào)用了objects屬性的方法all()。這里objects可能是一個(gè)實(shí)例,也可能是一個(gè)類(lèi)。我個(gè)人認(rèn)為(我沒(méi)看過(guò)Django的實(shí)現(xiàn))這應(yīng)該是一個(gè)實(shí)例,因?yàn)閷?shí)例化的過(guò)程可以傳遞一些表的信息,使得類(lèi)似all()這樣的函數(shù)可以工作。經(jīng)過(guò)分析之后,我們可以列出我們需要解決的問(wèn)題:

  •     需要實(shí)現(xiàn)一個(gè)模型的父類(lèi)Model,實(shí)際的表可以從這個(gè)父類(lèi)繼承以獲得自己沒(méi)有定義的功能。
  •     實(shí)際的模型類(lèi)(比如Question類(lèi))定義后,不實(shí)例話的情況下就要具備objects.all()這樣的查詢(xún)效果。
  • 從上面的需求可以看出,我們需要在類(lèi)定義的時(shí)候就實(shí)現(xiàn)這些功能,而不是等到類(lèi)實(shí)例化的時(shí)候再實(shí)現(xiàn)這些功能。類(lèi)定義的時(shí)候?qū)崿F(xiàn)功能?這不就是metaclass(元類(lèi))做的事情嘛。因此實(shí)現(xiàn)過(guò)程大概是下面這樣的:
  •     實(shí)現(xiàn)一個(gè)Model類(lèi),其綁定方法和表的增、刪、改有關(guān)。
  •     修改Model類(lèi)的元類(lèi)為ModelMetaClass,該元類(lèi)定義的過(guò)程中為類(lèi)增加一個(gè)objects對(duì)象,該對(duì)象是一個(gè)ModelDefaultManager類(lèi)的實(shí)例,實(shí)現(xiàn)了表的查詢(xún)功能。

代碼

都說(shuō)不給代碼就是耍流氓,我還是給吧。說(shuō)明下:使用的數(shù)據(jù)庫(kù)操作都是web.py的db庫(kù)中的接口。

  # -*- coding: utf-8 -*-

  import web

  import config # 自定義的配置類(lèi),可以忽略


  def _connect_to_db():
    return web.database(dbn="sqlite", db=config.dbname)


  def init_db():
    db = _connect_to_db()
    for statement in config.sql_statements:
      db.query(statement)


  class ModelError(Exception):
    """Exception raised by all models.

    Attributes:
      msg: Error message.
    """

    def __init__(self, msg=""):
      self.msg = msg

    def __str__(self):
      return "ModelError: %s" % self.msg


  class ModelDefaultManager(object):
    """ModelManager implements query functions against a model.

    Attributes:
      cls: The class to be managed.
    """

    def __init__(self, cls):
      self.cls = cls
      self._table_name = cls.__name__.lower()

    def all(self):
      db = _connect_to_db()
      results = db.select(self._table_name)
      return [self.cls(x) for x in results]

    def get(self, query_vars, where):
      results = self.filter(query_vars, where, limit=1)
      if len(results) > 0:
        return results[0]
      else:
        return None

    def filter(self, query_vars, where, limit=None):
      db = _connect_to_db()
      try:
        results = db.select(self._table_name, vars=query_vars, where=where,
                  limit=limit)
      except (Exception) as e:
        raise ModelError(str(e))

      return [self.cls(x) for x in results]


  class ModelMetaClass(type):

    def __new__(cls, classname, bases, attrs):
      new_class = super(ModelMetaClass, cls).__new__(cls, classname,
                              bases, attrs)
      objects = ModelDefaultManager(new_class)
      setattr(new_class, "objects", objects)

      return new_class


  class Model(object):
    """Parent class of all models.
    """

    __metaclass__ = ModelMetaClass

    def __init__(self):
      pass

    def _table_name(self):
      return self.__class__.__name__.lower()

    def insert(self, **kargs):
      db = _connect_to_db()
      try:
        with db.transaction():
          db.insert(self._table_name(), **kargs)
      except (Exception) as e:
        raise ModelError(str(e))

    def delete(self, where, using=None, vars=None):
      db = _connect_to_db()
      try:
        with db.transaction():
          db.delete(self._table_name(), where, vars=vars)
      except (Exception) as e:
        raise ModelError(str(e))

    def save(self, where, vars=None, **kargs):
      db = _connect_to_db()
      try:
        with db.transaction():
          db.update(self._table_name(), where, vars, **kargs)
      except (Exception) as e:
        raise ModelError(str(e))

使用

首先定義表對(duì)應(yīng)的類(lèi):

class Users(Model):
  ...

使用就和Django的方式一樣:

>>> user_list = Users.objects.all()

 

相關(guān)文章

最新評(píng)論