单独立使用Django ORM
一、常用的ORM框架简介
在Python
下的ORM
库不少,同样介绍类似的博文也不少,但是是我非常规的用法,顺便做做笔记。这里参考Python 常用的ORM框架简介文章列出几个, 这个几个我都使用过,但是我还是更喜欢Django ORM
, 被它的API惯坏了再也不想使用别的了,于是有种数据库操作都想用它的想法,所以才有了这篇笔记。
Django‘s ORM
是紧嵌到web框架的ORM,一个最流行的Python web框架, 有它独有的ORM。 相比 SQLAlchemy, Django 的 ORM 更吻合于直接操作SQL对象,操作暴露了简单直接映射数据表和Python类的SQL对象, 接口丰富易用 。优点:易用,学习曲线短 和Django紧密集合,用Django时使用约定俗成的方法去操作数据库
缺点:不好处理复杂的查询,强制开发者回到原生SQL紧密和Django集成,使得在Django环境外很难使用peewee
整个库是单个文件, 看源码费劲(我个人偏见了)优点:Django式的API,使其易用 轻量实现,很容易和任意web框架集成
缺点:不支持自动化 schema 迁移 多对多查询写起来不直观SQLAlchemy
采用了数据映射模式,其工作单元 主要使得 有必要限制所有的数据库操作代码到一个特定的数据库session,在该session中控制每个对象的生命周期 。优点:企业级 API,使得代码有健壮性和适应性灵活的设计,使得能轻松写复杂查询
缺点:工作单元概念不常见 重量级 API,导致长学习曲线
二、单独使用Django ORM功能
而这篇笔记的主角是Django
的ORM
, 它一般都是在web项目上使用的, 很少有领出来单独使用的,这里就提炼出一个小的Demo
展示独立使用Django ORM
, 即非Web项目上使用ORM
, 代码目录接口如下:
1.目录结构
│ demox.py │ main.py │ ├─django_orm │ │ settings.py │ │ __init__.py │ │ │ ├─app01 │ │ │ models.py │ │ │ __init__.py
2.用代码main.py
在入口处配置Django的设置文件系统环境变量DJANGO_SETTINGS_MODULE
值为设置文件的目录django_orm.settings
, 这取值跟目录结构有关,加载Django ORM 是读取配和这个配置问文件。
import os # 行是必须的 os.environ.setdefault("DJANGO_SETTINGS_MODULE", "django_orm.settings") from django_orm import migrate, make_migrations from django_orm.app01 import models from demox import do_demo import time import random import threading def update(): while True: try: obj = models.User.objects.first() obj.name = obj.name + 1 obj.save() print("update:", object) # time.sleep(random.random()*0.5) except Exception as err: print("update:", "-" * 40) print(err) break def create(): while True: try: obj = models.User.objects.create(name=random.randint(0, 100)) print("create:", obj) # time.sleep(random.random() * 0.5) except Exception as err: print("create:", "-" * 40) print(err) def select(): while True: try: print("select:", models.User.objects.all()[:5]) # time.sleep(0.5) except Exception as err: print("select:", "-" * 40) print(err) break def delete(): while True: try: obj = models.User.objects.first() print("delete:", obj) obj.delete() # time.sleep(0.5) except Exception as err: print("delete:", "-" * 40) print(err) break if __name__ == '__main__': do_demo() make_migrations("app01") migrate("app01") u = models.User.objects.create(name=2) u.save() print(len(models.User.objects.all())) # # threading.Thread(target=update).start() # # threading.Thread(target=create).start() threading.Thread(target=select).start() # # threading.Thread(target=delete).start()
3. 应用的models
方便管理创建一个目录django_orm专门放置Django models
项目的数据库表结构文件, 目录__init__.py
文件中把所有的app加载到Django里, 并提供migrate
和make_migrations
方法用于数据库迁移。
from django.apps import apps from django.conf import settings from django.core.management import call_command apps.populate(settings.INSTALLED_APPS) print("----------apps.populate----------") def migrate(app_name: str): call_command("migrate", app_name) def make_migrations(app_name: str): call_command("makemigrations", app_name)
settings.py
配置文件,即在main.py 最开始的入口加载的系统环境变量值
# !/usr/bin/env python # -*- coding: utf-8 -*- # # @project : demo2 # @file : settings.py # @time : 2019/11/8 22:28 # @author : GuangLin # @version : 0.01 # @desc : """ Django settings for demo2 project. Generated by 'django-admin startproject' using Django 2.1. For more information on this file, see https://docs.djangoproject.com/en/2.1/topics/settings/ For the full list of settings and their values, see https://docs.djangoproject.com/en/2.1/ref/settings/ """ import os import sys # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.insert(0, os.path.join(BASE_DIR, "..")) print(__file__) print(BASE_DIR) print(os.path.join(BASE_DIR, 'db.sqlite3')) # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/2.1/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = 'lyv+won7%7!=ra!nc160o-x1yz+m%n1jxm)wtw_y1r3%%' # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True # Application definition INSTALLED_APPS = [ 'django_orm.app01', ] # Database # https://docs.djangoproject.com/en/2.1/ref/settings/#databases DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), } }
app01/models.py
应用表结构
from django.db import models class User(models.Model): name = models.CharField(max_length=10)
在实践实用中发现Sqlite3在多线程下会锁库,这个是Sqlite内部机制导致的,在Peewee和裸跑多线程也是一样的锁库,特别是配置低的机器下,IO读写速度慢的时候。处理的机制是db操作放到独立的线程下操作,下篇笔记里记录。