首页 > 其他分享 >【2022-09-05】Django框架(五)

【2022-09-05】Django框架(五)

时间:2022-09-05 21:57:27浏览次数:60  
标签:name models res 09 Django filter objects 2022 print

Django框架(五)

定义模型类

from django.db import models


# Create your models here.

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.DateTimeField(auto_now_add=True)

补充知识

# 1、存储时间格式数据:
models.DateField()      # 日期字段:存储年月日
models.DateTimeField()  # 日期字段:存储年月日时分秒

# 日期字段重要参数 
auto_now		:  每次更新操作数据的时候 该字段会自动将当前时间更新
auto_now_add	        :  在创建数据的时候会自动将当前创建时间记录下来,之后只要不人为的修改,那么时间就一直不变
 
 
# 2、pk关键字
作用:pk会自动查找到当前表的主键字段 指代的就是当前表的主键字段
优点:用了pk之后 你就不需要指代当前表的主键字段到底叫什么了(nid,pid,uid....)
 
# 3、.get()方法
作用:.get()方法可直接拿到当前用户对象
eg:
user_obj = models.User.objects.get(pk=1)   # 直接拿到id=1的用户对象
相当于:
user_obj = models.User.objects.filter(pk=1).first()
 
# 但是不推荐使用get方法:因为一旦数据不存在那么使用该方法就会立刻报错,而使用filter方法如果数据不存在则返回空列表[]不会报错

执行数据库迁移命令

方式一:使用命令行

    python manage.py makemigrations
    python manage.py migrate

方式二:使用pycharm快捷方式

    上方菜单栏里找到并点击Tools——Run manage.py Task,依次执行下面两条语句即可
        makemigrations
        migrate

使用pychram连接mysql

一、修改配置文件

二、连接mysql

编写测试脚本

当我们只想操作django中某一个py文件内容时,那么可以不用书写前后端交互的形式来判断运行结果是否正确,我们可以直接写一个测试脚本即可。
  • 在我们创建应用的时候,会自动创建一个tests.py文件,我们可以在这里编写测试脚本。
from django.test import TestCase

# Create your tests here.


# 测试环境准备:去manage.py文件中拷贝下述代码到测试文件,然后自己配置两行,如下:

import os


# from app01 import models.py  不可以写在这里

def main():
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'djangoProject1.settings')
    import django
    django.setup()  # 相当于启动django

    from app01 import models
    print(models.User.objects.filter())


# 注意:如果测试的脚本需要用到模块,必须写在配置好的环境下面,不可在最外层导入模块使用

if __name__ == '__main__':
    main()

  • pycharm也提供了一种测试环境

单表操作

表的新增

# 方式一:
res = models.User.objects.create(name='jack',age=19,register_time='2000-1-2')
print(res)  # 返回值为当前被创建对象本身
 
# 方式二:
import datetime
ctime = datetime.datetime.now()   # 当前时间
user_obj = models.User(name='tom',age=10,register_time=ctime)  # 也可存入一个日期对象
user_obj.save()

表的删除

# 方式一:
res = models.User.objects.filter(pk=2).delete()
print(res)   # 返回值为当前sql语句影响的行数(到底删了几行)
 
# 方式二:
user_obj = models.User.objects.filter(pk=1).first()  # 拿到当前用户对象
user_obj.delete()  # 用户对象也有delete方法

表的修改

# 方式一:
models.User.objects.filter(pk=4).update(name='tom2222')  # 匹配到id=4的记录并只修改name属性
 
# 方式二:
user_obj = models.User.objects.get(pk=4)
user_obj.name = 'tom3333'
user_obj.save()

ORM常见查询关键字

1.all()   
# 查询所有数据
res = models.User.objects.all()  # 括号内不可添加筛选条件
print(res)
 
# 结果:<QuerySet [<User: 对象:jack>, <User: 对象:tom>]>
2.filter() 
# 带有过滤条件的查询
res = models.User.objects.filter(pk=2)   # 括号内可添加筛选条件
print(res)
 
# 结果:<QuerySet [<User: 对象:tom>]>
3.get()  
# 直接拿数据对象,但是条件所匹配的数据不存在则直接报错
res = models.User.objects.get(pk=2)
print(res)   # 结果    对象:tom
res1 = models.User.objects.get(pk=3)
print(res1)  # 结果    报错

4.first()  
# 拿queryset里面的第一个元素
 
res = models.User.objects.filter().first()
print(res)
 
