django之模型层(待补充)

Posted michealjy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了django之模型层(待补充)相关的知识,希望对你有一定的参考价值。

模型层

1. ORM查询

所有代码都是在test.py文件中运行的

注意:我如果想在test.py文件中测试相关代码,那么必须要进行配置,不然会报以下的错误

django.core.exceptions.ImproperlyConfigured: Requested setting DEFAULT_INDEX_TABLESPACE, but settings are not configured. You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings.

意思就是,django本身是一个搭好的框架,你不能单独运行某一个文件,它是一个整体,运行文件前必须要进行环境配置

所以我们的思路就是在test.py文件中,让它一启动改文件,就把相关的环境配置好,于是就加了下面几句

if __name__ == "__main__":
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "one_search.settings")
    import django
    django.setup()
    
## 这几句话的意思就是,启动该文件时,把暴露给用户的配置文件字符串名加到内部环境变量大字典中,然后启动django,就相当于一小型的manage.py启动文件。

查看ORM语句对应的sql语句有两种方式

  1. 如果适合queryset对象,可以直接点query查看
  2. 配置文件中直接配置
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 用query
    from app01 import models
    res = models.Book.objects.all()
    res1 = models.Book.objects.all().query
    print(res)
    print(res1)
    
#<QuerySet [<Book: 科比自传>, <Book: 艾弗森自传>, <Book: 乔布斯自传>, <Book: 扎克伯格自传>, <Book: 马云自传>]>
#SELECT `app01_book`.`id`, `app01_book`.`title`, `app01_book`.`price`, `app01_book`.`publish_date` FROM `app01_book`

## 例2 用配置文件,直接写一句就可以了。
    res = models.Book.objects.all()

#<QuerySet [<Book: 科比自传>, <Book: 艾弗森自传>, <Book: 乔布斯自传>, <Book: 扎克伯格自传>, <Book: 马云自传>]>
#(0.001) SELECT @@SQL_AUTO_IS_NULL; args=None
#(0.001) SELECT `app01_book`.`id`, `app01_book`.`title`, `app01_book`.`price`, `app01_book`.`publish_date` FROM `app01_book` LIMIT 21; args=()

只要是queryset对象就可以无限制的点queryset对象的方法
queryset.filter().filter().filter(),即使queryset对象是空也没关系

2.单表的增删改操作

## 增

    # 方式一

    models.Book.objects.create(title='时间简史',price=123.23,publish_date='2019-10-24')

'''
这样就会往数据库中存入数据,同时打印出sql语句

INSERT INTO 'app01_book'('title', 'price', 'publish_data') VALUES('时间简史', '123.23', '2019-10-24'); args=['时间简史', '123.23', '2019-10-24']
'''
    # 方式二
    
    from datetime import date
    ctime = date.today()
    book_obj = models.Book(title='时间简史', price=123, publish_date=ctime)
    book_obj.save()
    
    #结果和方式一是一样的
    
    

## 改
    
    # 方式一
    
    models.Book.object.filter(pk=1).update(price=999.66)
    
    '''
    会把主键为1的数据的价格改为999.66,同时打印出sql语句
    
    UPDATE 'app01_book' SET 'price'='999.66' WHERE pk=1;
    args=('999.66', 1)
    '''
    
    # 方式二
    
    book_obj = models.Book.object.filter(pk=1).first()
    book_obj.title = '奥尼尔自传'
    book_obj.save()
    
    '''
    打印结果同上,只不过这种效率比较低,会把所有的数据重新保存一遍
    '''


## 删除
    
    models.Book.object.filter(pk=1).delete()

3. 单表查询(13+__)

13+

