首页 > 其他分享 >Django模型层

Django模型层

时间:2022-12-15 20:11:26浏览次数:50  
标签:obj name models 模型 查询 filter objects Django

测试环境

Django默认需要整个项目跑起来才可以运行功能函数,如果想测试某个文件需要准备测试环境。(主要指模型层 models.py)

1.python自带测试环境

python Console 但整个是命令行形式 看起来不够直观

2.自己搭建

在自己的app里面创建一个test.py文件

并复制已下代码

from django.test import TestCase
 
# Create your tests here.
import os
 
def main():
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'djmodel.settings')
    import django
    django.setup()
    
    #需要执行的内容
    
    
main()

查看orm底层执行的sql语句

在sttings文件中配置

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

这样每次运行models命令都会显示对于的sql语句

常用关键字

create

表中新增数据,并有返回值是创建的对象本身

res = models.User.objects.create(name='moon',age=18)
print(res)  
# 在数据库表名 user 的表中 插入了一条数据,对应字段数据(name='moon',age=18)
# res就是这条数据本身

filter()

筛选 支持多个条件 默认是 多个条件是and关系

res = models.User.objects.filter(name='moon')
print(res) 
 
# 查询 user表中 字段name 是 moon 的数据对象
# 返回的是 <QuerySet [<User: User object (1)>]> 是一个列表

搭配 first() last() 使用

res = models.User.objects.filter(name='moon').first()
# 拿到查询列表中 第一个数据对象 res=对象

res = models.User.objects.filter(name='moon').last()
# 拿到查询列表中 最后一个数据对象 res=对象

update()

更新数据 搭配筛选来决定更新的个数

# 批量更新
models.User.objects.filter().update()  
#没有筛选条件 默认选中的是全部 所以是针对全部更新
 
# 单个更新
res = models.User.objects.filter(id=1).update(age=22)  
print(res) 
# 帅选出id=1的数据对象,针对这个对象 进行更新数据 age=22

delete()

删除数据 搭配筛选来决定删除的个数

# 批量删除
models.User.objects.filter().delete()  
#没有筛选条件 默认选中的是全部 所以是针对全部删除
 
# 单个删除
res = models.User.objects.filter(id=1).delete() 
print(res) 
# 帅选出id=1的数据对象,针对这个对象 进行删除

all()

查询所有数据

models.User.objects.all()
 
<QuerySet [<User: 用户对象的对象是:duo>, <User: 用户对象的对象是:bo>...]>
# 或得到所有数据对象的类别

values()

指定字段获取内容

models.User.objects.all().values('name')
#获取user表中字段name的所有的值
models.User.objects.filter(id=1).values('name')
# #获取user表中id为1的数据 的 name字段的值
models.User.objects.values('name')
print(res)  # <QuerySet [{},{},{}]>   列表套字典

# <QuerySet [{},{},{}]>   列表套字典

values_list()

指定字段获取内容

models.User.objects.values_list('name')

# <QuerySet [('duo',), ('bo',), ('duoduo',), ('bo',), ('hong',)]>

结果是QuerySet[(),(),(),()]列表套元组

distinct()

将查询的结果去重,不影响数据库中的数据

去重条件必须是查询出来的结果必须一模一样 所以不要带主键查询 因为主键都是不同的

models.User.objects.values('name','age').distinct()

# 针对表 user 字段 name 和 age 完全一样的数据去重展示

order_by()

根据指定条件排序 默认升序

models.User.objects.order_by('age')
# user表进行排序 排序根据为age 默认升序 从小到大

models.User.objects.order_by('-age')
# 加上 - 号 就是默认降序 从大到小

count()

统计结果集中数据数据的个数 返回值是整数

models.User.objects.filter(age=22).count()
# 统计user表中 age是22的有几个
# 3

exists()

判断数据中是否有该数据 返回布尔值

models.User.objects.filter(id=1).exists()
# 查看user表中是否有id为1的数据存在
---
True

ORM执行编写SQL语句

复杂数据查询时候orm的操作效率可能比较低 没有原生的sql效率高,我们也可以自己编写sql

