Ứng Dụng Meta Class Trong ORM

Meta Class và Thực Hiện ORM

1. Các Lớp Cũng Là Đối Tượng

Trong Python, lớp (class) không chỉ là một khối mã mà còn là một đối tượng thực sự. Điều này có nghĩa là bạn có thể gán lớp cho biến, sao chép nó, thêm thuộc tính vào nó, hoặc truyền nó như một tham số hàm.

Ví dụ:

<div>
<pre>
&lt;code&gt;
class ChuTaoDoiTuong:
    pass

doi_tuong = ChuTaoDoiTuong()
print(doi_tuong)
# Output: &lt;__main__.ChuTaoDoiTuong object at 0x...&gt;

def inLop(lop):
    print(lop)

inLop(ChuTaoDoiTuong)
# Output: &lt;class '__main__.ChuTaoDoiTuong'&gt;
&lt;/code&gt;
</pre>
</div>

2. Tạo Lớp Động

Bạn có thể tạo lớp động trong thời gian chạy bằng cách sử dụng hàm type. Ví dụ:

<div>
<pre>
&lt;code&gt;
def taoLop(ten):
    if ten == 'loaiA':
        class LoaiA:
            pass
        return LoaiA
    else:
        class LoaiB:
            pass
        return LoaiB

lop = taoLop('loaiA')
print(lop)
# Output: &lt;class '__main__.LoaiA'&gt;
&lt;/code&gt;
</pre>
</div>

3. Sử Dụng type Để Tạo Lớp

Hàm type có thể được dùng để tạo lớp với các thông tin như tên lớp, danh sách các lớp cha, và một từ điển chứa các thuộc tính.

<div>
<pre>
&lt;code&gt;
Test = type("Test", (), {})
print(Test())
# Output: &lt;__main__.Test object at 0x...&gt;
&lt;/code&gt;
</pre>
</div>

4. Tạo Lớp Với Thuộc Tính Và Phương Thức

Bạn có thể thêm thuộc tính và phương thức vào lớp khi tạo chúng bằng type.

<div>
<pre>
&lt;code&gt;
def hienThiThuocTinh(self):
    print(self.thuocTinh)

LopCoPhuongThuc = type('LopCoPhuongThuc', (), {'thuocTinh': True, 'hienThiThuocTinh': hienThiThuocTinh})
doiTuong = LopCoPhuongThuc()
doiTuong.hienThiThuocTinh()
# Output: True
&lt;/code&gt;
</pre>
</div>

5. Meta Class Là Gì?

Meta class là "lớp của lớp". Chúng được sử dụng để tạo ra các lớp khác. Ví dụ, type chính là meta class mặc định của Python.

<div>
<pre>
&lt;code&gt;
class LopGoc(object):
    __metaclass__ = type  # Định nghĩa meta class

class Con(LopGoc):
    pass
&lt;/code&gt;
</pre>
</div>

6. Sử Dụng Meta Class Để Tạo ORM

ORM (Object-Relational Mapping) giúp ánh xạ giữa đối tượng và cơ sở dữ liệu quan hệ. Một ví dụ đơn giản về việc sử dụng meta class để tạo ORM như sau:

<div>
<pre>
&lt;code&gt;
class MetaclassModel(type):
    def __new__(cls, ten_lop, cac_lop_cha, thuoc_tinh):
        mapping = {}
        for k, v in thuoc_tinh.items():
            if isinstance(v, tuple):
                mapping[k] = v
        for k in mapping.keys():
            del thuoc_tinh[k]
        thuoc_tinh['__mapping__'] = mapping
        thuoc_tinh['__ten_bang__'] = ten_lop
        return super().__new__(cls, ten_lop, cac_lop_cha, thuoc_tinh)

class Model(metaclass=MetaclassModel):
    def __init__(self, **kwargs):
        for ten, gia_tri in kwargs.items():
            setattr(self, ten, gia_tri)

    def luu(self):
        truong = []
        gia_tri = []
        for k, v in self.__mapping__.items():
            truong.append(v[0])
            gia_tri.append(getattr(self, k, None))
        gia_tri_temp = [str(x) if isinstance(x, int) else f"'{x}'" for x in gia_tri]
        cau_lenh_sql = f"INSERT INTO {self.__ten_bang__} ({','.join(truong)}) VALUES ({','.join(gia_tri_temp)})"
        print(cau_lenh_sql)

class NguoiDung(Model):
    id_nguoi_dung = ('id', 'int unsigned')
    ten = ('ten', 'varchar(30)')
    email = ('email', 'varchar(30)')
    mat_khau = ('mat_khau', 'varchar(30)')

nguoi_dung = NguoiDung(id_nguoi_dung=123, ten='Michael', email='test@orm.org', mat_khau='my-pwd')
nguoi_dung.luu()
# Output: INSERT INTO NguoiDung (id,ten,email,mat_khau) VALUES (123,'Michael','test@orm.org','my-pwd')
&lt;/code&gt;
</pre>
</div>

7. Hoàn Thiện Kiểm Tra Loại Dữ Liệu

Có thể cải thiện thêm bằng cách kiểm tra loại dữ liệu trước khi tạo câu lệnh SQL.

<div>
<pre>
&lt;code&gt;
class MetaclassModel(type):
    def __new__(cls, ten_lop, cac_lop_cha, thuoc_tinh):
        mapping = {}
        for k, v in thuoc_tinh.items():
            if isinstance(v, tuple):
                mapping[k] = v
        for k in mapping.keys():
            del thuoc_tinh[k]
        thuoc_tinh['__mapping__'] = mapping
        thuoc_tinh['__ten_bang__'] = ten_lop
        return super().__new__(cls, ten_lop, cac_lop_cha, thuoc_tinh)

class Model(metaclass=MetaclassModel):
    def __init__(self, **kwargs):
        for ten, gia_tri in kwargs.items():
            setattr(self, ten, gia_tri)

    def luu(self):
        truong = []
        gia_tri = []
        for k, v in self.__mapping__.items():
            truong.append(v[0])
            gia_tri.append(getattr(self, k, None))
        gia_tri_temp = [str(x) if isinstance(x, int) else f"'{x}'" for x in gia_tri]
        cau_lenh_sql = f"INSERT INTO {self.__ten_bang__} ({','.join(truong)}) VALUES ({','.join(gia_tri_temp)})"
        print(cau_lenh_sql)

class NguoiDung(Model):
    id_nguoi_dung = ('id', 'int unsigned')
    ten = ('ten', 'varchar(30)')
    email = ('email', 'varchar(30)')
    mat_khau = ('mat_khau', 'varchar(30)')

nguoi_dung = NguoiDung(id_nguoi_dung=123, ten='Michael', email='test@orm.org', mat_khau='my-pwd')
nguoi_dung.luu()
# Output: INSERT INTO NguoiDung (id,ten,email,mat_khau) VALUES (123,'Michael','test@orm.org','my-pwd')
&lt;/code&gt;
</pre>
</div>

Thẻ: python MetaClass orm TypeFunction

Đăng vào ngày 23 tháng 5 lúc 08:35