Django(七、模型层)

文章目录

模型层

模型层前期准备

使用django ORM要注意

1.django自带的sqlite3数据可对时间字段不敏感,有时候会展示错乱,所以我们习惯切换成常见的数据库比如MySQL。

2.django ORM并不会自动帮我们创建数据库,所以我们需要提前准备好'db001'库

3.id字段是自动添加的,如果想自定义主键,只需要在其中一个字段中店家primary_key=True,如果django发现你已经明确的设置了Field.primary_key,它将不会自动添加ID列

4.django支持mysql5.5及更高版本。

默认不允许单独测试某个py文件,如果想要测试某个py文件,一般是测试models.py文件

测试环境1:pycharm提供的python console(临时保存,不推荐使用)

测试环境2:自己搭建(自带的test或者自己创建的py文件)

python 复制代码
1.拷贝manage.py前四行代码
2.自己再添加两行
	import django
    django.setup()

代码演示:

tests.py

python 复制代码
# manage.py中拷贝前四行代码
import os
import sys
if __name__=='__main__':  # 需要在__name__下运行
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'djangoProject6.settings')# 1.引入django配置文件
    # 手写两行
    import django
    django.setup()  # 2.启动django
	# 导入app01文件夹内models文件并 测试models文件内User运行
    from app01 import models
    models.User.objects.all()

models.py

python 复制代码
class Userinfo(models.Model):
    username = models.CharField(max_length=32)
    password = models.CharField(max_length=64)
    age = models.IntegerField(null=True)
    register_time = models.DateTimeField(verbose_name='注册事件', auto_now_add=True)

    """
    DateField       : 年月日
    DateTimeField   : 年月日 时分秒
    
    两个重要参数
    auto_now        : 每次操作数据的时候 该字段会自动将当前时间更新 
    auto_now_add    : 在创建数据的时候会自动将当前创建时间记录下来 之后只要不人为的修改 那么就一直不变
    """

	def __str__(self):
        return self.username

切换MySQL数据库

python 复制代码
1.提前终端创建好库db001
2.将DATABASES的配置更改
	DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'db001',
        'USER':'root',
        'PASSWORD':'123123',
        'HOST':'127.0.0.1',
        'PORT':3306,
        'CHARSET':'utf8'

    }
}
3.连接MySQL库,数据迁移
4.makemigrations
5.migrate
如何查看django ORM 底层原理?

django ORM本质还是SQL语句。

1.如果有QuerySet对象,那么可以直接点query查看SQL语句

python 复制代码
res2 = models.Userinfo.objects.values_list('id', 'username')
print(res.query)
SELECT `app01_userinfo`.`id`, `app01_userinfo`.`username` FROM `app01_userinfo`

结论:有些不是QuerySet对象,就不能通过点query的形式点出来,就只能使用通过的方法

2.如果想查看所有ORM底层的SQL语句,也可以直接在配置文件添加日志记录

python 复制代码
res1 = models.User.objects.create(name='kimi',age=16)
print(res.query)  # 会报错

settings最后>>>拷贝代码放在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',
        },
    }
}

单表操作

模型层之ORM常见关键字
基础的增删改查
方法 返回值
create(字段名=数据) 刚创建的数据记录对象
filter(筛选条件) QuerySet列表对象
filter().update(修改内容) 受影响的行数
filter().delete() 受影响的行数即各表受影响的行数
常用的关键字
create 描述
filter 创建数据并直接获取当前创建的数据对象
first/last 根据条件筛选数据 结果是QuerySet [数据对象1,数据对象2]
update 拿queryset里面第一个元素/拿queryset里面最后一个元素
delete 删除数据(批量删除)
all 查询所有数据 结果是QuerySet [数据对象1,数据对象2]
values 根据指定字段获取数据 结果是QuerySet [{}},{},{},{}]
values_list 根据指定字段获取数据 结果是QuerySet [(),(),(),()]
distinct 去重 数据一定要一模一样才可以 如果有主键肯定不行
order_by 根据指定条件排序 默认是升序 字段前面加负号就是降序
get 根据条件筛选数据并直接获取到数据对象 一旦条件不存在会直接报错 不建议使用
exclude 取反操作
reverse 颠倒顺序(被操作的对象必须是已经排过序的才可以)
count 统计结果集中数据的个数
exists 判断结果集中是否含有数据 如果有则返回True 没有则返回False

常见的十几种查询

python 复制代码
if __name__=='__main__':
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'day06_1.settings')  # 1.引入django配置文件
    import django
    django.setup()  # 2.启动django
    from app01 import models
    res = models.Userinfo.objects.filter(pk=1).first()  # 查询id为1的数据
    print(res)

    # 查询所有数据,但是只要id和username字段
    res1 = models.Userinfo.objects.values('id', 'username')
    for i in res1:
        print(i['id'],i['username'])

    res2 = models.Userinfo.objects.values_list('id', 'username')  # 取出来的对象是列表套元组,可以通过索引取值
    print(res2)  # <QuerySet [(1, 'jack'), (2, 'jerry'), (3, 'tank')]>
    print(res2[0][1])  # jack
    print(res2.query)  #  SELECT `app01_userinfo`.`id`, `app01_userinfo`.`username` FROM `app01_userinfo`查看底层的SQL语句

    res3 = models.Userinfo.objects.all().values('password').distinct()  # distinct 去重
    print(res3)  # <QuerySet [{'password': '123'}, {'password': '222'}]>

    res4 = models.Userinfo.objects.all().order_by('id')  # order_by 默认按照升序排序,在需要查找的值中加一个-号就是降序,可以添加多个字段排序
    print(res4)

    res5 = models.Userinfo.objects.all().order_by('-id').reverse()  # reverse 反转排序,前提是已经排过序了
    print(res5)

    res6 = models.Userinfo.objects.filter(password=123).count()  # count 统计当前数据的个数
    print(res6)

    res7 = models.Userinfo.objects.exclude(pk=1)  # exclude 查询除了id=1的所有数据
    print(res7)

    res8 = models.Userinfo.objects.filter(pk=4).exists()  # exists 查询当前数据是否存在
    print(res8)

    res9 = models.Userinfo.objects.create(username='sb',password=123)  # 添加数据
    print(res9)

