类的方式定义表
编写类
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',
]
CharField 字符串型
SmallIntegerField 整型
IntegerField
BigIntegerFieldDateField 时间
DateTimeFieldBooleanField -> 其实数据库不支持真假,根据SmallIntegerField创造出来出来。 0 1DecimalField -> 精确的小数 在钱的表示中使用这个字段
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)
编写ORM操作的步骤:
settings.py,连接数据库
DATABASES = {'default': {'ENGINE': 'django.db.backends.sqlite3','NAME': BASE_DIR / 'db.sqlite3',}
}
settings.py,注册app
INSTALLED_APP = [..."app01.apps.App01Config"
]
编写models.类
class UserInfo(models.Model):.........
执行命令
python manage.py makemigrations # 找到所有已注册的app中的models.py中的类读取 -> migrations配置
python manage.py migrate # 读取已注册的app下的migrations配置 -> SQL语句 -> 同步数据库
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。
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数据库连接池的组件。
单表增删改查:
关键字:
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)
一对多联表查询:
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)
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)
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)