web.py에서 Django의 ORM과 유사한 조회 효과 구현

5140 단어 pythonweb.py
Django의 객체 질의
Django 프레임워크는 ORM을 자체로 가지고 비교적 강력하고 편리한 조회 기능을 실현했는데 이런 기능들은 표와 무관하다.예를 들면 다음과 같습니다.
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.allobjects.get 이런 기능들은 모두 class Question에서 정의된 것이 아니라 부류models.Model에서 정의된 것일 수도 있고 아닐 수도 있다.그럼 저희는 웹에서.py에서 어떻게 이런 기능을 실현합니까?(만약 당신이 SQLAlchemy를 선택한다면 스스로 실현할 필요가 없다).
이루어지다
사고의 방향
우리는 Question.objects.all() 이러한 호출은 클래스 속성objects에 직접 접근하고 objects 속성을 호출하는 방법all()을 발견했다.여기objects는 실례일 수도 있고 종류일 수도 있다.저는 개인적으로 (저는 Django의 실현을 본 적이 없습니다) 이것은 실례가 되어야 한다고 생각합니다. 실례화된 과정은 표의 정보를 전달할 수 있기 때문에 유사all()와 같은 함수가 작동할 수 있기 때문입니다.분석을 거친 후에 우리는 우리가 해결해야 할 문제를 열거할 수 있다.
  • 는 하나의 모델의 부류Model를 실현해야 한다. 실제 표는 이 부류로부터 자신이 정의하지 않은 기능을 계승할 수 있다.
  • 실제 모델 클래스(예를 들어Question 클래스)를 정의한 후 실례가 없는 상황에서objects.all()와 같은 조회 효과를 갖추어야 한다.

  • 위의 수요를 통해 알 수 있듯이 우리는 클래스가 정의될 때 이러한 기능을 실현해야 한다. 클래스가 실례화될 때까지 기다렸다가 이런 기능을 실현해야 한다.클래스 정의를 할 때 기능을 실현합니까?메타클래스가 하는 일이잖아.따라서 실현 과정은 다음과 같다.
  • 하나Model류를 실현하는데 그 귀속 방법은 표의 증가, 삭제, 수정과 관련이 있다.
  • 수정Model류의 원류는 ModelMetaClass이고 이 원류의 정의 과정에서 클래스에 objects 대상을 추가했다. 이 대상은 ModelDefaultManager류의 실례로 표의 조회 기능을 실현했다.

  • 코드
    코드를 안 주면 깡패라니까 내가 줄게.설명: 사용하는 데이터베이스 조작은 모두 웹입니다.py의db 라이브러리의 인터페이스입니다.
        # -*- coding: utf-8 -*-
        
        import web
        
        import config  #        ,    
        
        
        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))

    사용
    먼저 테이블에 해당하는 클래스를 정의합니다.
    class Users(Model):
        ...
        

    다음과 같이 Django를 사용합니다.
    user_list = Users.objects.all()

    좋은 웹페이지 즐겨찾기