关键词 raw

	res = models.User.objects.raw('select * from app01_user;')
  # 直接编写sql语句去执行
  
 方式二:
    from django.db import connection
    cursor = connection.cursor()
    cursor.execute('select name from app01_user;')
    print(cursor.fetchall())
    
    # 利用模块生成 cursor对象 然后利用cursor执行sql语句
    # cursor.fetchall() 接收反馈结果

双下划线查询

大于 小于 大于等于 小于等于 区间 包含等查询方式

我们通过models.User.objects.filter()方法可以获得多个符号条件的对象列表

通过.filter()方法获得数据,支持双下划线查询

'''
    只要还是queryset对象就可以无限制的点queryset对象的方法
    queryset.filter().values().filter().values_list().filter()...
'''

models.User.objects.filter(age__gt=18)
# 查询年龄大于18的数据对象

models.User.objects.filter(age__lt=18)
# 查询年龄小于18的数据对象

models.User.objects.filter(age__gte=18)
#大于等于
models.User.objects.filter(age__lte=18)
#小于等于



models.User.objects.filter(age__in=(18,28,38))
# 查询年龄是 18 或者 28 或者 38的数据对象

models.User.objects.filter(age__range=(10,20))
# 查询年龄从10到20岁  之间 的数据对象

models.User.objects.filter(name__contains='m')
# 查询name字段中 包含 'm' 的数据对象 不包括大写M
models.User.objects.filter(name__icontains='m')
# 也包含大写的M


models.User.objects.filter(register_time__year=2022)
# 查询时间字段里面 年是 2022的数据对象

ORM表外键字段的创建

外键创建的位置

一对多
外键字段建在多的一方
多对多
外键字段统一建在第三张关系表
一对一
建在任何一方都可以 但是建议建在查询频率较高的表中

关系的判断可以采用换位思考原则 熟练的之后可以瞬间判断

   一对多 ORM与MySQL一致 外键字段建在多的一方
 	多对多 ORM比MySQL有更多变化
    1.外键字段可以直接建在某张表中(查询频率较高的)
        	内部会自动帮你创建第三张关系表
  	2.自己创建第三张关系表并创建外键字段
        	详情后续讲解
	一对一 ORM与MySQL一致 外键字段建在查询较高的一方  
  
  
代码实操:

	  一对多
    一本书只可以对应一个出版社 一个出版社可以对应很多本书 
    publish = models.ForeignKey(to='Publish',on_delete=models.CASCADE)
    # 在 书 的表中建立外键 关联 出版社表  在django中会自动关联主键
    # on_delete=models.CASCADE 级联删除的意思
    
    多对多
    书可以有多个作者 作者也可以有多本书
    外键字段名 = models.ManyToManyField(to='关联表名')
    # 在 书 表中 建立外键 关联 作者表 ,
    # 多对多会自动生成一张表 记录 书对于作者的关系 和 作者对于书的关系
    # 针对多对多 不会在表中有展示 而是创建第三张表
    
    
    一对一
    一个作者只可以对应一个信息 一个信息也只可以对应一个作者
    author_info = models.OneToOneField(to='Author_info')
    # 在作者表中 建立外键 关联 作者信息表
    # 一对一外键字段建在查询较高的一方 
    
    #针对一对多和一对一同步到表中之后会自动加_id的后缀

外键字段增删改查

一对多 与 一对一的增删改查

在表中插入数据

一对多 与 一对一的增删改查
models.Book.objects.create
(name='西记',price='100',publish_id=1)
# 直接在外键添加实际字段 填写id

增:

publish_obj = models.Publish.objects.filter(pk=2).first()
# 先获取一个出版社对象
models.Book.objects.create
(name='西记',price='100',publish=publish_obj)
# 然后也可以直接把这个对象放入这个外接字段中publish=publish_obj

既可以写实际字段 publish_id='1' 也可以传对象 publish=publish_obj


删:

models.Publish.objects.filter(pk=2).delete()
# 级联删除


改:

models.Publish.objects.filter(pk=2).update(publish_id=2)
models.Publish.objects.filter(pk=2).update(publish=publish_obj)

多对多的增删改查

多对多的增删改查 其实就是针对于第三张表的增删改查

