Django知识整理三(django中orm简介,FBV与CBV, django settings源码分析,模板层相关知识,模型层相关知识)

django orm简介

    orm对象关系映射
    
    类                   数据库的表
    
    对象                  表的记录
    
    对象获取属性          记录的某个字段对应的值
    
    优点:能够让一个不会数据库操作的人 也能够简单快捷去使用数据库
    
    缺点:由于封装程度太高 可能会导致程序的执行效率偏低
    有时候 结合项目需求 可能需要你手写sql语句
    
    注意事项
        1.django的orm不会自动帮你创建库,库需要你自己手动创建
          表会自动帮你创建  你只需要书写符合django orm语法的代码即可
            
            
去应用下所在的models.py中书写类
    
    from django.db import models

 # Create your models here.
 class Userinfo(models.Model):
    # 设置id字段为userinfo表的主键  id int primary key auto_increment
    id = models.AutoField(primary_key=True)  # 在django中 你可以不指定主键字段 django orm会自动给你当前表新建一个名为id的主键字段
    # 设置username字段  username varchar(64)  CharField必须要指定max_length参数
    username = models.CharField(max_length=64)  # 在django orm中 没有char字段  但是django 暴露给用户 可以自定义char字段
    # 设置password字段  password int
    password = models.IntegerField()
    
*****数据库迁移(同步)命令******
python manage.py makemigrations  # 不会创建表 仅仅是生成一个记录  将你当前的操作记录到一个小本本上(migrations文件夹)
    
python manage.py migrate  # 将你的orm语句真正的迁移到(同步)到数据库中
    
    
只要你在models.py中修改了跟数据库相关的代码  你就必须重新开始执行上面两条命令    

FBV与CBV

基于函数/类的视图

        CBV
        写视图函数 必须要写一个类 然后继续View
        from django.views import View
        class MyLogin(View):
            def get(self,request):
                return render(request,'login.html')
            
            def post(self,request):
                return HttpResponse('post请求')
        
        路由配置
        CBV源码
            FBV
                url(r'^index/',views.index)
            CBV
                url(r'^login/',views.MyLogin.as_view())
                # url(r'^login/',views.view)
                            def as_view(cls,*args,**kwargs):
                def view(...):
                    self = cls(...)
                    
                    return self.dispatch(...)
                return view
                            def dispatch(...):
                # 判断当前请求方式在不在八个默认的请求方式中 get post delete options ...
                # 利用反射 获取对象的所对应的属性或者是方法
                # 执行对应方法

django settings源码

django暴露给用户一个自定义配置的文件 
        用户配置了就用用户的 用户没有配置就使用默认的  并且配置文件中的变量名必须是大写才有效
        from django.conf import settings
        
        settings = LazySettings()
        
        class LazySettings(object):
            ...
         
        class Settings(object):
            # 循环获取默认的配置文件中所有的大写配置
            # 利用setattr给对象不停的设置键值对
            # 再循环获取暴露给用户的自定义配置文件中所有的大写的配置
            # 再利用setattr给对象不停的设置键值对
            """字典的键存在的情况 再设值其实就是替换"""

模板层

{{}} 变量相关
{%%} 逻辑相关

模板语法传值
python基本数据类型
如果传递给前端一个函数名 会直接加括号调用 将函数的返回值展示到前端
如果函数有参数 不好意思 django的模板语法 不支持给函数传参
#方法都不能传参
<p>{{ obj }}</p>
<p>{{ obj.get_cls }}</p>
<p>{{ obj.get_func }}</p>
<p>{{ obj.get_self }}</p>


​ 模板语法获取容器类型的数据 只能采用句点符(.)
​ 点索引
​ 点键

{{ l.1 }}


{{ l.3 }}



{{ d.username }}


{{ d.password }}


{{ d.password.1 }}

模板语法之过滤器(|)

过滤器 有点类似于小的方法        
会将|左边的值当作第一个参数传入 右边的当作第二个参数传入
    |add
    |default 
    |length
    |slice
    |truncatechars  # 截字符 三点也算
    |truncatewords  # 按空格截  三点不算
    |filesizeformat
    |safe
<p>{{ n|add:100 }}</p>
<p>{{ n|add:'abc' }}</p>
<p>{{ s|add:'sasahhdasda' }}</p>
<p>{{ l|length }}</p>
<p>{{ d|length }}</p>

