ORM数据库操作

ORM操作关键字

        ORM就是为了让不会数据库操作的python程序员也能够操作数据库处理数据,而处理数据无非就是对数据的增、删、改、查,因此ORM给我们提供了各种操作数据的关键字

         先创建一张表用于举例

class User(models.Model):
    uid = models.AutoField(primary_key=True, verbose_name='编号')
    name = models.CharField(max_length=32, verbose_name='姓名')
    age = models.IntegerField(verbose_name='年龄')
    join_time = models.DateField(auto_now_add=True)

1.模型层测试环境准备

        方式一:在任意空的py文件中准备环境

import os
def main():
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'day59.settings')
    import django
    django.setup()

if __name__ == '__main__':
    main()

2.常见关键字

create():创建数据 返回值就是当前创建的数据对象

update():更新数据

delete():删除数据

'添加数据'
models.User.objects.create('小明','18')
models.User.objects.create('小强','26')
models.User.objects.create('小红','38')
models.User.objects.create('小兰','66')
'修改id为2的年龄'
models.User.objects.filter(pk=2).update(age=88)
'删除id为3的数据'
models.User.objects.filter(pk=3).delete()

常见的13个查询关键字:

filter():返回值是一个QuerySet(可以看成是列表套数据对象)

res = models.User.objects.filter(name='小明', age=18)
'''
括号内可以填写多个条件 逗号分开默认是and关系
括号内不写查询条件 默认查询所有
'''

all():查询所有数据 返回值是一个QuerySet(可以看成是列表套数据对象)

res = models.User.objects.all()
print(res[1])
for i in res:
    print(i)

'''
可以索引获取每个数据对象
也可以用for循环获取
'''

first():获取Queryset中第一个数据对象 如果是空则返回None

res = models.User.objects.filter(name="小明").first()
print(res)

last():获取Queryset中最后一个数据对象 如果是空则返回None

res = models.User.objects.filter(name="小明").last()
print(res)

get():直接根据条件查询具体的数据对象  如果条件不存在直接报错(不推荐使用)

res = models.User.objects.get(pk=999)
print(res)
'''
显然没有id为999的值所以会直接报错
更推荐下面这种方式
'''
res = models.User.objects.filter(pk=999).first()
print(res)
# 不存在返回None

values():指定查询字段 结果是Queryset(可以看成是列表套字典数据)

res = models.User.objects.all().values('name', 'age')
print(res)
'''
获取别中所有数据的'name','age'字段数据
'''

values_list():指定查询字段 结果是Queryset(可以看成是列表套元组数据)

res = models.User.objects.values_list('name','join_time')
print(res)

order_by():指定字段排序 默认是升序 在字段前加负号则为降序 并且支持多个字段排序

res = models.User.objects.order_by('age') # 按年龄升序

res = models.User.objects.order_by('-age') # 按年龄降序

res = models.User.objects.order_by('age','-join_time') 
# 先按年龄升序有相同的年龄再按创建时间降序

count():统计ORM查询之后结果集中的数据格式

res = models.User.object.all().count()

distinct():针对重复的数据进行去重 (注意数据对象中的主键)

res = models.User.objects.values('name','join_time').distinct()
print(res)
'''
避免主键因为主键肯定是不重复的数据
'''

exclude():针对括号内的条件取反进行数据查询(QuerySet可以看成是列表套数据对象)

res = models.User.objects.exclude(pk=1)
print(res)
'''
查询除id是1以为的所有数据
'''

reverse():针对已经排序了的结果集做颠倒

res = models.User.objects.all().order_by('age').reverse()
print(res)
'''
将按年龄升序完后的数据再取个反,倒叙一下
'''

existe():判断查询结果是否有数据, 返回布尔值(几乎所有数据都已自带布尔值了)

res = models.User.objects.filter(pk=999).exists()
print(res)
'''
判断查询结果 True/False
'''

raw():执行SQL语句

res = models.User.objects.raw('select * from app01_user')
print(res)
'''
注意要用生成的app01_user表
也可以用另一种方法:在配置文件中加
from django.db import connection  
cursor = connection.cursor()  
cursor.execute("insert into hello_author(name) VALUES ('郭敬明')") 
cursor.execute("update hello_author set name='韩寒' WHERE name='郭敬明'")  
cursor.execute("delete from hello_author where name='韩寒'")  
cursor.execute("select * from hello_author")  
cursor.fetchone()  
cursor.fetchall()
'''    

双下划线查询

1.比较运算符

'''
字段__gt        大于
字段__lt        小于
字段__gte       大于等于
字段__lte       小于等于
'''
# 举例:
res = models.User.objects.filter(age__gt=20)
# 查询年龄大于20的数据,换成__gte则是查询小于等于
res1 = models.User.objects.fileter(age__lt=20)
# 查询年龄小于20的数据,换成__lte则是查询小于等于

2.日期处理

'''
字段__year        年
字段__month       月
字段__day         日
'''
res = models.User.objects.filter(join_time__year=2022)
# 查询创建年份是2022年的数据

res = models.User.objects.filter(join_time__month=9)
# 查询创建月份是9月的数据

res = models.User.objects.filter(join_time__day=5)
# 查询创建日子是5号的数据

3.其它补充