# 结果:对象:jack
5.last()   
# 拿queryset里面的最后一个元素
res = models.User.objects.filter().last()
print(res)
 
# 结果:对象:tom
6.values()  
# 可指定获取的字段,返回结果可以看作是列表套字典的形式
 
# 拿到所有用户的信息
res = models.User.objects.values()
print(res)
 
# 结果:<QuerySet [{'id': 1, 'name': 'jack', 'age': 19, 'register_time': datetime.date(2000, 1, 2)}, {'id': 2, 'name': 'tom', 'age': 10, 'register_time': datetime.date(2022, 2, 26)}]>   # 列表套字典的形式
 
 
eg:
# 1、只拿用户的名字
res = models.User.objects.values('name')
print(res)
    
# 结果:<QuerySet [{'name': 'jack'}, {'name': 'tom'}]>
 
 
# 2、只拿用户的名字和年龄
res = models.User.objects.values('name','age')
print(res)
# 结果:<QuerySet [{'name': 'jack', 'age': 19}, {'name': 'tom', 'age': 10}]>
相当于sql语句:select name,age from user
7.values_list()
# 同样可以指定需要获取的字段
# 但返回结果可以看作是列表套元组的形式
res = models.User.objects.values()
print(res)
 
# 结果:<QuerySet [(1, 'jack', 19, datetime.date(2000, 1, 2)), (2, 'tom', 10, datetime.date(2022, 2, 26))]>

8.distinct()
# 去重
# 注意:去重一定要是一摸一样的数据(一定要考虑主键),一个对象如果包含主键的话永远去不了重复数据
 
res = models.User.objects.filter().distinct()
print(res)  # 查所有:无意义,因为包含主键
 
res1= models.User.objects.values('name').distinct()
print(res1)  # 按照name字段去重
 
# 结果:
# <QuerySet [<User: 对象:jack>, <User: 对象:tom>, <User: 对象:jack>, <User: 对象:gary>]>
# <QuerySet [{'name': 'jack'}, {'name': 'tom'}, {'name': 'gary'}]>
9.order_by()
# 排序
.order_by('age')   # 默认升序
.order_by('-age')  # 降序在参数前加一个-
 
# eg:
    res1 = models.User.objects.values('age').order_by('age')
    print(res1)   # 升序
    res = models.User.objects.order_by('-age')
    print(res)    # 降序

10.reverse()
# 反转
 
# 前提:数据已经排序了,如果没排序是不支持反转的,必须提前排序过。
 
order_by().reverse()   # 通常情况下跟order_by联合使用
 
# eg:
    res = models.User.objects.filter().reverse()
    print(res)
 
    res1 = models.User.objects.order_by('age')
 
    res2 = models.User.objects.order_by('age').reverse()
    print(res2)

11.count()
# 统计当前数据的个数
res = .count()
 
# eg:
    res = models.User.objects.filter().count()
    print(res)  # 统计所有数据对象的个数
 
    res = models.User.objects.values('name').distinct().count()
    print(res)  # 按照name去重之后统计数据个数
    
# 结果:
	4
	3

12.exclude()
# .exclude()  # 排除(括号内匹配成功)之外的数据
 
# eg:
    res = models.User.objects.exclude(name='jack')
    print(res)
# 查询name = 'jack'之外的数据

13.exists()
# 判断是否存在  返回的是布尔值 
# 作用不大:因为数据本身就存在布尔值
 
# eg:
    res = models.User.objects.filter(pk=1).exists()
    print(res)
    res1 = models.User.objects.filter(pk=200)
    print(res1)
    res2 = models.User.objects.filter(pk=200).exists()
    print(res2)
    
# 结果:
    True
    <QuerySet []>
    False

14.raw()
	执行SQL语句
 	还可以借助于模块
    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()

ORM双下划线查询方法

比较运算

# 关键字:
    大于:			 __gt
    小于:			 __lt
    大于等于:	    __gte
    小于等于:		__lte
  
# 举例:
    res = models.User.objects.filter(age__gt=20)
    print(res)   # 年龄大于20
    res1 = models.User.objects.filter(age__lt=30)
    print(res)   # 年龄小于30
    res2 = models.User.objects.filter(age__gte=19)
    print(res2)  # 年龄大于等于19
    res3 = models.User.objects.filter(age__lte=30)
    print(res3)   # 年龄小于等于30

在某一数据集内

# 关键字:__in=['数据集']
 
