django框架之ORM操作
创始人
2025-05-30 08:42:19

文章目录

  • 1.表结构
    • 1.1 常见字段和参数
      • 1.1.1 字段
      • 1.1.2 参数
    • 1.2 表关系
  • 2.数据操作
    • 2.1 连接 注册
    • 2.2 编写类与执行 映射
    • 2.3 连接数据库
  • 3.连接池
  • 4.数据表操作
    • 4.1 单表操作
    • 4.2 一对多
    • 4.3 多对多
    • 4.4 一对一

1.表结构

类的方式定义表

  • 编写类

    from django.db import modelsclass UserInfo(models.Model):name = models.CharField(max_length=16)age = models.IntegerField()
    
  • 注册app

    INSTALLED_APPS = [# 'django.contrib.admin',# 'django.contrib.auth',# 'django.contrib.contenttypes',# 'django.contrib.sessions',# 'django.contrib.messages','django.contrib.staticfiles','apps.app01.apps.App01Config','apps.app02.apps.App02Config',
    ]
    

1.1 常见字段和参数

1.1.1 字段

CharField  字符串型
SmallIntegerField 整型
IntegerField
BigIntegerFieldDateField  时间
DateTimeFieldBooleanField  -> 其实数据库不支持真假,根据SmallIntegerField创造出来出来。 0  1DecimalField  -> 精确的小数  在钱的表示中使用这个字段

1.1.2 参数

name = models.CharField(verbose_name="姓名", max_length=16)
name = models.CharField(verbose_name="姓名", max_length=16, default="哈哈哈")# 经常查询,速度快(MySQL,https://www.bilibili.com/video/BV15R4y1b7y9)
name = models.CharField(verbose_name="姓名", max_length=16, default="哈哈哈", null=True, blank=True, db_index=True)  #索引
email = models.CharField(verbose_name="姓名", max_length=16, default="哈哈哈", null=True, blank=True, unique=True)  #唯一
# blank和null的区别
# https://blog.csdn.net/qq_39253370/article/details/109717356
# 在数据库存储时只能是:sh、bj (上海、北京一般用于页面显示中文)
code = models.CharField(verbose_name="姓名", max_length=16, choices=(("sh", "上海"), ("bj", "北京")),default="sh")
# 不用 max_length=16
count = models.IntegerField(verbose_name="数量", default=1, null=True, blank=True, unique=True)
code = models.IntegerField(verbose_name="性别",choices=((1, "男"), (2, "女")),default=1)
register_date = models.DateField(verbose_name="注册时间", auto_now=True)
amount = models.DecimalField(verbose_name="余额", max_digits=10, decimal_places=2)

示例:

from django.db import modelsclass UserInfo(models.Model):name = models.CharField(verbose_name="姓名", max_length=16, db_index=True)age = models.PositiveIntegerField(verbose_name="年龄")email = models.CharField(verbose_name="邮箱", max_length=128, unique=True)amount = models.DecimalField(verbose_name="余额", max_digits=10, decimal_places=2, default=0)register_date = models.DateField(verbose_name="注册时间", auto_now=True)class Goods(models.Model):title = models.CharField(verbose_name="标题", max_length=32)# detail = models.CharField(verbose_name="详细信息", max_length=255)detail = models.TextField(verbose_name="详细信息")price = models.PositiveIntegerField(verbose_name="价格")count = models.PositiveBigIntegerField(verbose_name="库存", default=0)

1.2 表关系

  • 单表
  • 一对多
  • 多对多
  • 一对一

2.数据操作

2.1 连接 注册

编写ORM操作的步骤:

  • settings.py,连接数据库

    DATABASES = {'default': {'ENGINE': 'django.db.backends.sqlite3','NAME': BASE_DIR / 'db.sqlite3',}
    }
    
  • settings.py,注册app

    INSTALLED_APP = [..."app01.apps.App01Config"
    ]
    

2.2 编写类与执行 映射

  • 编写models.类

    class UserInfo(models.Model):.........
    
  • 执行命令

    python manage.py makemigrations    # 找到所有已注册的app中的models.py中的类读取 -> migrations配置
    python manage.py migrate           # 读取已注册的app下的migrations配置 -> SQL语句  -> 同步数据库
    

2.3 连接数据库

sqlites:

DATABASES = {'default': {'ENGINE': 'django.db.backends.sqlite3','NAME': BASE_DIR / 'db.sqlite3',}
}

mysql