如果给书籍表添加作者
1.先拿到数据对象
book_obj = models.Book.objects.filter(pk=1).first()
book_obj.authors
# 对象.外键其实已经进入了关系表了
book_obj.authors.add(1)
# 给这个数据对象 绑定一个 id为1的作者

add也可以同时添加多条 

book_obj.authors.add(1,3)
# 这样相当于 给书的这个对象 绑定了 1和3 2个id的作者

book_obj.authors.add(author_obj,author_obj2)
# 也支持直接放入一个对象 书的id和这个对象的id会绑定

add是给第三张关系表添加数据 既可以传id 也可以直接传对象


删除:
remove

book_obj.authors.remove(1,3)
# 这样就直接删除了 这个书对于的作者关系

book_obj.authors.remove(author_obj,author_obj2)
# 跟增加一样 也支持直接删除对象


修改:
  set
  
  book_obj.authors.set([1,3])
  # 把数据对应的作者关系 更改为 这本书 对应作者id为 1和3
  # set(括号内必须是可迭代对象 列表 或者 元组)
  
  book_obj.authors.set([author_obj,author_obj2])
  # 也支持直接放对象
  
  
清空:
  book_obj = models.Book.objects.filter(pk=1).first()
  book_obj.authors.clear()
  
  # 直接去authors这个表里面取消所有相关的绑定关系

正反向的概念

关键是看 外键字段在哪里

加入由书查出版社

因为外键字段在书内 所以就是正向查询

出版社查书 因为出版社内没有外键字段 就是 反向查询

多表查询

正向查询按字段

反向查询按表名小写

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

正向查询

代码演示:

查询书籍id为1的 出版社名称

1、首先要查询到id为1的书籍对象
book_obj = models.Book.objects.filter(pk=1).first()
2. 通过书的对象 查询出版社 属于正向查询 直接按字段查询
book_obj.publish.name
3. 直接通过书籍内关联出版社的外键字段 直接查询


查询书籍主键为1的作者

1、首先要查询到id为1的书籍作者
book_obj = models.Book.objects.filter(pk=1).first()
2. 通过书的对象查询作者属于正向查询 直接可以使用关于作者的外接字段
book_obj.authors.all()
3. 这样就直接拿到了作者对象


查询作者为'moon'的电话号码

1.首先查询到名为 moon 的作者对象
authors_obj = models.Authors.objects.filter(name='moon').first()
authors_obj.info.phone


正反向查询的概念(重要)
	正向查询
    	由外键字段所在的表数据查询关联的表数据 正向
 	反向查询
    	没有外键字段的表数据查询关联的表数据	 反向
 	ps:正反向的核心就看外键字段在不在当前数据所在的表中
 
ORM跨表查询的口诀(重要)
	正向查询按外键字段
	反向查询按表名小写

反向查询

查询是东方出版社出版的书

拿到东方出版社对象
 publish_obj = models.Publish.objects.filter(name='东方出版社').first()
 publish_obj.book_set.all()
 # 反向查询用表名小写 加_set 
  
  
查询作者是'moon'写过的书

authors_obj = models.Authors.objects.filter(name='moon').first()
authors_obj.book_set.all()



# 都是先拿到已知的条件获得一个对象 然后判断是反向还是正向 
# 正向就直接点外键字段查询 反向就小写表名加_set


'''
当你的查询结果是多个的时候 必须要用 _set.all()
当你的结果直接一个的时候不需要加_set.all()
'''

联表查询(基于双下划线方法的)

正向查询

1.查询作者'moon'的 手机号
authors_obj = models.Authors.objects.filter(name='moon').
values('author_detail__phone')
# 直接在values里面 填写外键字段名 然后直接 __取值
# 反向 models.info.objects.filter(authors__name='moon').valuse(phome)



2.查询数据id为1的出版社名称和书的名称
models.Book.objects.filter(pk=1).values(publish__name,name)
# 反向 models.Publish.objects.filter(book__pk=1).values(name,book__name)


3.查询书籍主键为1的作者姓名 
models.Book.objects.filter(pk=1).values(authors__name)
# 反向 models.Authors.objects.filter(book__pk=1).values(name)



标签:obj,name,models,模型,查询,filter,objects,Django
From: https://www.cnblogs.com/moongodnnn/p/16985929.html

相关文章