Django之models模型层1
一、测试环境的搭建
1、app应用中默认有一个tests.py的测试文件,拷贝manage.py的内容如下到tests.py中
此时这个测试文件就能使用django环境了
import os import sys if __name__ == '__main__': os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'djangoProject222.settings') import django django.setup() from app01 import models
二、models层中
1、.values()和.values_list()方法
默认查询所有的字段,也可以指定某一个字段
res = models.Userinfo.objects.values() # 默认查询所有的字段 # <QuerySet [{'id': 1, 'username': 'cc1', 'password': '123'}, {'id': 2, 'username': 'cc2', 'password': '123'}, {'id': 3, 'username': 'cc3', 'password': '123'}]> res = models.Userinfo.objects.values('username') # <QuerySet [{'username': 'cc1'}, {'username': 'cc2'}, {'username': 'cc3'}]> res = models.Userinfo.objects.values_list() # <QuerySet [(1, 'cc1', '123'), (2, 'cc2', '123'), (3, 'cc3', '123')]> print(res)
2、排序
order by age asc/desc
res = models.User.objects.all().order_by('age') # 默认是升序排列 res = models.User.objects.all().order_by('-age') # 降序排列 res = models.User.objects.all().order_by('age', 'id') # 降序排列 res = models.User.objects.all().order_by('age', '-id', '') # 降序排列
3、去重,
每一条数据都要完全一样,如果说带主键,一定不会重复
res = models.User.objects.all().values('password', 'age').distinct() print(res)
4、反转,先排序,数据要先有序才能反转
降序---> 升序
res=models.User.objects.all().order_by('-age').reverse() print(res)
5、count
select count(*) from user res = models.User.objects.count() print(res)
6、exclude 排除
res=models.User.objects.exclude(username='kevin1') print(res)
7、exist 是否存在
res = models.UserInfo.objects.filter(pk=1).exist() print(res)
三、
1、方法一
print(res.query)
res = models.Userinfo.objects.values() # 默认查询所有的字段 print(res) print(res.query) ## 输出 SELECT "app01_userinfo"."id", "app01_userinfo"."username", "app01_userinfo"."password" FROM "app01_userinfo"
2、方法二
修改settings配置文件
LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console': { 'level': 'DEBUG', 'class': 'logging.StreamHandler', }, }, 'loggers': { 'django.db.backends': { 'handlers': ['console'], 'propagate': True, 'level': 'DEBUG', }, } }
四、
# 1 年龄大于35岁的数据 # select * from user where age > 10 # res = models.User.objects.filter(age__gt=10).all() # print(res) # 2 年龄小于10岁的数据 # res = models.User.objects.filter(age__lt=10).all() # print(res) # 3 年龄大于等于10岁的数据 e---------->equal # res = models.User.objects.filter(age__gte=10).all() # res = models.User.objects.filter(age__lte=10).all() # 4 年龄是11 或者 20 或者 23 # select * from user where age in (11, 20, 23) # res = models.User.objects.filter(age__in=[11,20,23]).all() # print(res) # 5 年龄在18到40岁之间的 首尾都要 # select * from user where age between 18 and 40 # res = models.User.objects.filter(age__range=[11,40]) # print(res) # 6 查询出名字里面含有s的数据 模糊查询 # select *from user where username like '%s%' # 回头复习 # res = models.User.objects.filter(username__contains='s').all() # print(res) # 7 用户名以s开头的 res = models.User.objects.filter(username__startswith='s').all() # res = models.User.objects.filter(username__endswith='s').all() print(res) # 8 查询出注册时间是 2023 5月 # select * from user where reg_time = '2023-05' # select date_format(reg_time, '%Y-%m') from user where date_format(reg_time, '%Y-%m') = '2023-05' # res= models.User.objects.filter(reg_time__month='5') # 查5月的 res= models.User.objects.filter(reg_time__month='5',reg_time__year='2023') # 查5月的 print(res)
补充:时间字段:DateField
其中两个参数:
auto_now:记录修改时间,一旦改动记录,自动修改为当前时间
auto_now_add:记录的创建时间,自动填写
-default=datatime.datatime:设置默认值,创建时自动添加时间
在django中修改亚洲上海时区,不修改的话,时间相差8小时。
class Userinfo(models.Model): username = models.CharField(max_length=64) password = models.CharField(max_length=64) age = models.IntegerField(default=0) reg_time = models.DateField(auto_now=True) create_time = models.DateField(auto_now_add=True) ''' auto_now = False, # 默认是False auto_now_add = False ''' def __str__(self): return self.username
五、外键字段的查询
1、数据准备
注意:多对多建外键时不用on_delete参数
# 用图书表,出版社表,作者表,作者详情表 class Book(models.Model): title = models.CharField(max_length=32) price = models.DecimalField(max_digits=8, decimal_places=2) publish_date = models.DateField(auto_now_add=True) # 一对多 publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE) # 多对多 authors = models.ManyToManyField(to='Author') class Publish(models.Model): name = models.CharField(max_length=32) addr = models.CharField(max_length=64) class Author(models.Model): name = models.CharField(max_length=32) age = models.IntegerField() # 一对一 author_detail = models.OneToOneField(to='AuthorDetail', on_delete=models.CASCADE) class AuthorDetail(models.Model): phone = models.BigIntegerField() # 电话号码用BigIntegerField或者直接用CharField addr = models.CharField(max_length=64)
2、增删改
增加一本图书? # 外键字段的查询和增加 # 增加一本图书 # models.Book.objects.create(title='洋哥自转', price=1000, publish_date='2023-08-01', publish_id=1) # publish_obj = models.Publish.objects.filter(pk=20).first() try: publish_obj = models.Publish.objects.get(pk=20) except: pass # models.Book.objects.create(title='洋哥自转2', price=2000, publish_date='2023-08-02', publish=publish_obj) # print(publish_obj) # None # 删除一本图书 # models.Book.objects.filter(pk=1).delete() # 修改 # models.Book.objects.filter(pk=2).update(publish=publish_obj) # models.Book.objects.filter(pk=2).update(publish_id=3)
3、多对多关系表的增删改查
通过对象点外键字段
add(增) remove(删) set(修改) clear(清空)
# 给图书id为2的添加一个作者id=1 book_obj = models.Book.objects.filter(pk=2).first() # print(book_obj.authors) # app01.Author.None # print(book_obj.authors.all()) # app01.Author. # 添加 book_obj.authors.add(1) # book_obj.authors.add(2, 3) # 同时添加多个作者 # 这里的数字也支持对象,但是不推荐 # author_obj = models.Author.objects.filter(pk=1).first() # print(author_obj) # book_obj.authors.add(author_obj) # 删除 book_obj.authors.remove('3') # 也支持一次删除多个。一本书有多个作者,先查书的id,再删除指定作者ID的记录 # 修改 book_obj.authors.set([1, 3]) # 清空表 book_obj.authors.clear()
4、多表查询
子查询:一个sql语句的执行结果当成另一个sql语句的执行条件,分布操作
连表查询:把多个表关联在一起拼接成一个大的虚拟表,然后按照表单查询
inner join left join right join union
正反向概念
正向概念:
外键字段在己方,我查你就是正向查询
# 图书查出版社:外键字段在图书表中,正向查询
反向概念:
外键字段在己方,你查我就是正向查询
# 出版社查图书,外键字段在图书表中,反向查询
判断出来正向和反向之后有什么用?
正向查询按照字段查询(外键字段)
反向查询按照表名小写或者表名小写_set
查询案例
# 1、查询书籍主键为1的出版社 # 书籍查出版社 ----------> 正向查询 ------------> 按外键字段查询 res = models.Book.objects.filter(pk=1).first() # print(res) # Book object (1) # print(res.publish) # book对象点外键字段publish跳转到出版社表 print(res.publish.addr) # 接着可以点表里的字段查记录 # 2、查询书籍主键为2的作者 # 书籍查作者 ----------> 正向查询 ------------> 按外键字段查询 res = models.Book.objects.filter(pk=2).first() # print(res.authors) # app01.Author.None # print(res.authors.all()) # <QuerySet [<Author: Author object (2)>, <Author: Author object (3)>]> print(res.authors.all()[1].name) # 由上可知查询对象有2条结果,按下标取name # 循环取出所有的作者名 # for i in res.authors.all(): # print(i.name) # 3、查询作者曹雪芹的电话号码 # 作者查询作者信息 ----------> 正向查询 ------------> 按外键字段查询 res = models.Author.objects.filter(name='曹雪芹').first() print(res.author_detail.phone) # 4、查询出版社是北京出版社的书 # 出版社查书籍----------> 反向查询 ------------> 按照表名小写或者拼接_set res = models.Publish.objects.filter(name='北京出版社').first() print(res.book_set) # app01.Book.None print(res.book_set.all()[0].title) # 5、查询作者是罗贯中写过的书 # 作者查书籍 ----------> 反向查询 ------------> 按照表名小写或者拼接_set res = models.Author.objects.filter(name='罗贯中').first() print(res.book_set.all()) for i in res.book_set.all(): print(i.title) # 6、查询手机号是1209的作者姓名 # 作者详情查作者 ----------> 反向查询 ------------> 按照表名小写或者拼接_set res = models.AuthorDetail.objects.filter(phone='1209').first() print(res.author.name)
注意:反向查询按照表名小写或者表名小写+_set
只有在一对一表关系中才能使用小写表名的形式,即当查询的结果只有一条的时候,不能拼接_set