ORM模型
文章目录
前言
ORM是三个单词首字母组合而成,包含了Object(对象-类),Relations(关系),Mapping(映射)。解释过字面意思,但ORM的概念仍然模糊。私以为要理解一个事物,最好的法子是搞明白它出现是为了解决什么问题。
然而,ORM是否应该存在仍被许多程序员争论着。我所实习的公司,项目组负责封装数据层抽象出接口的程序员也为此跟leader激烈讨论过。我同他持相同观点,即:过于复杂的sql操作不应该让ORM代为实现,原生sql会让代码简单,目的明确。离开复杂的“层次”,代码也易维护。
显然,上面一段话是在说ORM不适合的场景。那它的对立面,也就是ORM大展拳脚的领域了。当项目中的sql语句比较简单,复用率大,映射关系清晰,通过ORM避开sql语句的直接使用,其实是不错选择。
Django中的ORM
在Django中,有现成的ORM模型,利用它,往数据库写东西变得简洁。我在models.py文件做了如下定义:
from django.db import models
class Student(models.Model):
# db_column 指定列名
name = models.CharField(db_column="NAME", max_length=20)
age = models.IntegerField(db_column="AGE")
class Meta:
db_table = "student" # 指定表名
然后执行两个命令。第一个是生成迁移文件,第二个是执行迁移文件:
python manage.py makemigrations
python manage.py migrate
此时查看数据库,发现student表已经创建好了(Django会默认创建id列)。
mysql> show tables;
+----------------------------+
| Tables_in_model |
+----------------------------+
| ...... |
| student |
+----------------------------+
11 rows in set (0.00 sec)
mysql> desc student;
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| NAME | varchar(20) | NO | | NULL | |
| AGE | int(11) | NO | | NULL | |
+-------+-------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)
现在利用Django提供的接口,向数据库写入数据。
>>> from studymodel.models import Student
>>> stu = Student()
>>> stu.name = "zty"
>>> stu.age = 19
>>> stu.save()
一个简单的ORM模型
体验过Django中的ORM后,发现模板类操作数据库在一定环境下确实带来了方便。事实上,我们也可以通过元类来实现自己的ORM。下面将涉及两个知识点:元类,描述符。因为已经在《元类》和《属性描述符》中总结过了,后面不再细述。
首先,完成属性描述符的设计:
class Field(object):
pass
class IntegerField(Field):
def __init__(self, col=None, minvalue=None, maxvalue=None):
self._value = None
self.col = col
if not isinstance(maxvalue, numbers.Integral):
raise ValueError("'maxvalue'需要一个整数")
self.maxvalue = maxvalue or 100
if not isinstance(minvalue, numbers.Integral):
raise ValueError("'minvalue'需要一个整数")
self.minvalue = minvalue or 0
def __get__(self, instance, owner):
return self._value
def __set__(self, instance, value):
if not isinstance(value, numbers.Integral):
raise ValueError("'age'需要一个整数")
if not self.minvalue < value &l