'''
字段__in        在什么里
字段__range     数字范围
字段__contains  模糊查询(不忽略大小写)
字段__icontains 模糊查询(忽略大小写)
'''
# 举例
res = models.User.objects.filter(name__in =['小明','小兰'])
# 查询姓名是小明或者小兰的数据

res = models.User.objects.filter(age__range=(38, 88))
# 查询年龄在38到88之间的数据(包含首尾)

res = models.User.objects.filter(name__icontains='H')
# 查询名字中带有字母H的忽略大小写包含h的也行

res = models.User.objects.filter(name__contains='H')
# 查询名字中带有字母H只能是大写字母H

ORM底层SQL查看

方式一:

        如果结果是Queryset对象 那么可以直接点query查看SQL语句

方式二:

        在配置文件里配置 打印所有的ORM操作对应的SQL语句

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console':{
            'level':'DEBUG',
            'class':'logging.StreamHandler',
         },
    },
    'loggers': {
        'django.db.backends': {
            'handlers': ['console'],
            'propagate': True,
            'level':'DEBUG',
         },
    }
}

ORM创建外键关系

1.一对多

        ORM中外键字段建在多的一方  会自动添加_id后缀

models.ForeignKey()

2.多对多

        ORM中有三种创建多对多字段多方式   

models.ManyToManyField()
'''
方式1:直接在查询频率较高的表中填写字段即可 自动创建第三张关系表
方式2:自己创建第三张关系表
方式3:自己创建第三张关系表 但是还是要ORM多对多字段做关联
'''

3.一对一

        ORM中外键字段建在查询频率较高的表中 自动添加__id后缀

models.OneToOneField()

django1.x 针对 models.ForeignKey() 、models.OneToOneField() 不需要on_delete

django2.x 3.x 则需要添加on_delete参数

4.创建表格

class Book(models.Model):
    title = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=8, decimal_places=2)  # 总共八位 小数点后面站两位
    publish_time = models.DateTimeField(auto_now=True)

    publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE)
    authors = models.ManyToManyField(to='Author')

    def __str__(self):
        return '书籍对象:%s' % self.title


class Publish(models.Model):
    name = models.CharField(max_length=32)
    email = models.EmailField()

    def __str__(self):
        return '出版社对象:%s' % self.name


class Author(models.Model):
    name = models.CharField(max_length=32)
    age = models.IntegerField()
    author_detail = models.OneToOneField(to='AuthorDetail', on_delete=models.CASCADE)

    def __str__(self):
        return '作者对象:%s' % self.name


class AuthorDetail(models.Model):
    phone = models.BigIntegerField()
    addr = models.CharField(max_length=255)

    def __str__(self):
        return '作者详情对象:%s' % str(self.phone)

4.2.外键字段数据操作

models.ForeignKey?(to='Publish', on_delete=models.CASCADE)

'''
方式一:直接给实际字典添加关联数据值  publish_id = 1
方式二:间接使用外键虚拟字段添加数据对象  publish = publish_obj
'''
models.OneToOneField(to='AuthorDetail', on_delete=models.CASCADE)
'''
方式一:直接给实际字段添加关联数据值  author_detail_id = 1
方式二:间接使用外键虚拟字段添加数据对象 author_detail = authorDetail_obj
'''
models.ManyToManyField(to='Author')

add():添加数据 括号内可以填写数字值也可以填写数据对象 支持多个

remove():删除数据 括号内即可以填写数字值也可以填写数据对象 支持多个

set():修改数据 括号内必须是可迭代对象

clear():清空指定数据 括号内不需要任何参数

ORM多表查询

1.正反向概念

        正反向的概念核心在于外键字段在谁手上

正向查询

        通过书查询出版社 外键字段在书表中

反向查询

        通过出版社查询书 外键字段不在出版社表中

ps:ORM多表查询口诀>>>:正向查询按外键字段 反向查询按表名小写(_set)

2.基于对象的跨表查询(子查询)

举例题目理解正向查询与反向查询

# 查询主键为1的书籍对应的出版社
'''
1.1 先根据条件查询数据对象
1.2 以对象为基准 考虑是正向还是反向 在通过口诀(正向)
'''
book_obj = models.Book.objects.filter(pk=1).first()
print(book_obj.publish)

# 查询出版社出版的书籍
'''
2.1 先根据条件查询数据对象
2.2 一样思考是正向还是反向 再给予口诀(反向)
'''
publish_obj = models.Publish.objects.filter(name  ='出版社')
print(publish_obj.book_set.all())

ps:反向查询时表名小写后还需加(_set)此时获取到的是 app01.Book.None 所以还要加上all()

3.基于双下划线的跨表查询(连表操作)

举例题目理解基于双下划线的正向查询与反向查询

#  查询主键为1的书籍对应的出版社及书名
'''
1.1 根据条件查询数据对象
1.2 以对象为基准加关键字 values获取另一张表数据 (正向)
'''
res = models.Book.objects.filter(pk=1).values('publish__name','title')

# 查询出版社出版的书籍名称和价格
'''
2.1 根据条件查询数据对象
2.2 以对象为基准加关键字 values获取另一张表数据 (反向)
'''
res = models.Publish.objects.filter(name='出版社').values('book_title','book_price')

你可能感兴趣的:(Djangp,数据库,sql,mysql)