{#<p>{{ file_size|filesizeformat }}</p>#}

{#<p>截取10个字符 三个点也算{{ w1|truncatechars:10 }}</p>#}
{#<p>截取10个字符 三个点也算{{ w|truncatechars:10 }}</p>#}
{#<p>安装空格截取单词 三个点不算{{ w1|truncatewords:6 }}</p>#}
{#<p>安装空格截取单词 三个点不算{{ w|truncatewords:6 }}</p>#}
{#<p>安装空格截取单词 三个点不算{{ w2|truncatewords:6 }}</p>#}

{#<p>{{ l|slice:'0:5' }}</p>#}
{#<p>{{ l|slice:'0:5:2' }}</p>#}

{#<p>{{ ctime|date:'Y-m-d' }}</p>#}
{#<p>{{ ctime|date:'Y年/m月' }}</p>#}

{#<p>{{ sss|safe }}</p>#}
{#<p>{{ sss1|safe }}</p>#}
{#<p>{{ res }}</p>#}


​ {#

{{ xo|default:'' }}#}
​ {#有值就拿值 没值就用后面默认的#}
​ 前端
​ |safe
​ 后端
​ from django.utils.safestring import mark_safe

res = mark_safe("<h1>111</h1>")
​ """前端代码不一定必须要在前端写好 也可以再后端写完 传递给前端页面"""
​ 只要思想不滑坡 方法总比困难多

模板语法之标签

{%%}
if判断  后端语法一模一样
{#{% if xo %}#}
{#    <p>xo有值</p>#}
{#{% else %}#}
{#    <p>xo没有值</p>#}
{#{% endif %}#}

{#{% if xo %}#}
{#    <p>xo有值</p>#}
{#{% elif xo1 %}#}
{#    <p>xo1有值</p>#}
{#{% else %}#}
{#    <p>去他大爷的</p>#}
{#{% endif %}#}

for循环
内部提供了一个forloop对象
{#{% for foo in l %}#}
{#    {% if forloop.first %}#}
{#        <p>这是我的第一次</p>#}
{#    {% elif forloop.last %}#}
{#        <p>这是最后一次了啊</p>#}
{#    {% else %}#}
{#        <p>嗨起来 大宝贝~</p>#}
{#    {% endif %}#}
{#{% endfor %}#}


​ {#{% for foo in xo %}#}
​ {#

{{ forloop.counter }}:{{ foo }}

#}
​ {# {% empty %}#}
​ {#

你给我的对象是个空的没法进行for循环

#}
​ {#{% endfor %}#}
​ counter # 1开始
​ counter0 # 0开始
​ first
​ last
​ empty 当for循环对象是个空的时候 就会走empty下面的逻辑

​ with起别名 当一个数据是通过很复杂的方式获取到 好多地方有需要用
​ {#

{{ yyy.user_list.2.username.1 }}

#}

{#{% with  yyy.user_list.2.username.1 as dsb %}#}
{#    <p>{{ dsb }}</p>#}
{#    <p>{{ yyy.user_list.2.username.1 }}</p>#}
{#{% endwith %}#}
        
keys,values,items
{#{% for foo in d.items %}#}
{#    <p>{{ foo }}</p>#}
{#{% endfor %}#}
{##}
{#{% for foo in d.keys %}#}
{#    <p>{{ foo }}</p>#}
{#{% endfor %}#}
{##}
{#{% for foo in d.values %}#}
{#    <p>{{ foo }}</p>#}
{#{% endfor %}#}

自定义过滤器和标签

1.在应用下新建一个名字必须叫templatetags文件夹
2.在该文件夹下新建一个任何名称的py文件
3.在该py文件中 先固定写两行代码
     from django.template import Library
                
     register = Library()
                
     @register.filter(name='过滤器的名字')
     def index(a,b):
     # 过滤器内部逻辑代码
     ...  # ...等价于pass
                
     @register.simple_tag(name='标签的名字')
     def login(a,b,c,*args):
      ...

模板的继承

很多页面的大部分区域长的都差不多的情况下 你可以考虑使用模板的继承
                1,在你想用的那个页面上 通过block事先划定 你将来可能用得到的区域
                    {% block 名字 %}
                        模板内容
                    {% endblock %}
                2,子板需要先继承模板 才能用到该模板中 事先划定的区域
                    {% extends 模板的名字 %}
                    {% block 名字 %}
                        子板内容
                    {% endblock %}
                    
 一个模板页面通常应该有三个区域
                    {% block css %}
                        
                    {% endblock %}
                    
                    
                    {% block content %}
                        
                    {% endblock %}
                    
                    
                    {% block js %}
                        
                    {% endblock %}

模板的导入

通常情况下是将页面上的某一块区域当作一个模块
{% include 模块名 %}

模型层

ORM查询

        """
        如果你向查看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',
                    },
                }}
        
        """
    
    只要是queryset对象就可以无限制的点queryset对象的方法
        queryset.filter().filter().filter()

django测试环境搭建

import os


        if __name__ == "__main__":
            os.environ.setdefault("DJANGO_SETTINGS_MODULE", "one_search.settings")
            import django
            django.setup()
            # 你就可以在下面测试django任何的py文件

把上面代码直接复制到tests.py文件中

单表查询

# 单表操作
# 增删改查
# 增
# models.Book.objects.create(title='西游记',price=123.23,publish_date='2019-10-24')
# from datetime import date# ctime = date.today()
# book_obj = models.Book(title='三国演义',price=666.66,publish_date=ctime)
# book_obj.save()# 改# models.Book.objects.filter(pk=1).update(price=999.66)
# book_obj = models.Book.objects.filter(pk=1).first()
# book_obj.title = '不符合社会主义核心价值观'
# book_obj.save()
# 删除
# models.Book.objects.filter(pk=1).delete()

单表操作 查 的13种方法

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

    # 2.filter()                  QuerySet
    # res = models.Book.objects.filter(pk=2)
    # print(res)

    # 3.get()                        数据对象本身

    # 4.first()     拿第一个
    # res = models.Book.objects.all()
    # print(res)
    # print(res.first())
    #5. last()     拿最后一个
    # res = models.Book.objects.all()
    # print(res)
    # print(res.last())

    # 6.exclude  除此之外        QuerySet
    # res = models.Book.objects.exclude(pk=3).filter(pk=4).filter(pk=1).filter(pk=4)
    #     # # <QuerySet []>
    #     # print(res)

    # 7.values  QuerySet    列表套字典
    # res = models.Book.objects.values('title')
    # for r in res:
    #     print(r.get('title'))


    # 8.values_list  QuerySet    列表套元组
    # res = models.Book.objects.values_list('title')
    # print(res)


    # 9.count()  统计数据的个数
    # res = models.Book.objects.count()
    # res1 = models.Book.objects.all().count()
    # print(res,res1)


    # 10.distinct() 去重
    """去重:数据必须是一模一样的情况下才能去重"""
    # res = models.Book.objects.all().distinct()
    # res1 = models.Book.objects.values('title','price').distinct()
    # print(res1)
    
    # 11.order_by()
    # res = models.Book.objects.order_by('price')  # 默认是升序
    # # res1 = models.Book.objects.order_by('-price')  # 加负号就是降序
    # print(res)
    
    # 12.reverse()  前面必须是先结果排序才可以反转
    # res = models.Book.objects.order_by('price').reverse()
    # print(res)
    
    # 13.exists()  一点卵用没有
    # res = models.Book.objects.filter(pk=1).exists()
    # print(res)

神奇的双下划线查询

    # 查询价格大于200的书籍
    # res = models.Book.objects.filter(price__gt=200)
    # 查询价格小于200的书籍
    # res = models.Book.objects.filter(price__lt=200)
    # print(res)
    # 查询价格大于或者等于200的书籍
    # res = models.Book.objects.filter(price__gte=200)
    # res1 = models.Book.objects.filter(price__lte=200)
    # print(res,res1)

    # 价格是200 或者是123.23 或者666.66
    # res = models.Book.objects.filter(price__in=[200,123.23,666.66])
    # print(res)
    # 价格在200 到700之间的书籍
    # res = models.Book.objects.filter(price__range=(200,666.66))  # 顾头不顾尾
    # print(res)
    
    # 查询书籍名称中包含p的
    # res = models.Book.objects.filter(title__contains='p')  # 区分大小写
    # print(res)
    # 忽略大小写
    # res = models.Book.objects.filter(title__icontains='p')  # 忽略大小写
    # print(res)


    # 查询书籍名称是以三开头的书籍
    # res = models.Book.objects.filter(title__startswith='三')
    # res1 = models.Book.objects.filter(title__endswith='P')
    # print(res1)


    # 查询出版日期是2019年的书籍
    # res = models.Book.objects.filter(publish_date__year='2019')
    # 查询出版日期是10月的书籍
    # res = models.Book.objects.filter(publish_date__month='10')

一对多字段增删改查

    
    # 增
    # models.Book.objects.create(title='三国演义',price=123.23,publish_id=1)       # publish_id直接传出版社主键值

    # publish_obj = models.Publish.objects.filter(pk=2).first()
    # models.Book.objects.create(title='水浒传',price=123.23,publish=publish_obj)  # publish直接传出版社数据对象

    # 查
    # 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(publish_id=3)
    # publish_obj = models.Publish.objects.filter(pk=2).first()
    # models.Book.objects.filter(pk=1).update(publish=publish_obj)

    # 删除
    # models.Publish.objects.filter(pk=2).delete()
    # 默认也是级联更新 级联删除

多对多字段的增删改查


    # 给主键为3的书籍添加两个作者 1 2
    # book_obj = models.Book.objects.filter(pk=3).first()
    # # print(book_obj.authors)  # 就相当于 已经在书籍和作者的关系表了
    # # 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()
    # # book_obj.authors.add(author_obj)
    # book_obj.authors.add(author_obj,author_obj1)
    """
    add() 括号内既可以传数字也可以传数据对象
    并且都支持传多个
    """


    # 修改关系
    # book_obj = models.Book.objects.filter(pk=3).first()
    # # book_obj.authors.set([3,])
    # # book_obj.authors.set([1,3])
    # author_obj = models.Author.objects.filter(pk=1).first()
    # author_obj1 = models.Author.objects.filter(pk=2).first()
    # book_obj.authors.set((author_obj,))
    # book_obj.authors.set((author_obj,author_obj1))
    """
    set() 括号内 既可以传数字也传对象 
    并且也是支持传多个的
    但是需要注意 括号内必须是一个可迭代对象
    """

    # 删
    # book_obj = models.Book.objects.filter(pk=3).first()
    # # book_obj.authors.remove(2)
    # # book_obj.authors.remove(1,2)
    #
    # author_obj = models.Author.objects.filter(pk=1).first()
    # author_obj1 = models.Author.objects.filter(pk=2).first()
    # # book_obj.authors.remove(author_obj)
    # book_obj.authors.remove(author_obj,author_obj1)
    """
    remove() 括号内 既可以传数字也传对象 
    并且也是支持传多个的
    """
    # 清空
    # book_obj = models.Book.objects.filter(pk=3).first()
    # book_obj.authors.clear()
    """clear()括号内不需要传任何参数 直接清空当前书籍对象所有的记录"""

ORM跨表查询

 """
    
        1.子查询
        2.连表查询
        
    正反向的概念
        外键字段在谁那儿 由谁查谁就是正向
        
        谁手里有外键字段 谁就是正向查
        没有外键字段的就是反向
        书籍对象 查  出版社    外键字段在书籍       正向查询
        出版社 查 书籍         外键字段在书籍       反向查询
        
        
        正向查询按字段
        反向查询按表名小写 ...
        
    """

1.基于对象的跨表查询 子查询

    
    # 1.查询书籍是python入门的出版社名称
    # book_obj = models.Book.objects.filter(title='python入门').first()
    # # 正向查询按字段
    # print(book_obj.publish.name)
    # print(book_obj.publish.addr)
    # 2.查询书籍主键是6的作者姓名
    # book_obj = models.Book.objects.filter(pk=6).first()
    # # print(book_obj.authors)  # app01.Author.None
    # print(book_obj.authors.all())
    # 3.查询作者是jason的手机号
    # author_obj = models.Author.objects.filter(name='jason').first()
    # print(author_obj.author_detail.phone)
    # print(author_obj.author_detail.addr)
    """
    正向查询 按字段 
    当该字段所对应的数据有多个的时候 需要加.all()
    否者点外键字段直接就能够拿到数据对象
    """
    # 4.查询出版社是东方出版社出版过的书籍
    # publish_obj = models.Publish.objects.filter(name='东方出版社').first()
    # # print(publish_obj.book_set)  # app01.Book.None
    # print(publish_obj.book_set.all())
    # 5.查询作者是jason写过的所有的书
    # author_obj = models.Author.objects.filter(name='jason').first()
    # # print(author_obj.book_set)  # app01.Book.None
    # print(author_obj.book_set.all())
    # 6.查询手机号是110的作者
    # author_detail_obj = models.AuthorDetail.objects.filter(phone=110).first()
    # print(author_detail_obj.author)
    # print(author_detail_obj.author.name)
    # print(author_detail_obj.author.age)
    """
    反向查询按表名小写 
        什么时候需要加_set.all()
            当查询的结果可以是多个的情况下 需要加_set.all()
        什么时候不需要加_set.all()
            当查询的结果有且只有一个的情况下 不需要加任何东西 直接表名小写即可
    """
    # 7.查询书籍是python入门的作者的手机号
    # book_obj = models.Book.objects.filter(title='python入门').first()
    # print(book_obj.authors.all())

    
    

2.基于双下划綫的跨表查询 连表查询

"""
    MySQL
        left join
        inner join
        right join
        union
    """
    # 1.查询书籍是python入门的出版社名称
    # 正向
    # res = models.Book.objects.filter(title='python入门').values('publish__name')
    # print(res)
    # 反向
    # res = models.Publish.objects.filter(book__title='python入门').values('name')
    # print(res)


    # 2.查询作者是jason的手机号码
    # 正向
    # res1 = models.Author.objects.filter(name='jason').values('author_detail__phone')
    # print(res1)
    # 反向
    # res = models.AuthorDetail.objects.filter(author__name='jason').values('phone','author__age')
    # print(res)



    # 3.查询手机号是120的作者姓名

    # res2 = models.AuthorDetail.objects.filter(phone=120).values('author__name')
    # print(res2)
    # res = models.Author.objects.filter(author_detail__phone=120).values('name','author_detail__addr')
    # print(res)


    # 4.查询出版社是东方出版社出版的书籍名称
    # res = models.Publish.objects.filter(name='东方出版社').values('book__title','addr')
    # print(res)
    # 5.查询作者是jason的写过的书的名字和价格
    # res = models.Author.objects.filter(name='jason').values('book__title','book__price')
    # print(res)

    # 7.查询书籍是python入门的作者的手机号
    # res = models.Book.objects.filter(title='python入门').values('authors__author_detail__phone')
    # print(res)

聚合查询

    """
  
    
    关键字:aggregate
    """
    from django.db.models import Max,Min,Count,Sum,Avg
    # 统计所有书平均价格
    # res = models.Book.objects.all().aggregate(Avg('price'))
    # res1 = models.Book.objects.all().aggregate(Max('price'))
    # res2 = models.Book.objects.all().aggregate(Min('price'))
    # res3 = models.Book.objects.all().aggregate(Sum('price'))
    # res4 = models.Book.objects.all().aggregate(Count('title'))
    # res5 = models.Book.objects.all().aggregate(Avg('price'),Max('price'),Min('price'),Sum('price'),Count('title'))
    # print(res5)


    

分组查询

"""
    
        
    关键字:annotate
    """
    # 1.统计每一本书的作者个数
    # res = models.Book.objects.annotate(author_num = Count('authors')).values('author_num')
    # print(res)

    # 2.统计出每个出版社卖的最便宜的书的价格
    # res = models.Publish.objects.annotate(price_min=Min('book__price')).values('price_min')
    # print(res)

    # 3.统计不止一个作者的图书
    """
    1.统计每本书对应的作者个数
    2.基于上面的结果 筛选出作者个数大于1 的
    
    """
#res=models.Book.objects.annotate(author_num=Count('authors')).filter(author_num__gt=1).values('author_num')
    # print(res)

    # 4.查询各个作者出的书的总价格
    # res = models.Author.objects.annotate(sum_price=Sum('book__price')).values('sum_price')
    # print(res)

F与Q查询

我们之前在查询数据库的时候条件都是我们自己手写的
但是现在出现了条件是从数据库里面获取的

F查询

 """

    """
   
    from django.db.models import F,Q
    # 1.查询出卖出数大于库存数的书籍
    # res = models.Book.objects.filter(maichu__gt=F('kucun'))
    # print(res)

    # 2.将所有的书的价格 全部提高100块
    # models.Book.objects.update(price=F('price') + 100)

    # 3.了解  尝试着将所有的书的名字后面都加上 爆款


   

    # Q查询进阶用法   用Q产生对象 然后再使用
    # q = Q()
    # q.connector = 'or'
    # q.children.append(('title__icontains','p'))
    # # q.children.append(('kucun',666))
    # res = models.Book.objects.filter(q)
    # print(res)
    """
    字符串的左边 跟你的变量名条件书写一模一样
    """

    # 惰性查询
    # res = models.Book.objects.all()
    # res = models.Book.objects.values('title')
    # res = models.Book.objects.only('title')
    # for r in res:
    #     # print(r.title)
    #     print(r.price)
    """
    only会将括号内的字段对应的值 直接封装到返回给你的对象中  点该字段 不需要再走数据库
    一旦你点了不是括号内的字段  就会频繁的去走数据库查询
    """

    # res = models.Book.objects.defer('title')  # defer和only互为反关系
    # for r in res:
    #     print(r.title)
    """
    defer会将括号内的字段排除之外将其他字段对应的值 直接封装到返回给你的对象中  点该其他字段 不需要再走数据库
    一旦你点了括号内的字段  就会频繁的去走数据库查询
    """

Q查询

 """
    
    """
    # 1.查询书籍名称是python入门或者价格是544.44的书
    # res = models.Book.objects.filter(title='python入门',price=544.44)
    # res = models.Book.objects.filter(Q(title='python入门'),Q(price=544.44))  # 逗号就是and
    # res = models.Book.objects.filter(Q(title='python入门')|Q(kucun=666))  # 用来Q之后 就能够支持|表示或
    # res = models.Book.objects.filter(~Q(title='python入门')|Q(kucun=666))  # esc下面那个键 波浪号  表示非
    # print(res)

常见字段及参数

        AutoField(primary_key=True)
        CharField(max_length=32)   varchar(32)
        IntegerField()             int
        BigIntegerField()          long
        DateField()
            auto_now:每次修改数据的时候 都会更新该字段
            auto_now_add:只在创建数据的时候 才会自动将创建时间添加 后续不会再自动修改了
        DecimalField()
        BooleanField(Field)
            - 布尔值类型
            该字段在存储数据的时候 你只需要传布尔值即可
            对应到数据库中 会变成0/1
        TextField(Field)
            - 文本类型
            存大段文本
        EmailField(CharField)               varchar(...)
        FileField(Field)
            - 字符串,路径保存在数据库,文件上传到指定目录
            - 参数:
                upload_to = ""      上传文件的保存路径
                storage = None      存储组件,默认django.core.files.storage.FileSystemStorage

        DecimalField(Field)
        - 10进制小数
        - 参数:
            max_digits,小数总长度
            decimal_places,小数位长度

自定义char字段

# 自定义char类型字段
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):
        return 'char(%s)'%self.max_length
    
    
   如果你使用的是django2.X版本 你在建数据库表关系的时候
   你需要手动指定两个参数
   (你要手动告诉django  级联更新 级联删除  是否建外键约束)
        
        on_delete
        db_constraint

查询与优化

惰性查询

 
    # res = models.Book.objects.all()
    # res = models.Book.objects.values('title')
    # res = models.Book.objects.only('title')
    # for r in res:
    #     # print(r.title)
    #     print(r.price)
    """
    only会将括号内的字段对应的值 直接封装到返回给你的对象中  点该字段 不需要再走数据库
    一旦你点了不是括号内的字段  就会频繁的去走数据库查询
    """

    # res = models.Book.objects.defer('title')  # defer和only互为反关系
    # for r in res:
    #     print(r.title)
    """
    defer会将括号内的字段排除之外将其他字段对应的值 直接封装到返回给你的对象中  点该其他字段 不需要再走数据库
    一旦你点了括号内的字段  就会频繁的去走数据库查询
    """
    # select_related
    
    # res = models.Book.objects.select_related('publish')
    # res1 = models.Author.objects.select_related('author_detail')
    # # res = models.Book.objects.all()
    # for r in res1:
    #     print(r.author_detail)
    #     print(r.author_detail.phone)
    #     print(r.author_detail.addr)
    """
    select_related 会自动帮你做连表操作 然后将连表之后的数据全部查询出来封装给对象
    
    select_related括号内只能放外键字段
        并且多对多字段不能放
        
    如果括号内外键字段所关联的表中还有外键字段 还可以继续连表
            select_related(外键字段__外键字段__外键字段...)

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

    """
    prefetch_related  看似连表操作  其实是类似于子查询
    prefetch_related括号内只能放外键字段
        并且多对多字段不能放
        
    如果括号内外键字段所关联的表中还有外键字段 还可以继续连表
            select_related(外键字段__外键字段__外键字段...)
    """

"""
第一个 内部自动连表 消耗的资源就在连表上   但是走数据库的次数较少

第二个 内部不做连表 消耗的资源就在查询次数上  但是给用户的感觉跟连表操作一样



"""
# django中如何开启事务
from django.db import transaction
with transaction.atomic():    
    # 在该代码块中所写的orm语句 同属于一个事务
    # 缩进出来之后自动结束
    #事务的特性: ACID
            原子性
            一致性
            隔离性
            持久性

猜你喜欢

转载自www.cnblogs.com/asyouwish/p/11762704.html