DATABASES = {'default': {'ENGINE': 'django.db.backends.mysql','NAME': 'xxxxxxxx',  # 数据库名字'USER': 'root','PASSWORD': 'root123','HOST': '127.0.0.1',  # ip'PORT': 3306,}
}

安装第三方组件

  • pymysql

    pip install pymysql
    
    项目根目录/项目名目录/__init__.pyimport pymysqlpymysql.install_as_MySQLdb()
    
  • mysqlclient

    pip install mysqlclient
    
    电脑上先提前安装MySQL。
    

3.连接池

django默认内置没有数据库连接池 。

pymysql   -> 操作数据库
DBUtils   -> 连接池

https://pypi.org/project/django-db-connection-pool/

pip install django-db-connection-pool
DATABASES = {"default": {'ENGINE': 'dj_db_conn_pool.backends.mysql','NAME': 'day04',  # 数据库名字'USER': 'root','PASSWORD': 'root123','HOST': '127.0.0.1',  # ip'PORT': 3306,'POOL_OPTIONS': {'POOL_SIZE': 10,  # 最小'MAX_OVERFLOW': 10,  # 在最小的基础上,还可以增加10个,即:最大20个。'RECYCLE': 24 * 60 * 60,  # 连接可以被重复用多久,超过会重新创建,-1表示永久。'TIMEOUT':30, # 池中没有连接最多等待的时间。}}
}

注意:组件django-db-connection-pool不是特别厉害。拿了另外一个支持SQLAchemy数据库连接池的组件。

4.数据表操作

4.1 单表操作

单表增删改查:
关键字:

  • 增加:create
  • 删除:delete
  • 更新:update
  • 条件:filter
  • 查看部分所有和单个:all() first
  • query:查看对应的sql语句
    举例练习:
class Role(models.Model):title = models.CharField(verbose_name='标题',max_length=32)od = models.IntegerField(verbose_name="排序")def __str__(self):return "{}-{}".format(self.title,self.od)

新增行:

 obj1 = models.Role.objects.create(title='alex',od=1)obj2 = models.Role.objects.create(**{"title":"管理员","od":2})models.Role.objects.create(title='lcy',od=8)models.Role.objects.create(title='lll',od=11)obj = models.Role(title='mmm',od=12)obj.od=11obj.save()

删除与更改:

	obj = models.Role.objects.filter(title='alex').delete()print(obj)obj1 = models.Role.objects.all().update(od=99,title='管理员')models.Role.objects.filter(id=3).update(**{"title":'mm','od':22})# 可以通过关键字传参或者传一个字典

条件查询:

	v2 = models.Role.objects.filter(od__lt=99)  #双下划线加条件的用法v2 = models.Role.objects.filter(od__in=[8,11,3])v2 = models.Role.objects.filter(title__contains='y')v2 = models.Role.objects.filter(title__startswith='l')v2 = models.Role.objects.filter(title__isnull=False)v2 = models.Role.objects.exclude(id=5).filter(od=11)  # 表示不等于  出去id=5的,就是不等于5print(v2.query)for obj in v2:print(obj)

values和values_list

    v4 = models.Role.objects.filter(id__gt=2).values('id','title')  #获取到的是列表#print(v4.queryset)print(v4)v5 = models.Role.objects.filter(id__gt=2).values_list('id','title') #获取到 的是元组print(v5)v6 = models.Role.objects.filter(id__gt=2).values('id','title')  #.first()print(v6.query)   # 这样可以得到生成的sql语句,但是加上first就不可以了,那样得到的是具体的值print(v6)v6 = models.Role.objects.filter(id__gt=2).values('id', 'title').first()print(v6.query)print(v6)
  • 排序
	v6 = models.Role.objects.filter(od__gt=22).exists() # 查看是否存在print(v6)v7 = models.Role.objects.order_by('-id','od') # 排序 加-代表是desc方式,如果不加代表asc方式print(v7)

4.2 一对多

一对多联表查询:

class Depart(models.Model):title = models.CharField(max_length=32)class Admin(models.Model):name = models.CharField(max_length=32)pwd = models.CharField(max_length=32)depart = models.ForeignKey(to="Depart",on_delete=models.CASCADE)

映射到表内是这样的:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
可以看到,虽然class内定义的是depart,但是反应在表内的结果确实depart_id,直接通过depart_id是能够对应到depart表内的id列的。
以上两个为部门表和人员表
添加数据:

	models.Depart.objects.create(title='销售')models.Depart.objects.create(title='开发')models.Depart.objects.create(title='财务')#虽然这里写的是depart,但是因为外键的缘故,生成出来就是depart_idmodels.Admin.objects.create(name='lcy',pwd='123',depart_id=2)models.Admin.objects.create(name='lll',pwd='234',depart_id=1)models.Admin.objects.create(name='武沛齐',pwd='12345',depart_id=3)# 以上方式最简便,因为默认两个表通过外键相连的obj = models.Depart.objects.filter(id=2).first()models.Admin.objects.create(name='lcyyy',pwd='123',depart=obj)models.Admin.objects.create(name='lcy12',pwd='123',depart_id=obj.id)# 以上三种方式均能实现添加id并且与depart相连

查询:

# 通过depart_id可以连接到本表内的depart_id字段,通过depart__title可以连接到depart表内的title字段,其余字段相同v6 = models.Admin.objects.filter(depart__title='开发').all().values()print(v6)
#    因为已经联表了,所以可以通过depart__字段  连表和条件v6 = models.Admin.objects.filter(depart__title='销售').delete()print(v6.query)v7 = models.Admin.objects.filter(depart__title='销售')print(v7.query)v1 = models.Admin.objects.filter(id__gt=0)for obj in v1:print(obj.id,obj.name,obj.pwd,obj.depart_id)v2 = models.Admin.objects.filter(id__gt=0).select_related("depart")for obj in v2:print(obj.name, obj.pwd, obj.id, obj.depart_id, obj.depart.title)v3 = models.Admin.objects.filter(id__gt=0).values('id','name','pwd','depart_id','depart__title')print(v3)

4.3 多对多

class Boy(models.Model):name = models.CharField(max_length=10,db_index=True)class Girl(models.Model):name = models.CharField(max_length=10,db_index=True)class B2G(models.Model):bid = models.ForeignKey(verbose_name="男生id",to='Boy',to_field='id',null=True,on_delete=models.CASCADE)gid = models.ForeignKey(verbose_name='女生id',to='Girl',to_field='id',null=True,on_delete=models.CASCADE)address = models.CharField(verbose_name='地点',max_length=32,null=True)
  • 添加数据 与单次添加多个数据
	models.Boy.objects.create(name='宝强')models.Boy.objects.create(name='羽凡')models.Boy.objects.create(name='乃亮')models.Girl.objects.create(name='马蓉')models.Girl.objects.create(name='小路')models.Girl.objects.create(name='百合')models.Girl.objects.bulk_create(objs = [models.Girl(name='苍井空'),models.Girl(name='椎名由奈'),models.Girl(name='神波多一花')],batch_size=3,)models.B2G.objects.create(bid_id=1,gid_id=1,address='bj')models.B2G.objects.bulk_create(objs = [models.B2G(bid_id=1,gid_id=3,address='sh'),models.B2G(bid_id=2,gid_id=8,address='jan'),models.B2G(bid_id=3,gid_id=9,address='tj'),],batch_size = 3,)
  • 查询数据
 	v1 = models.B2G.objects.filter(bid__name='宝强').select_related('gid')# 因为连表了,所以可以执行联查print(v1.query)# SELECT `asserts_b2g`.`id`, `asserts_b2g`.`bid_id`, `asserts_b2g`.`gid_id`, `asserts_b2g`.`address`, `asserts_girl`.`id`, `asserts_girl`.`name` FROM `asserts_b2g` INNER JOIN `asserts_boy` ON (`asserts_b2g`.`bid_id` = `asserts_boy`.`id`) LEFT OUTER JOIN `asserts_girl` ON (`asserts_b2g`.`gid_id` = `asserts_girl`.`id`) WHERE `asserts_boy`.`name` = 宝强for v in v1:print(v.id,v.address,v.bid.name,v.gid.name)
# 与一对多相同,可以通过双下划线实现取出其他表中的字段v2 = models.B2G.objects.filter(bid__name='宝强').values('bid__name','gid__name','address')print(v2)v3 = models.B2G.objects.filter(gid__name='神波多一花').values('bid__name','gid__name','address')print(v3)

4.4 一对一

class UserInfo(models.Model):name = models.CharField(max_length=32,db_index=True)pwd = models.CharField(max_length=32)class Blog(models.Model):user = models.OneToOneField(max_length=32,to='UserInfo',on_delete=models.CASCADE)blog = models.CharField(verbose_name="博客地址",max_length=255)summary = models.CharField(verbose_name="简介",max_length=128)
  • 添加数据
	models.UserInfo.objects.create(name='武沛齐',pwd='12345')models.UserInfo.objects.create(name='lcy',pwd='12345')models.Blog.objects.create(blog='xxxx1',summary='mmmmm',user_id=1)#models.Blog.objects.create(blog='xxx2',summary='nnnn',user_id=2)user_object = models.UserInfo.objects.filter(name='lcy').first()models.Blog.objects.create(blog='yyyy1',summary='nnnnn',user=user_object)

查询

	user_object = models.UserInfo.objects.filter(name='lcy').select_related('blog').first()print(user_object.id,user_object.name,user_object.pwd,user_object.blog.blog,user_object.blog.summary)blog_object = models.Blog.objects.filter(id=1).select_related('user').first()print(blog_object.blog,blog_object.summary,blog_object.user.name,blog_object.user.pwd)

相关内容

热门资讯

重大通报“金州水鱼究竟有没有挂... 您好:金州水鱼这款游戏可以开挂,确实是有挂的,需要软件加微信【5951795】,很多玩家在金州水鱼这...
科普实测“微乐四川麻将能不能开... 您好:微乐四川麻将这款游戏可以开挂,确实是有挂的,需要软件加微信【69174242】,很多玩家在微乐...
科技通报“66红中麻将究竟是有... 亲.66红中麻将这款游戏是可以开挂的,确实是有挂的,通过添加客服【4830828】很多玩家在这款游戏...
重大消息.科尔沁麻将有挂吗.(... 重大消息.科尔沁麻将有挂吗.(原来真的有挂)亲.科尔沁麻将这款游戏是可以开挂的,确实是有挂的,通过添...
重大通报“樱花之盛到底是有挂吗... 您好:【樱花之盛】这款游戏可以开挂,确实是有挂的,需要了解加客服微信【6670747】很多玩家在这款...