基于双下滑线的查询

python 复制代码
    1 年龄大于35岁的数据
    res = models.User.objects.filter(age__gt=35)
    print(res)
    2 年龄小于35岁的数据
    res = models.User.objects.filter(age__lt=35)
    print(res)
    大于等于 小于等于
    res = models.User.objects.filter(age__gte=32)
    print(res)
    res = models.User.objects.filter(age__lte=32)
    print(res)

    年龄是18 或者 32 或者40
    res = models.User.objects.filter(age__in=[18,32,40])
    print(res)

    年龄在18到40岁之间的  首尾都要
    res = models.User.objects.filter(age__range=[18,40])
    print(res)

    查询出名字里面含有s的数据  模糊查询
    res = models.User.objects.filter(name__contains='s')
    print(res)

    是否区分大小写  查询出名字里面含有p的数据  区分大小写
    res = models.User.objects.filter(name__contains='p')
    print(res)
    忽略大小写
    res = models.User.objects.filter(name__icontains='p')
    print(res)

    res = models.User.objects.filter(name__startswith='j')
    res1 = models.User.objects.filter(name__endswith='j')

    print(res,res1)


    查询出注册时间是 2020 1月
    res = models.User.objects.filter(register_time__month='1')
    res = models.User.objects.filter(register_time__year='2020')

多表操作

ORM外键字段的创建

跟MySQL外键关系一样判断规律

python 复制代码
1.一对多  外键字段建在多的一方
2.多对多  外键字段统一建在第三张关系表
3.一对一  建在任何一方都可以,但是建议建在查询频率较高的表中
注意:目前关系的判断可以采用表与表之间换位思考原则

基础表的准备

1.创建基础表(书籍表、出版社表、作者表、作者详情)

2.确定外键关系

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

3.ORM创建

针对一对多和一对一同步到表中之后自动加_id的后缀,如book中的外键字段publish,会自动变成publish_id。

python 复制代码
1.一对多关系
publish= models.ForeignKey(to='Publish',on_delete=models.CASCADE)
在多的表中建立外键字段,会在表中产生一个实际的字段(自动加_id后缀)
2.一对一
author_detail = models.OneToField(to='AuthorDetail',on_delete=models.CASCADE)
在查询频率较高的表中建立外键字段,会在表中产生一个实际的字段(自动加入_id后缀)

针对多对多,不会在表中有展示,而是自动创建第三张表

python 复制代码
1.多对多
authors=models.ManyToManyField(to='Author')
在查询频率较高的表中建立外键字段(ORM自动创建的,也可自己创建),不会在表中产生实际的字段,而是告诉ORM创建第三张关系表。

模型创建一对一、一对多和多对多的实例

需要注意

1.创建一对多的关系:

和SQL语句一样,外键建立到多的那一张表上,不同的是,我们可以不讲究连表和被关联的建立顺序。字段类为ForeignKey

在django2.x版本以上,建立一对多关系时需要指定on_delete参数为CASCADE,不加会报错,不过也不一定就是CASCADE,可能为其他实参。

建立外键是,系统会自动加上_id后缀作为字段名。

2.创建多对多关系

SQL中是将两张表建立好后,将外键字段创建在第三张表中,而Django为我们省去了这一步,我们可以在多对多关系双方的一个模型表中直接建立一个虚拟外键,ManyToManyField

在底层,sql依旧创建了第三张表来存储两表的多对多关系,但是在orm操作中我们就可以将模型表中的外键当做实实在在的联系,因为在查询时,我们看不到第三张表的存在

多对多关系的外键没有on_delete关键字参数。

3.创建一对一关系

一对一字段类为OneToOneField,建议建立在查询频率高的一方。

建立一对一关系时需要指定on_delete参数,否则报错。

相关推荐
阿华的代码王国1 小时前
MySQL ------- 索引(B树B+树)
数据库·mysql
Hello.Reader1 小时前
StarRocks实时分析数据库的基础与应用
大数据·数据库
执键行天涯1 小时前
【经验帖】JAVA中同方法,两次调用Mybatis,一次更新,一次查询,同一事务,第一次修改对第二次的可见性如何
java·数据库·mybatis
yanglamei19622 小时前
基于GIKT深度知识追踪模型的习题推荐系统源代码+数据库+使用说明,后端采用flask,前端采用vue
前端·数据库·flask
工作中的程序员2 小时前
ES 索引或索引模板
大数据·数据库·elasticsearch
严格格2 小时前
三范式,面试重点
数据库·面试·职场和发展
微刻时光2 小时前
Redis集群知识及实战
数据库·redis·笔记·学习·程序人生·缓存
单字叶2 小时前
MySQL数据库
数据库·mysql
mqiqe3 小时前
PostgreSQL 基础操作
数据库·postgresql·oracle
just-julie3 小时前
MySQL面试题——第一篇
数据库·mysql