064.django之模型层单表查询

一、orm简介

(一) orm概述

1 orm:对象关系映射(跟语言无关)
    	数据库中的表     ----》对应程序的一个类
        数据库中的一行数据----》对应程序中的一个对象

2 python中常见orm框架
	-django的orm框架
    -sqlachemy orm框架

3 orm能干的事
	-创建表(不能创建数据库,手动创建数据库)
    -增加删除表内字段
    -增删查改数据

​ 查询数据层次图解:如果操作mysql,ORM是在pymysq之上又进行了一层封装。

ORM图示:

(二) django中orm的使用

0 sqlite:也是要给数据库,文件数据库,一个库就是一个文件,不需要单独安装
	-咱们现在在用,也要用到关系型数据库,不想装mysql,就可以使用sqlite
    -移动开发本地存储数据,存在sqlite中

1 创建个UserInfo表,在models中写一个类
2 表中有字段(类属性),字段有属性,


# 第一步在models中写要给类
	class UserInfo(models.Model):
        # 字段属性--》后面那个对象决定的,
        # 改字段自增,并且是主键
        id = models.AutoField(primary_key=True)
        # 改字段是varchar类型,长度为32(唯一约束,是否是索引,默认值是,是否可以为空)
        name = models.CharField(max_length=32)
        # 密码字段
        password =models.CharField(max_length=64)
        
# 第二步,把表创建出来(执行两个命令)
	-python3 manage.py makemigrations  # 这条命令会在migrations创建一条记录,数据库变更记录
    -python3 manage.py migrate         # 把更改同步到数据库,若数据库没有变化,执行此命令则没变化(删除字段在models中注释代码即可完成删除字段)

二、单表操作

(一) 创建表

1 创建模型

2 常用的字段、参数和元信息

#1) 常用字段
	-IntegerField   整数
    -AutoField
    -BooleanField
    -CharField
    -DateField
    -DateTimeField
    -DecimalField
    -FileField   上传文件,本质是varchar
    -ImageField   图片,本质是varchar,继承了FileField
    -TextField   存大文本
    -EmailField   本质是varchar
#2) 非常用字段
	-BigAutoField
    -SmallIntegerField   
    -PositiveSmallIntegerField
    -PositiveIntegerField
    -BigIntegerField
    

"""
    'AutoField': 'integer AUTO_INCREMENT',
    'BigAutoField': 'bigint AUTO_INCREMENT', 
    'BinaryField': 'longblob',
    'BooleanField': 'bool', 
    'CharField': 'varchar(%(max_length)s)', 
    'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',
    'DateField': 'date', 
    'DateTimeField': 'datetime',
    'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)',
    'DurationField': 'bigint',
    'FileField': 'varchar(%(max_length)s)',
    'FilePathField': 'varchar(%(max_length)s)',
    'FloatField': 'double precision',
    'IntegerField': 'integer',
    'BigIntegerField': 'bigint',
    'IPAddressField': 'char(15)',
    'GenericIPAddressField': 'char(39)',
    'NullBooleanField': 'bool',
    'OneToOneField': 'integer',
    'PositiveIntegerField': 'integer UNSIGNED',
    'PositiveSmallIntegerField': 'smallint UNSIGNED',
    'SlugField': 'varchar(%(max_length)s)',
    'SmallIntegerField': 'smallint',
    'TextField': 'longtext',
    'TimeField': 'time',
    'UUIDField': 'char(32)',
"""   
#3) 常用参数
	-null
    -max_length
    -default
    -primary_key
    -unique
    -db_index
    
    # 
    -choices:比较常用(后面再说)
	-blank: django admin里提交数据,限制
        
#4) 元数据
	-必须记住的
    class Meta:
            # 表名
        db_table = "book"
        #联合索引
        index_together = [
            ("name", "publish"),
        ]
        # 联合唯一索引
        unique_together = (("name", "publish"),)
        
   -了解
	    # admin中显示的表名称
        verbose_name='图书表'
        #verbose_name加s
        verbose_name_plural='图书表'        

3 settings配置信息

​ 若想将模型转为mysql数据库中的表,需要在settings中配置:

#1) settings.py
DATABASES = {
     'default': {
         # 配置使用mysql
         'ENGINE': 'django.db.backends.mysql',     # 数据库产品
         'HOST': "localhost",           # 数据库ip
         'PORT': 3306,                  # 数据库端口
         'USER': "root",                # 用户名
         'PASSWORD': "123",           # 密码
         'NAME': "xxx",               # 数据库名
     }
 }
'''
'NAME':    要连接的数据库,连接前需要创建好
'USER':    连接数据库的用户名
'PASSWORD':连接数据库的密码
'HOST':    连接主机,默认本机
'PORT':    端口 默认3306
'ATOMIC_REQUEST': True,
设置为True统一个http请求对应的所有sql都放在一个事务中执行(要么所有都成功,要么所有都失败)。
是全局性的配置, 如果要对某个http请求放水(然后自定义事务),可以用non_atomic_requests修饰器 
'OPTIONS': {
             "init_command": "SET storage_engine=MyISAM",
            }
设置创建表的存储引擎为MyISAM,INNODB
'''
#2) 项目同名文件夹下的 __init__.py中
import pymysql
pymysql.install_as_MySQLdb()
#3) 两条数据库迁移命令即可在指定的数据库中创建表 :
python3 manage.py makemigrations
python3 manage.py migrate
#4) 确保配置文件中的INSTALLED_APPS中写入我们创建的app名称:
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    "book"  # 或者这种形式:'app名字.apps.App01Config',
]

4 增加、删除字段

# 1) 删除,直接注释掉字段,执行数据库迁移命令即可

# 2) 新增字段,在类里直接新增字段,直接执行数据库迁移命令会提示输入默认值,此时需要设置
publish = models.CharField(max_length=12,default='人民出版社',null=True)
# 注意:
——1) 数据库迁移记录都在 app01下的migrations里

——2) 使用showmigrations命令可以查看没有执行migrate的文件

——3)  makemigrations是生成一个文件,migrate是将更改提交到数据量

(二) 添加表记录

# 方式一:使用create方法
# create方法的返回值book_obj就是插入book表中的python葵花宝典这本书籍纪录对象
	book_obj=Book.objects.create(title="python葵花宝典",state=True,price=100,publish="苹果出版社",pub_date="2012-12-12")

# 方式二:对象自己的方法,然后对象.save()。
	book_obj=Book(title="python葵花宝典",state=True,price=100,publish="苹果出版社",pub_date="2012-12-12")
	book_obj.save()

(三) 查询表记录API

#1) 返回queryset对象
<1> all():                  查询所有结果
  
<2> filter(**kwargs):       它包含了与所给筛选条件相匹配的对象 

<4> exclude(**kwargs):      它包含了与所给筛选条件不匹配的对象
 
<5> order_by(*field):       对查询结果排序(默认升序)-表示降序
  
<6> reverse():              对查询结果反向排序  

<11> values(*field):        返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列model的实例化对象,而是一个可迭代的字典序列
    
<12> values_list(*field):   它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列
 
<13> distinct():            从返回结果中剔除重复纪录

#2) 返回数据对象本身
<3> get(**kwargs):          返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。

<8> first():                返回第一条记录
  
<9> last():                 返回最后一条记录

#3) 返回数字
<7> count():                返回数据库中匹配查询(QuerySet)的对象数量。
 
#4) 返回布尔值 
<10> exists():              如果QuerySet包含数据,就返回True,否则返回False
 

代码示例:

# 在脚本中调用djagno服务
import os

