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

Django模型层

时间:2022-11-27 21:46:00浏览次数:39  
标签:Book name models 模型 Django filter objects 查询

Django模型层

目录

测试脚本

# 如果只想测试django中某一个py文件,则不用书写全部前后端交互的代码,而是直接写一个脚本即可
# 测试环境准备,在test.py中:
import os

if __name__ == '__main__':
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'django模型层.settings') #修改项目名
    import django
    django.setup()
    # 此处写测试代码,注意缩进

单表操作

from app01 import models
    # 增
    # models.User.objects.create(name='jason',age=19,register_time=timezone.now()) #返回被创建的对象
    # user_obj = models.User(name='egon',age=20,register_time='2020-11-11')
    # user_obj.save()

    # 删
    # res = models.User.objects.filter(pk=2).delete() #批量删除
    # del_obj = models.User.objects.filter(pk=3).first()
    # del_obj.delete() #单独删除

    # 改
    # models.User.objects.filter(pk=4).update(name='egon') #批量改

    # 查
    '''
    1.all() 查询所有
    2.filter() 带有过滤条件查询
    3.get() 查询数据对象,条件有误直接报错
    4.first() 拿QuerySet第一个元素
    5.last() 拿QuerySet第一个元素
    6.values() 

    res = models.User.objects.values('name','age)
    返回仅带有指定字段的QuerySet(列表套字典)

    7.values_list()

    res = models.User.objects.values_list('name','age)
    返回仅带有指定字段的QuerySet(列表套元组)
    print(res.query) QuerySet对象可以使用.query查看内部sql语句

    8.distinct()
    去重一定要是一模一样的数据,所以要排除主键

    9.order_by()
    res = models.User.objects.order_by('age')
    默认升序
    res = models.User.objects.order_by('-age') 降序

    10.reverse()
    先排序,后翻转

    11.count()
    res = models.User.objects.count()
    12.exclude()
    res = models.User.objects.exclude(name='jason)
    排除符合参数条件的记录
    13.exists()
    res = models.User.objects.filter(name='jason).exists()
    '''

查看内部sql语句的方式

# 一、QuerySet对象可以使用.query查看内部sql语句
res = models.User.objects.values_list('name','age)
print(res.query)
# 二、配置settings.py
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console':{
            'level':'DEBUG',
            'class':'logging.StreamHandler',
        },
    },
    'loggers': {
        'django.db.backends': {
            'handlers': ['console'],
            'propagate': True,
            'level':'DEBUG',
        },
    }
}

双下划线查询

res = models.User.objects.filter(age__gt=20) # 年龄大于20
res = models.User.objects.filter(age__lt=20) # 年龄小于20
res = models.User.objects.filter(age__gte=20) # 年龄大于等于20
res = models.User.objects.filter(age__in=[10,20,30]) # 年龄等于10或者20或者30
res = models.User.objects.filter(age__range=[18,40]) # 年龄大于等于18小于等于40
res = models.User.objects.filter(name__contains='n') # name字段包含'n'的,默认区分大小写
# 忽略大小写:
res = models.User.objects.filter(name__icontains='n')
# ignore
res = models.User.objects.filter(name__startwith='n') # name字段以'n'开头的
res = models.User.objects.filter(name__endwith='n')

res = models.User.objects.filter(register_time__month='12') # 注册时间为12月份的
# 好多方法自己点出来看啊

外键增删改

# 一对多外键增删改
# 增
models.Book.objects.create(name='三国',price=123.23,publish_id=1)

pub_obj = models.Publish.objects.filter(pk=3).first()
models.Book.objects.create(name='红楼', price=123.00, publish=pub_obj)

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

# 改
models.Book.objects.filter(pk=5).update(publish_id=4)
models.Book.objects.filter(pk=5).update(publish=pub_obj)


# 多对多外键增删改,即对中间表的操作
# 增

book_obj = models.Book.objects.filter(pk=1).first()
book_obj.authors.add(1,6,7)

book_obj = models.Book.objects.filter(pk=2).first()
author_obj1 = models.Author.objects.filter(pk=2).first()
author_obj2 = models.Author.objects.filter(pk=6).first()
book_obj.authors.add(author_obj1,author_obj2)

# 删
book_obj = models.Book.objects.filter(pk=1).first()
book_obj.authors.remove(7) # 同样可以传对象,支持多个

# 改

book_obj = models.Book.objects.filter(pk=1).first()
book_obj.authors.set([1,8])# 参数需要是可迭代对象,参数内同样可以传对象,支持多个,set不会改变与参数重复的原纪录,会删去不在参数中的纪录,不回收主键值,另新建只在参数中有的纪录

# 清空,即在中间表中清空某本书籍与作者的绑定关系
book_obj = models.Book.objects.filter(pk=5).first()
book_obj.authors.clear() # 无需传参

正反向

# 正向 由外键所在表向外键关联表查询即为正向
# 反向 由外键关联表向外键所在表查询即为反向