# 举例:
    res = models.User.objects.filter(age__in=[10,20,30,40])
    print(res)

在某一范围内

# 关键字:__range=[]
# 举例:
    res = models.User.objects.filter(age__range=[19,40])
    print(res)

模糊查询

# 关键字:__contain=''  区分大小写
	 __icontain=''  不区分大小写
# 举例:
    res = models.User.objects.filter(name__contains='k')
    print(res)
    res1 = models.User.objects.filter(name__icontains='k')
    print(res1)

以什么开头/结尾

# 关键字:__startswith=''  以什么开头
	 __endswith=''	 以什么结尾
    	__istartswith=''  不区分大小写
        __iendswith=''   不区分大小写

按照日期查询

# 关键字:
    __month='1'   # 按照月份取
    __year='2020'  # 按照年份
    __day='29'    # 按照天筛选
    __weekday=''  # 按照日期
 
# 举例:
    res = models.User.objects.filter(register_time__month='01')
    print(res)
    res1= models.User.objects.filter(register_time__day='02')
    print(res1)
    res2= models.User.objects.filter(register_time__week_day='02')
    print(res2)
    res3 = models.User.objects.filter(register_time__year='2022')
    print(res3)
    res4 = models.User.objects.filter(register_time__year='2022',register_time__month='02')
    print(res4)

查看ORM底层SQL语句

# .query方法
 
.query方法可查看内部封装的sql语句
但是使用该方法查看sql语句的方式,只能用于queryset对象属性
只有返回结果为queryset对象才能够使用
 
eg:
    res1 = models.User.objects.filter()
    print(res1.query)
    res = models.User.objects.get(name='jack')
    print(res.query)

# 解决:所有的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外键字段的创建

一对多
	ORM中外键字段建在多的一方 models.ForeignKey()
   	会自动添加_id后缀
多对多
	ORM中有三种创建多对多字段的方式 models.ManyToManyField()
    	方式1:直接在查询频率较高的表中填写字段即可 自动创建第三张关系表
        方式2:自己创建第三张关系表
        方式3:自己创建第三张关系表 但是还是要orm多对多字段做关联
一对一
	ORM中外键字段建在查询频率较高的表中 models.OneToOneField()
    	会自动添加_id后缀
 
django1.X 针对 models.ForeignKey() models.OneToOneField()不需要on_delete
django2.X 3.X 则需要添加on_delete参数

ORM多表操作

多表操作前期准备

models.py

class Book(models.Model):
    name = models.CharField(max_length=32,verbose_name='书名')
    price = models.DecimalField(max_digits=8,decimal_places=2,verbose_name='价格')
    publish_date = models.DateTimeField(auto_now_add=True,verbose_name='出版时间')
    publish = models.ForeignKey('Publish')  # 一对多
    authors = models.ManyToManyField('Author')   # 多对多
 
 
class Publish(models.Model):
    name = models.CharField(max_length=32,verbose_name='出版社名字')
    addr = models.CharField(max_length=32,verbose_name='出版社地址')
 
class Author(models.Model):
    name = models.CharField(max_length=32,verbose_name='作者名字')
    age = models.IntegerField(verbose_name='作者年龄')
    author_detail = models.OneToOneField('AuthorDetails')   # 一对一
 
class AuthorDetails(models.Model):
    phone = models.BigIntegerField(verbose_name='作者电话')
    addr = models.CharField(max_length=32,verbose_name='作者地址')

一对多外键增删改查

# 一对多外键增加数据
 
    # 方式一:直接写实际字段
    models.Book.objects.create(name='红楼梦',price=111.11,publish_id=1)
    # 方式二:虚拟字段
    publish_obj = models.Publish.objects.filter(pk=2).first()
    models.Book.objects.create(name='三国演义',price=22.5,publish=publish_obj)

# 一对多外键删除数据
 
models.Pulish.objects.filter(pk=1).delete()
 
# 删除记录是级联删除的,所以对应的外键字段一会直接删除,取消关联关系
# 一对多外键修改数据
 
    # 方式一:直接写实际字段
    models.Book.objects.filter(pk=1).update(publish_id=2)
 
    # 方式二:虚拟字段
    publist_obj = models.Publish.objects.filter(pk=3).first()
    models.Book.objects.filter(pk=2).update(publish=publist_obj)

多对多外键增删改查

# 多对多的增删改查其实就是在操作第三张虚拟表

