django框架之ORM操作

文章介绍了Django框架中如何使用ORM定义表结构,包括常见的字段类型和参数,如CharField、IntegerField等,并展示了如何处理表关系。此外,文章还讨论了数据操作,如连接注册、执行映射以及数据库连接池的设置,以及如何进行单表、一对多、多对多和一对一的数据操作。
摘要由CSDN通过智能技术生成

1.表结构

类的方式定义表

  • 编写类

    from django.db import models
    
    
    class 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
BigIntegerField

DateField  时间
DateTimeField

BooleanField  -> 其实数据库不支持真假,根据SmallIntegerField创造出来出来。 0  1

DecimalField  -> 精确的小数  在钱的表示中使用这个字段

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 models


class 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__.py
    	import pymysql
    	pymysql.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=11
    obj.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的,就是不等于5
    print(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_id
    models.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)
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值