if __name__ == '__main__':
    # 1  引入django配置文件
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'day067.settings')
    # 2 让djagno启动
    import django

    django.setup()
    # 3 使用表模型
    from app01 import models

    models.Book.objects.create(name='测试书籍', publish='xx出版社')
    models.Book.objects.create(name='凡人修仙传', publish='古彭出版社')
    models.Book.objects.create(name='神墓', publish='古彭出版社')
    models.Book.objects.create(name='从姑获鸟开始', publish='南京出版社')
    models.Book.objects.create(name='铁血残明', publish='南京出版社')

    for i in range(198):
        models.Book.objects.create(name='重返东京有点热%s' % i, publish='东京出版社')

    # 单表API查询
    # < 1 > all(): 查询所有结果,返回queryset对象,可以看作是列表
    res = models.Book.objects.all()
    print(res)
    print(type(res))  # <class 'django.db.models.query.QuerySet'>

    # < 2 > filter(**kwargs): 过滤 queryset对象的方法
    res = models.Book.objects.filter(name='从姑获鸟开始')
    print(res)  # <QuerySet [<Book: 从姑获鸟开始>]>
    res = models.Book.objects.all().filter(name='从姑获鸟开始')
    print(res)  # <QuerySet [<Book: 从姑获鸟开始>]>
    res = models.Book.objects.all().filter(name='从姑获鸟开始', publish='南京出版社')
    print(res)  # <QuerySet [<Book: 从姑获鸟开始>]>
    print(type(models.Book.objects))  # <class 'django.db.models.manager.Manager'>

    # < 3 > get(**kwargs): queryset对象的方法,返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。
    res = models.Book.objects.all().get(name='从姑获鸟开始')
    res1 = models.Book.objects.get(name='从姑获鸟开始')
    res2 = models.Book.objects.filter().get(name='从姑获鸟开始')
    print(res, type(res), res1, res2)  # 从姑获鸟开始 <class 'app01.models.Book'> 从姑获鸟开始 从姑获鸟开始
    # 返回的数据是——————————————》》》》》》数据对象本身

    # < 4 > exclude(**kwargs): 它包含了与所给筛选条件不匹配的对象,可以继续链式调用
    res = models.Book.objects.exclude(name='从姑获鸟开始')
    print(type(res))  # <class 'django.db.models.query.QuerySet'>

    # < 5 > order_by(*field): 对查询结果排序(默认升序)  加-表示降序
    res = models.Book.objects.all().order_by('id')
    res = models.Book.objects.all().order_by('-id')
    res = models.Book.objects.all().order_by('name', '-id')
    res = models.Book.objects.all().order_by('id', 'name')
    print(res)

    # < 6 > reverse(): 对查询结果反向排序,必须结合order_by使用,对结果进行反转,等同于 ('-i')
    res = models.Book.objects.exclude(name='从姑获鸟开始').order_by('id')
    res = models.Book.objects.exclude(name='从姑获鸟开始').order_by('id').reverse()
    print(res)

    # < 7 > count(): 返回数据库中匹配查询(QuerySet)的对象数量。
    res = models.Book.objects.exclude(name='从姑获鸟开始').count()
    res = models.Book.objects.all().count()
    print(res)
    # 返回的数据是——————————————》》》》》》数字

    # < 8 > first(): 返回第一条记录
    res = models.Book.objects.exclude(name='从姑获鸟开始').first()
    print(res, type(res))  # 测试书籍 <class 'app01.models.Book'>
    # 返回的数据是——————————————》》》》》》数据对象本身

    # < 9 > last(): 返回最后一条记录
    res = models.Book.objects.exclude(name='从姑获鸟开始').last()
    print(res, type(res))  # 测试书籍 重返东京有点热197 <class 'app01.models.Book'>
    # 返回的数据是——————————————》》》》》》数据对象本身

    # < 10 > exists(): 如果QuerySet包含数据,就返回True,否则返回False
    res = models.Book.objects.exclude(name='从姑获鸟开始').exists()
    print(res, type(res))  # True <class 'bool'>
    res = models.Book.objects.filter(name='从姑获鸟开始aaa').exists()
    print(res, type(res))  # False <class 'bool'>
    # 返回的数据是——————————————》》》》》》布尔值

    # < 11 > values(*field): 返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列model的实例化对象,而是一个可迭代的字典序列
    res = models.Book.objects.all().values('name', 'publish')
    print(res, type(res))  # <QuerySet [...]> <class 'django.db.models.query.QuerySet'>
    res = models.Book.objects.all().values('name', 'publish').first()
    print(type(res), res)  # <class 'dict'> {'name': '测试书籍', 'publish': 'xx出版社'}

    # < 12 > values_list(*field): 它与values()非常相似,不同的是它返回的queryset对象内部是一个元组序列,values返回的是一个字典序列
    res = models.Book.objects.all().values_list('name', 'publish')
    print(type(res), res)  # <class 'django.db.models.query.QuerySet'>
    res = models.Book.objects.all().values_list('name', 'publish').first()
    print(type(res), res)  # <class 'tuple'> ('测试书籍', 'xx出版社')

    # < 13 > distinct(): 从返回结果中剔除重复纪录 --->>>在字段未设置唯一或联合唯一时使用
    res = models.Book.objects.all().values('name', 'publish').distinct()
    print(type(res), res)