# 先思考一个问题,如何添加作者
# 这张表不是我们自己创建的是系统帮助我们创建的,所以我们根本不能通过models的方法(.)到这张表
 
# 这里就要通过对象(.)外键的方式找到第三张表
# 多对多表关系的增加:
# 关键字:.add(主键值)
    # 方式一:
    book_obj = models.Book.objects.filter(pk=1).first()
    book_obj.authors.add(1)
   	book_obj.authors.add(2,3)   # 增加多个
    # 方式二:
    author_obj = models.Author.objects.filter(pk=1).first()
    author_obj1 = models.Author.objects.filter(pk=2).first()
    author_obj2 = models.Author.objects.filter(pk=3).first()
    book_obj.authors.add(author_obj)
    book_obj.authors.add(author_obj1,author_obj2)   # 增加多个

# 多对多表关系的删:
# 关键字:.remove(主键值)
    # 方式一:
    book_obj = models.Book.objects.filter(pk=1).first()
    book_obj.authors.remove(2,3)  # 同样支持多条数据同时删除
    # 方式二:对象
    book_obj1 = models.Book.objects.filter(pk=2).first()
    author_obj1 = models.Author.objects.filter(pk=1).first()
    author_obj2 = models.Author.objects.filter(pk=2).first()
    author_obj3 = models.Author.objects.filter(pk=3).first()
    book_obj1.authors.remove(author_obj1,author_obj2)

# 多对多表关系的修改
# 关键字:set()
    # 方式一:
    book_obj = models.Book.objects.filter(pk=1).first()
    book_obj.authors.set([2,3])  # 同样支持多条数据同时修改
    # 方式二:对象
    book_obj1 = models.Book.objects.filter(pk=2).first()
    author_obj1 = models.Author.objects.filter(pk=1).first()
    author_obj2 = models.Author.objects.filter(pk=2).first()
    author_obj3 = models.Author.objects.filter(pk=3).first()
    book_obj1.authors.set([author_obj1,author_obj2])

# 注意:set关键字括号内必须填写一个可迭代对象(列表或者元组)

# 多对多表关系的清空(清空在第三中某个书籍与作者的绑定关系)
# 关键字:clear()  #  括号内不要加任何参数

正反向的概念

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

正向查询
	通过书查询出版社 外键字段在书表中
反向查询
	通过出版社查询书 外键字段不在出版社表中
 
ORM跨表查询口诀>>>:正向查询按外键字段 反向查询按表名小写

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

# 查找主键值为1的书的出版社名字和出版社地址(正向)
 
book_obj = models.Book.objects.filter(pk=1).first()  # 先拿到主键为1的书籍对象
res = book_obj.publish  # 拿到外键字段所对应关系表中的对象
print(res)   # 对应出版社的对象
print(res.name)      # 出版社名字
print(res.addr)      # 出版社地址

# 查询书籍主键为2的作者(正向)
    book_obj = models.Book.objects.filter(pk=2).first()
    res = book_obj.authors    # 
    print(res)

# 我们发现返回了一个:app01.Author.None
# 注意这个返回结果是一个标志性的问题:在当返回结果可能为多个的时候(一本书可以由多名作者编写(多对多的表关系)必须加关键字.all())
 
 # # 查询书籍主键为2的作者(正向)
    book_obj = models.Book.objects.filter(pk=2).first()
    res = book_obj.authors.all()
    print(res)
    print(res[0].name)   # 因对象有多个所以要通过索引取值拿到单独的对象
    print(res[1].name)

# 查询作者gary的电话号码(正向)
    author_obj = models.Author.objects.filter(name='gary').first()
    print(author_obj)
    res = author_obj.author_detail
    print(res)
    print(res.phone)
    print(res.addr)

# 查询是南方出版社出版的书(无外键字段(反向))
    publish_obj = models.Publish.objects.filter(name='东方出版社').first()
    res = publish_obj.book
    print(res)

# 反向查询上边有提到需要加入_set
# 查询是南方出版社出版的书(无外键字段(反向))
    publish_obj = models.Publish.objects.filter(name='南方出版社').first()
    res = publish_obj.book_set.all()  # 并且使用到.all()方法
    print(res)

# 5.查询作者是jason写过的书
    author_obj = models.Author.objects.filter(name='jason').first()
    res = author_obj.book_set.all()
    print(res)

# 6.查询手机号是110的作者姓名
    authorsetails_obj = models.AuthorDetails.objects.filter(phone='110').first()
    res1 = authorsetails_obj.author
    print(res1)