## 1.all() 查询所有               QuerySet
    res = models.Book.objects.all() #惰性查询
    print(res)
    for i in res:
        print(i.title)

    
    '''
    会先把sql语句打印出来
    
    SELECT 'app01_book'.'id','app01_book'.'title','app01_book'.'price','app01_book'.'publish_date' FROM 'app01_book';
    
        <QuerySet [<Book: 科比自传>, <Book: 艾弗森自传>, <Book: 乔布斯自传>, <Book: 扎克伯格自传>, <Book: 马云自传>, <Book: 时间简史>]>
    科比自传
    艾弗森自传
    乔布斯自传
    扎克伯格自传
    马云自传
    时间简史

    '''   

## 2.filter()

    res = models.Book.object.filter(pk=2)
    print(res)
    
    '''
    就相当于语句: select * from book where id = 2
    '''

## 3.get() #不建议使用,这个是数据对象本身

## 4.first() 拿第一个

## 5.last() 拿最后一个
    res = models.Book.objects.all()
    print(res.first())
    print(res.last())
    
    '''
    sql语句:
        select * from book order by id asc/desc limit 1
        
    '''

## 6.exclude 除此之外

    #先取出id不是1的所有记录,然后再筛选出id为2的值
    res = models.Book.objects.exclude(pk=1).filter(pk=2)
    print(res)|

    """
    sql语句就是:
        select * from book where (not(id=1) and id=2)
    """

## 7.values 列表套字典

    res = models.Book.objects.values('title')
    for r in res:
        print(r.ger('title'))
        
    '''
    返回的是一个一个字典,每个字典是title: 书名
    '''

## 8.values_list  列表套元组

    res = models.Book.objects.values_list('title')
    print(res)
    
    '''
    返回的是一个一个元组,每个元组是 (书名,)
    '''

## 9.count() 统计数据的个数

    res = models.Book.objects.count()
    res1 = models.Book.objects.all().count()
    print(res)
    '''
    返回的是数字,表示有多少个数据,上面两句话是等价的
    '''

## 10.distinct() 去重
    
    """去重:数据必须是一模一样的情况下才能去重"""
    res = models.Book.objects.all().distinct()
    # 上面这句去不了重,因为id不可能一样,因此需要按照其他的字段先筛选出一批,在进行去重就是避免id的干扰
    res1 = models.Book.objects.values('title', 'price').distinct()
    print(res1)
    '''
    sql语句就是:
        select distinct book.title,book.price from book
    '''

## 11.order_by() 排序
    
    res = models.Book.objects.order_by('price')  #默认是升序排序
    res1 = models.Book.objects.order_by('-price') #降序排序
    print(res)
    '''
    sql语句就是:
        select * from book order by 'price' asc
    '''

## 12.reverse() 前面必须是先结果排序才可以反转
    
    res = models.Book.objects.order_by('price').reverse()
    print(res)
    '''
    sql语句就是:
        select * from book order by 'price' desc
    '''

## 13.exists() 
    res = models.Book.objects.filter(pk=1).exists()
    print(res)
    '''
    就是判断是否存在这个记录
    '''

双下划线

# __gt/__lt/__gte/__lte=(大于,小于,大于等于,小于等于)

## 查询价格大于200的书籍
res = models.Book.objects.filter(price__get=200)


# __in=[1,2,3] 在列表中就返回,找到一个即可
res = models.Book.objects.filter(price__in=[200, 123.33])

# __range=(200, 700) 顾头不顾尾,在200-700之间
res = models.Book.objects.filter(price__range=(200, 700))



# 模糊匹配

##查询书籍名称中包含p的
res = models.Book.objects.filter(title__contains='p') #区分大小写

res = models.Book.objects.filter(title__icontains='p') #忽略大小写

##以什么开头/结尾  __startswith / __endswith
res = models.Book.objects.filter(title__startswith='三')

##日期
res = models.Book.objects.filter(publish_date__month='10')
res = models.Book.objects.filter(publish_date__year='2019')

多表操作(增删改和简单的查)

### 一对多字段的增删改查


##增

# 直接传出版社主键值
models.Book.objects.create(title='时间简史', price=123.22, publish_id=1)
'''前提是先在出版社中加入id为1的数据,这样就成功插入'''