(四) 基于双下划线的模糊查询

# 基于双下划线的模糊查询
# 1) 在范围内的
    res = models.Book.objects.filter(id__in=[100, 120, 200])
    print(1, res)
# 2) 大于、小于、大于等于、小于等于
    res = models.Book.objects.filter(id__gt=100)
    print(2, res)
    res = models.Book.objects.filter(id__lt=100)
    print(3, res)
    res = models.Book.objects.filter(id__gte=100)
    print(4, res)
    res = models.Book.objects.filter(id__lte=100)
    print(5, res)
# 3) 范围内的
    res = models.Book.objects.filter(id__range=[100, 200])
    print(6, res)
# 4) 包含,忽略大小写包含
    res = models.Book.objects.filter(name__contains="东京")
    print(7, res)
    res = models.Book.objects.filter(name__icontains="东京")
    print(8, res)
# 5) 以XX开头、结尾(name__endswith)
    res = models.Book.objects.filter(name__startswith="神")
    print(9, res)
# 6) 时间类型,年份是2019
    res = models.Book.objects.filter(publish_date__year=2019)
    print(10, res)

(五) 删除表记录

# 删除表记录的两种方式
    # 第一种:queryset的delete方法
    res = models.Book.objects.filter(name='重返东京有点热0').delete()
    print(res)  # (1, {'app01.Book': 1})
    
    # 第二种:对象自己的delete方法
    book = models.Book.objects.filter(name__contains='重返东京').first()
    print(type(book))
    res = book.delete()  # <class 'app01.models.Book'>
    print(res)  # (1, {'app01.Book': 1})

(六) 修改表记录

# 修改表记录的两种方式
    # 第一种:queryset的update方法
    res = models.Book.objects.filter(publish='东京出版社', name='重返东京有点热2').update(name='TokyoHot')
    print(res)  # 1
    
    # 第二种:对象自己的方法
    book = models.Book.objects.filter(publish='东京出版社').last()
    book.name = 'Absolutely_Perfect'
    book.save()

三、在python脚本中调用Django环境

# 在脚本中调用djagno服务
import os
if __name__ == '__main__':
    # 1  引入django配置文件
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', '项目名.settings')
    # 2 让djagno启动
    import django
    django.setup()
    # 3 使用表模型
    from app01 import models
    models.Book.objects.create(name='测试书籍', publish='xx出版社')

四、Django终端打印原生sql

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

五、其他操作补充

(一) 时区和国际化问题

# setting.py中
1) 后台管理汉语问题
	LANGUAGE_CODE = 'zh-hans'  # 管理后台看到的就是中文
2) 时区问题(使用东八区)
	TIME_ZONE = 'Asia/Shanghai'
    USE_TZ = False

(二) blank参数作用

1) 需要把book表注册到admin中
	在app下的admin.py中写
    from app01 import models
	# 把book表注册一些,管理后台就能看到了
	admin.site.register(models.Book)
2) 可以快速的对book表进行增删查改操作 

(三) django admin(管理后台的简单使用)

0) 管理后台是django提供的可以快速对表进行增删查改操作

1) 创建一个后台管理账号
    python3 manage.py createsuperuser
    输入用户名
    输入邮箱(可以不填,敲回车)
    输入密码
    确认密码
    # 超级用户创建出来了,可以登录管理后台了

2) 创建好之后,可以登录admin,但是看不到表,需要在app中的admin注册
	from app01 import models
	admin.site.register(models.Book)

3) admin中表中一行一行的数据显示我们定制的样子
	重写模型类的__str__方法【在models下的数据表类中】
    def __str__(self):  
        return self.name

重写模型类的效果对比:

之前

之后

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值