多表查询

# 基于对象的跨表查询,即子查询,正向查询用字段,反向查询用小写表名

models.Book.objects.filter(pk=1).first().publish.name # 查图书表主键为一的书的出版社

models.Book.objects.filter(pk=1).first().authors.all() # 查符合条件的书籍的所有作者

pub_obj = models.Publish.objects.filter(name='东方出版社').first()
pub_obj.book_set.all() # 查询东方出版社出版的书籍

# 反向查询时,当查询结果有可能有多个时,需要_set.all(),一对一结果不需要

# 基于双下划线的跨表查询,即连表查询
models.Author.objects.filter(name='吴承恩').values(‘name','author_info__phone') #查询吴承恩手机号,返回QuerySet

# 可以将返回的QuerySet当做mysql中的结果表,返回的一个不可分对象当做一条记录。
# filter()中的字段名作为关键字不需用'',而values中的字段名需要''                                   

# publish是虚拟字段,publish_id是django自动添加后缀在mysql生成的字段,.publish返回的是此外键关联的publish对象,而.values('publish_id')返回的是该条记录此字段的值

聚合查询

from django.db.models import Max,Min,Sum,Count,Avg # 一般情况下与分组查询一起使用
#单独使用聚合查询 aggregate

分组查询

# annotate
models.Book.objects.annotate(a_num=Count('authors')).values('name','a_num') #查询每本书的作者数量
print(models.Book.objects.aggregate(Avg('price'))
print(models.Book.objects.annotate(a_num=Count('authors')).values('name','a_num'))
     print(models.Publish.objects.annotate(l_price=Min('book__price')).values('name','l_price'))
     print(models.Book.objects.annotate(a_num=Count('authors')).filter(a_num__gt=1).values('name','a_num'))
     print(models.Author.objects.annotate(amount=Sum('book__price')).values('name','amount'))

# 按照字段分组查询
models.Author.objects.values('price').annotate()

F与Q查询

# F('') 直接获取表中某字段的数据返回到代码位置
# 
from django.db.models.functions import Concat
from django.db.models import Value
models.Book.objects.update(name=Concat(F('name'),Value('文学大师推荐')))
from django.db.models import Q
   print(models.Book.objects.filter(Q(sold__gt=2000)|Q(price__lt=100)).values('name','sold','price')) # or=|,and=,,not=~

q = Q()
q.connector = 'or' # 设置条件连接关系
q.children.append(('sold__gt',2000)) # 设置比较条件,注意传入的是一个元组
q.children.append(('price__lt',100))
print(models.Book.objects.filter(q).values('name','sold','price'))
# 即SELECT `app01_book`.`name`, `app01_book`.`sold`, `app01_book`.`price` FROM `app01_book` WHERE (`app01_book`.`sold` > 2000 or `app01_book`.`price` < 100) LIMIT 21; args=(2000, Decimal('100'))

开启事务

# 事务的ACID:原子性,一致性,隔离性,持久性
# 事务的回滚rollback、确认commit
from django.db import transaction
with transaction.atomic():
    # 内部所有ORM操作同属于一个事务 

ORM常用字段及参数

AutoField #主键字段 primary_key=True
CharField #即varchar verbose字段注释,max_lenth长度
IntegerField #即int
BigIntegerField #即BigInt
DecimalField #max_digits,decimal_places
EmailField #varchar(254)
DateField #即Date auto_now/auto_now_add
DateTimeField #即DateTime
BooleanField #即布尔值,传False/True,存0/1
TextField #没有字数限制
FileField #upload_to '' 
# 自定义字段
# class MyCharField(models.Field):
#     def __init__(self,max_length,*args,**kwargs):
#         self.max_length=max_length
#         super().__init__(max_length=max_length,*args,**kwargs)
#
#     def db_type(self,connection):
#         '''
#         返回真正的数据类型及约束条件
#         :param connection:
#         :return:
#         '''
#         return f'char({self.max_length})'


#null:即是否可以为空
#unique:是否唯一
#db_index:为字段建立索引
#default:设置字段默认值
#外键字段
#to_field:默认关联另一张表的主键字段
#on_delete:2.x一对多一对一需要手动设定级联

数据库查询优化

# ORM惰性查询,如果查询结果没有被使用,则不执行查询语句
# only/defer
models.Book.objects.only('name') # 返回包含name字段信息的对象组成的QuerySet,但仍可以.其他字段,只不过会重新查询数据库
models.Book.objects.defer('name') # 返回不包含name字段信息的对象组成的QuerySet,但仍可以.name字段,只不过会重新查询数据库

#only与defer一种是返回只包含参数字段对象组成的QuerySet,一种是返回不包含参数字段对象组成的QuerySet,如果要使用.字段访问信息,则当返回的QuerySet中没有此字段信息时需要重新查询数据库


# select_related(连表查询)/prefetch_ralated(子查询)

res = models.Book.objects.all()
for i in res:
    print(i.publish.name) # 每循环一次都查询一次数据库

res = models.Book.objects.select_related('publish') # 只在这里连表查询一次数据库、参数只能是一对多一对一外键字段,只支持正向查询
for i in res:
    print(i.publish.name) # 这里使用上面的连表查询结果,不用每次都查询数据库

res = models.Book.objects.prefetch_related('publish')
for i in res:
    print(i.publish.name)

# 要结合具体需求,选择查询方法,select_related返回的对象结果可能过大,而prefetch_related查询的次数可能更多。

图书管理系统

# redirect参数可以直接传URL别名,但使用带正则的别名必须使用reverse()
# 见项目代码

choices参数

# 如果某个字段的值是可以列举完全的,那么通常会采用choices参数
gender_choices = (
    (1,'男'),
    (2,'女'),
    (3,'其他')
)
gender = models.IntegerField(choices=gender_choices) # 该gender字段仍存数字,但是如果数字值在gender_choices内,那么可以轻松获取数字对应的真正内容,字段类型由元组内第一个参数类型决定

# gender字段可以存储不在gender_choices内的值,范围参考数据类型

# 获取对应信息 get_字段名_display
user_obj = models.User.objects.filter(pk=1).first()
user_obj.get_gender_display()
# 如果无对应值,则返回原值

MTV与MVC模型

# MTV,即models、templates、views
# MVC,即models、views、controller

多对多三种创建方式

class BooK
class Author

# 全自动:利用ORM自动创建中间表,可以使用ORM封装好的操作,但无法使用ORM拓展
authors = models.ManyToManyField(to='Author')

# 半自动:可以使用ORM正反向查询,但无法使用add、set、remove、clear四个方法,为了拓展性,一般半自动
class Book2Author(models.Model):
    book = models.ForeignKey(to='Book')
    author = models.ForeignKey(to='Author')
class Book
    authors = models.ManyToManyField(to='Author',through='Book2Author',through_field=('book','author')) # 元组顺序由中间表查询本表、被连接表的键决定,可以判断为先自后它



# 全手动:手动创建表,无法使用ORM封装好的操作,容易拓展
class Book_Author(models.Model):
    book = models.ForeignKey(to='Book')
    author = models.ForeignKey(to='Author')

标签:Book,name,models,模型,Django,filter,objects,查询
From: https://www.cnblogs.com/missfxy/p/16930671.html

相关文章

  • Django模板层
    Django模板层目录Django模板层模板语法传值过滤器标签自定义过滤器、标签、inclusion_tag模板的继承模板的导入模板语法传值#模板语法形式:1.{{变量相关}}2.{%逻辑......
  • Django初识
    Django初识目录Django初识基本操作项目主要文件介绍初始技巧静态文件配置Request对象form表单request.methodrequest.POSTrequest.GETpycharm连接数据库(MySQL)django连接数......
  • Django路由层
    Django路由层目录Django路由层路由匹配无名分组有名分组反向解析无名分组反向解析有名分组反向解析路由分发名称空间伪静态虚拟环境null路由匹配#url方法第一个参数是......
  • Django版本差异
    Django版本差异#一、路由层'''django1.x路由层使用url方法django2.x/3.x路由层使用path方法可以根据习惯使用re_pathpath方法支持5种转换器'''fromdjango.ur......
  • Django-ORM简介
    DjangoORM目录DjangoORM字段的增删改查数据的增删改查创建表关系null#即对象关系模型#类——表#对象——记录#对象属性(值)——记录某个字段(值)#在models.py中写......
  • 拓端tecdat|R语言代码编写析因设计分析:线性模型中的对比
    R语言析因设计分析:线性模型中的对比 对比度可用于对线性模型中的处理进行比较。常见的用途是使用析因设计时,除析因设计外还使用控制或检查处理。在......
  • 拓端tecdat|R语言编程指导预测人口死亡率:用李·卡特模型、非线性模型进行平滑估计
    R语言预测人口死亡率:用李·卡特模型、非线性模型进行平滑估计​  今天早上,我和同事一起分析死亡率。我们在研究人口数据集,可以观察到很多波动性。......
  • 拓端tecdat|R语言编程指导LME4混合效应模型研究教师的受欢迎程度
    R语言LME4混合效应模型研究教师的受欢迎程度 ​ 介绍本教程对多级回归进行了基本介绍。  本教程期望:多级分析的基础知识。R中编码的基础知识......
  • 拓端tecdat|R语言编程指导马尔可夫区制转换模型Markov regime switching
    R语言马尔可夫体制转换模型Markovregimeswitching​ 总览本文简要介绍了一种简单的状态切换模型,该模型构成了隐马尔可夫模型(HMM)的特例。这些模型......
  • 拓端tecdat|python3编程指导用ARIMA模型进行时间序列预测
    python3用ARIMA模型进行时间序列预测ARIMA模型是一种流行的且广泛使用的用于时间序列预测的统计方法。ARIMA是首字母缩写词,代表自动回归移动平均。......