总结:

# 基于对象 
反向查询的时候
    当你的查询结果可能有多个的时候 就必须加_set.all()
    当你的结果只能有一个的时候 不需要加_set.all()

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

# 同样遵循
# 正向查询按字段
# 反向查询按表名小写
# 查询作者gary的手机号(必须用一行代码展示)
    res = models.Author.objects.filter(name='gary').values('author_detail__phone','name')
    print(res)
    
# 利用values方法查询
注意:此时Author为基表可通过values方法直接查到该表的属性值
 
 
# 反向:(不允许.Author)
    res = models.AuthorDetails.objects.filter(author__name='gary').values('phone','author__name')
    print(res)

# 查询书籍主键为1的出版社的名称和书的名称
    res = models.Book.objects.filter(pk=1).values('name','publish__book')
    print(res)
 
# 方式二:反向
    res = models.Publish.objects.filter(book__id='1').values('name','book__name')
    print(res)

# 3.查询书籍主键为1的作者姓名
res = models.Book.objects.filter(pk=1).values('authors__name')
print(res)
# 方式二:反向
    res = models.Author.objects.filter(book__id=1).values('name')
    print(res)

# 查询书籍主键是1的作者的手机号
# 注意:这道题涉及到三张表
# 思路:通过书籍查作者,再通过作者查作者详情
    res = models.Book.objects.filter(pk=1).values('authors__author_detail__phone')

标签:name,models,res,09,Django,filter,objects,2022,print
From: https://www.cnblogs.com/dy12138/p/16659247.html

相关文章

  • 220905-读书笔记-把时间当做朋友
    印象中,第一次读这本书的时候,是在大学期间,应该是大一或者大二的时候,当时候自己的智识达不到理解这本书的层次。现在在读这本书,竟觉得略有些浅显。总的来说,这本书写的比较零......
  • 【题解】做题记录(2022.9)
    可能会断断续续的,是因为可能有的时候忘记了写记录9.5今天搞了一天的平衡树,但大部分都是比较基础的操作[SHOI2009]会场预约题目分析:set大法吼啊我们考虑重新定义两个......
  • 【题解】[SDOI2009] 虔诚的墓主人
    题意传送门\(N\timesM\)的矩形,格点是共\(W\)棵常青树或墓地。对于一块墓地,它的虔诚度为让它正上下左右各恰有\(k\)棵常青树的方法数量。求出整个矩形公墓的虔诚度总......
  • JAVA进阶--日志框架、阶段项目实战--2022年9月5日
    第一节 日志框架1、什么是日志用来记录程序运行过程中的信息,并且可以进行永久存储  2、输出语句存在哪些问题,日志结束应该具备哪些特点......
  • 2022-09-03 第二小组 张晟源(JAVAWebMVC)
    JAVAWeb一,MVC架构是一种软件架构模式,把整个软件分为三层:Model,view,controllerModel:模型---获取数据,并处理,返回给controller  entity:数据库实体类User---user表 ......
  • ifort + mkl + impi (全套intel)编译安装量子化学软件GAMESS 2022 R1版本
    说明:linux下编译软件都需要先配置好该软件依赖的系统环境。系统环境可以通过软件的安装说明了解,例如:readme.md等文件或网页。这个前提条件很重要!后面正式编译出错基本都......
  • 2022-09-05 第四小组 王星苹 学习笔记
    学习心得简单的做一个java里面要连接网页和数据库实现注册,主要是代码,建议先写好工具类,这样之后写东西的时候直接就可以用了,比如新学的密码加密的盐的工具类,之前的JDBC工具......
  • 2022 Microsoft Build After Party活动:杨中科聊天分享会
    去年,我组织了一次MicrosoftBuildAfterParty活动,今年,咱们活动继续。预计在2022年11月11日晚上19:00(北京时间),我将会通过哔哩哔哩平台直播,为大家分享我对MicrosoftBuild......
  • django之模型层1
    #模型层就是跟数据库打交道的数据库就是如何查询数据一、表查询数据准备以及测试环境搭建'''1.django自带一个数据库sqlite3小型数据库这个数据库功能少而且对......
  • 2022-08-30 day38 第一小组 王鸣赫
    目录HttpServletRequest//请求HttpServletResponse//响应路径匹配servlet加载时期常见传参有2种:GET和POST区别获取一个key对应的多个值请求转发作用域其他方法Respo......