ORM模型

本文探讨了ORM(对象关系映射)模型的概念,以及其在解决数据库操作问题中的作用。以Django为例,展示了ORM如何简化数据库操作,并提供了一个简单的ORM模型实现,利用元类和描述符。文章还分享了如何通过元类动态注入属性,以实现模板类的统一save()接口,旨在帮助理解ORM的原理和应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值