# 直接传出版社数据对象
publish_obj = models.Publish.objects.filter(pk=2).first()
models.Book.objects.create(title="科比自传",price=342.44, publish=publish_obj)


##查

book_obj = models.Book.objects.filter(pk=1).first()
print(book_obj.publish) #拿到当前所对应的的出版社对象
print(book_obj.publish_id) #获取表中的实际字段值


##改

models.Book.objects.filter(pk=1).update

多表查询(ORM跨表查询)

#正向查询和反向查询

例如:外键在book表上,book表和publish表是一对多的关系,那么,从book表开始查询,就是正向查询,否则就是反向查询

##记住一句话
    
    正向查询按字段
    反向查询按表名小写(一对多或者多对多时外键不唯一,这时候就需要 小写表名_set.all())
    

## 1.子查询

#1.查询时间简史的出版社名字
book_obj = models.Book.objects.filter(title='时间简史').first()
print(book_obj.publish.name)
print(book_obj.publish.addr)
"""正向查询按字段"""

#2.查询书籍主键是7的作者姓名
book_obj = models.Book.objects.filter(pk=7).first()
print(book_obj.authors)  #会打印app01.Author.None  原因是由很多值,但是只接收了一个
"""正确的是""" print(book_obj.authors.all())

#3.查询作者是michael的手机号
author_obj = models.Author.objects.filter(name='michael').first()
print(author_obj.author_detail.phone)

'''
小总结:
    正向查询按字段, 当该字段所对应的数据有多个的时候,加.all() 否则直接点外键字段拿到的是数据对象
'''

#4.查询出版社是人民出版社出版过的书籍
publish_obj = models.Publish.objects.filter(name='人民出版社').first()
print(publish_obj.book_set.all())

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

##6.查询手机号是234的作者
author_detail_obj = models.AuthorDetail.objects.filter(phone=234).first()
print(author_detail.author.name)


'''
小总结:
    反向查找按照表名的小写形式
        加set的时候是一对多或者多对多,主键值不唯一,小写表名_set.all()
        一对一的时候不需要加任何东西,直接点属性
'''




##2.基于双下划线的跨表查询(是按字段查询的,不是按表名)  连表查询
"""
mysql
    left join
    inner join
    right join
    union
"""

#1.查询书籍是艾弗森自传的出版社名称

#正向
res = models.Book.objects.filter(title="艾弗森自传").values('publish__name')
print(res)
'''
原生sql:
    select publish.name from book inner join publish on (book_id = publish_id) where book.title='艾弗森自传'
'''
#反向
res = models.Publish.objects.filter(book__title='艾弗森自传').values('name')

#2.查询作者是jason的手机号码

#正向
res = models.Author.objects.filter(name='jason').values('author_detail__phone')
print(res)

#反向
res = models.AuthorDetail.objects.filter(author__name='jason').values('phone')

#3.查询手机号是123的作者姓名
##正向
res = models.AuthorDetail.objects.filter(phone=123).values('author__name')

##反向
res = models.Author.objects.filter(author_detail__phone=123).values('name')

#4.查询出版社是东方出版社的书籍名字
#正向
res = models.Publish.objects.filter(name="东方出版社").values('book__title')

#反向
res = models.Book.objects.filter(publish__name='东方出版社').values('title')

#5.查询作者是jason的写过的书的名字和价格
##正向
res = models.Author.objects.filter(name='jason').values('book__title', 'book_price')

##反向
res = models.Book.objects.filter(authors__name='jason').values('title', 'price')
'''反向查找需要到第三张()'''


#6.查询书籍是时间简史的作者的手机号
    res = models.Book.objects.filter(title='时间简史').values('authors__author_detail__phone')
    print(res)

以上是关于django之模型层(待补充)的主要内容,如果未能解决你的问题,请参考以下文章

67django之模型层(model)--查询补充及mookie

django--模型层(orm)-查询补充及cookie

Django基础之模型(models)层

前端之js(待补充)

django之 模型层

Django2.0路由补充之path,re_path及视图层