第9章 Django框架

一. Django简介

1. 谈谈你对web框架的认识,简述web框架请求流程

1. 浏览器发起HTTP请求
2. wsgiref模块对解析HTTP格式的数据封装成处理成大字典
    2.1 如果需要立即返回数据. 将数据打包成HTTP格式, 在返回给浏览器
    2.2 如果需要进行2次处理. 将到urls.py文件.
3. 到urls.py文件查找路由与用户视图函数对于关系找到对应的视图函数
4. 找到视图函数views.py中函数执行功能
    4.1 如果是需要返回静态HTML页面, 直接返回给wsgiref中. 由其返回给浏览器
    4.2 如果是需要返回动态HTML页面, 使用jinja2模板语法, 将数据赋值给变量传入需要操作的HTML中, 进行操作
    操作完毕以后返回给wsgiref中. 由其返回给浏览器
    4.3 如果是需要返回动态HTML页面, 且页面中数据来自于数据库. 使用pymysql模块链接数据库,
    再使用jinja2模板进行渲染, 渲染完毕以后返回给wsgiref中. 由其返回给浏览器
5. 数据库提供数据

2. python三大主流web框架的区别

# Django:
    特点: 大而全 类始于航空母舰
    不足之处: 有时候过于笨重

# Flask:
    特点: 小而精 类始于游骑兵
        第三方的模块特别多, 如果将所有的第三方模块加起来, 功能完全超过Django, 并且也越来越像Django
    不足之处: 比较依赖于第三方开发者

# Tornado:
    特点: 异步非阻塞 可以支持百万级别高并发

SANIC
FASKAPI
...

# web框架的三部分组成
    A: socket
    B: 路由与视图函数对应关系
    C: 模板语法
    Django:   A使用wsgiref   B使用自己   C使用自己, 比jinja2稍差
    Flask:    A使用werkzeug, 内部还是使用wsgiref   B使用自己  C使用jinja2
    Tornado:  ABC都是使用自己

3. 如何验证django是否安装成功? 命令行如何创建django项目? 如何启动django项目? 与pycharm创建django项目的区别?

# 验证django是否安装成功的2种方法:
    方法一: 配置了环境变量前提下. 命令行输入 django-admin
    方法二: 进入交互式命令行输入导入django
        import django
        django.get_version()

# 创建django项目
    命令行创建:  创建当前路径下. django-admin startproject 项目名
    pycharm创建:

# 启动django项目
    命令行启动:  在配置了python解释器环境变量前提下, 切换到项目文件下.  python3 manage.py runserver host:port
    pycharm启动:

# 命令行创建与pycharm创建django项目的区别
    命令行创建:  不会创建templates文件
        你需要手动到setting.py配置文件中找到TEMPLATES中的DIRS对应的[]中添加os.path.join(BASE, templates)路径
    pycharm创建: 可以动态指定创建templates文件(默认创建)
        会自动帮你在setting.py配置文件中找到TEMPLATES中的DIRS对应的[]中添加os.path.join(BASE, templates)路径

4. 什么是app,django中如何创建app,需要注意什么?

# app
    app就是对应的一种功能. 例如: 选课系统

# 创建app: app因该见名知意
    命令行创建: 在配置了python解释器环境变量前提下, 切换到项目文件下. python3 manage.py startapp 应用app名
        不会帮你注册. 需要手动注册.
            到setting.py配置文件中找到INSTLLED_APPS注册.
            注册的2种方式: 例如你的应用名为app01. 第一种方式: 'app01.apps.App01Config' 第二种方式: 'app01'
    pycharm创建: 可以动态指定创建templates文件(默认创建)
        在创建django项目时可以指定创建一个Application. 不过只能指定一个. 如果后续需要创建应用, 任然需要执行上面命令行式的注册方式.

5. 什么是静态文件? django静态文件配置如何配置? 如何解决接口前缀不断变化, html页面上路径的引用需要反复修改的问题?

# 什么是静态文件?
    已经写好功能的文件, 可以拿来就直接使用的文件
    例如: js, css, img, 前端第三方框架 ...

# django静态文件配置如何配置
    提示: django项目默认不会帮你创建静态文件, 需要手动创建. 约定熟成文件名为 static
    到settings.py中找到STATIC_URL. 并在其下面添加上
    STATICFILES_DIRS = [
        os.path.join(BASE_DIR, '创建的静态文件'),
        os.path.join(BASE_DIR, '创建的静态文件2'),
    ]

# 如何解决接口前缀不断变化,html页面上路径的引用需要反复修改的问题
   在templates管理的html文件中, 在head引用外部资源之前以如下书写方式:
   {% load static %}
   <script src="{% static '静态文件中的文件路径' %}"></script>

6. 列举常见的状态码。

1xx: 指示信息   表示请求已经接收, 继续处理
2xx: 成功      表示请求已经被成功接收, 理解, 接受
3xx: 重定向     表示要完成请求ixu进行更进一步的操作
4xx: 客户端错误  表示请求有语法错误或者请求无法实现
5xx: 服务端错误  表示服务器无法实现合法的亲求

常见状态码:
200 OK                        //客户端请求成功
400 Bad Request               //客户端请求有语法错误,不能被服务器所理解
401 Unauthorized              //请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用
403 Forbidden                 //服务器收到请求,但是拒绝提供服务
404 Not Found                 //请求资源不存在,eg:输入了错误的URL
500 Internal Server Error     //服务器发生不可预期的错误
503 Server Unavailable        //服务器当前不能处理客户端的请求,一段时间后可能恢复正常

更多状态码: http://www.runoob.com/http/http-status-codes.html

6-1. 301和302的区别

3xx开头都是重定向.
301表示的是永久用定向
    301表示旧地址A的资源已经被永久地移除了(这个资源不可访问了),搜索引擎在抓取新内容的同时也将旧的网址交换为重定向之后的网址;
302表示的是暂时重定向.
    302表示旧地址A的资源还在(仍然可以访问),这个重定向只是临时地从旧地址A跳转到地址B,搜索引擎会抓取新的内容而保存旧的网址。

7. 下面关于http协议中的get和post方式的区别,那些是错误的?(多选)

A. 它们都可以被收藏, 以及缓存         
B. get请求参数放在url中              
C. get只用于查询请求,不能用于数据请求  
D. get不应该处理敏感数据的请求        


# 答案: B,D

# GET
    GET请求可被缓存
    GET请求保留在浏览器历史记录中
    GET请求可被收藏为书签
    GET请求不应在处理敏感数据时使用
    GET请求有长度限制(最多只能是1024字节)
    GET请求只应当用于取回数据

# POST
    POST请求不会被缓存
    POST请求不会保留在浏览器历史记录中
    POST不能被收藏为书签
    POST请求对数据长度没有要求

参考网址: https://www.runoob.com/tags/html-httpmethods.html

8. WSGI, uwsgi, uWSGI, wsgiref, werkzeug

# WSGI: 通信规范
    英文全称:Web Server Gateway Interface,
    Web服务网管接口,简单来说它是一种Web服务器和应用程序间的通信规范。

# uwsgi: 通信协议
    uwsgi是一种通信协议,不过跟WSGI分属两种东西,该协议下速度比较快。

# uWSGI:
    uWSGI是一个Web Server,并且独占uwsgi协议,
    但是同时支持WSGI协议、HTTP协议等,
    它的功能是把HTTP协议转化成语言支持的网络协议供python使用。

# wsgiref:
    wsgiref则是官方给出的一个实现了WSGI标准用于演示用的简单Python内置库,
    它实现了一个简单的WSGI Server和WSGI Application(在simple_server模块中)

# werkzeug
    werkzeug 不是一个web服务器,也不是一个web框架,而是一个工具包,
    官方的介绍说是一个 WSGI 工具包,它可以作为一个 Web 框架的底层库,
    因为它封装好了很多 Web 框架的东西,werkzeug,
    本质上就是编写一个socket服务端,用于接收用户请求(flask),
    和django中的wsgiref是类似的。

参考网址: https://www.cnblogs.com/liuweida/p/11717683.html

9. django的请求生命周期?

10. django是什么模型的框架,简述MTV与MVC模型

MTV 全称 Models Templates Views  模型模板视图
MVC 全称 Models Views Controller 模型视图控制

Django号称MTV. 本质还是MVC

二. 路由控制

1. 无名、有名分组各是什么意思, 有什么注意事项?(待定)

# 无名分组: 无须定义名字
    路由书写: url('^index/(\d+)', views.index)
    内部逻辑: 括号内正则表达式匹配到的内容将会当作位置参数传递给与之绑定的视图函数index
    视图函数:
        def index(request, xxx):
            pass

# 有名分组: 需定义名字
    路由书写: url('^index/(?P<year>\d+)', views.index)
    内部逻辑: 括号内正则表达式匹配到的内容将会当作关键字参数传递给与之绑定的视图函数index
    视图函数:
        def index(request, year):
            pass

# 注意事项:
    又名无名分组不可混用, 不过可以单种多次使用.
        url('^index/(\d+)/(\d+)/', views.index)
        url('^index/(?P<year>\d+)/(?P<year>\d+)/', views.index)

    多次使用如果是无名分组, 视图函数中可以使用*args接收参数
        def index(request, *args):
            pass

    多次使用如果是有名分组, 视图函数中可以使用**kwargs接收参数
         def index(request, *kwargs):
            pass

2. 反向解析是什么,如何使用? 无名和有名反向解析如何操作?(待定)

# 反向解析
    反向解析就是当执行某一个方法得到一个结果, 通过这个结果可以访问到对应的url方法, 只要满足第一个路由正则匹配机制匹配, 进而触发与之绑定的视图函数的执行.

# 反向解析使用
    第一步: 在urls.py中给路由与视图函数取一个别名(注意: 别名不能重复, 一定要唯一)
        url('^index/', views.index, name='xxx')

    第二部: 使用反向解析
        在模板层使用:
            {% url 'xxx' %}
            <a href="{% url 'ooo' %}">111</a>
        在视图层使用:
            from django.shortcuts import reverse
            reverse('xxx')
            
            
# 无名和有名反向解析操作
    # 无名分组反向解析
        # 路由层配置
            url(r'^index/(\d+), views.index, name='index')
        # 视图层使用
            {% url 'index' 能与(\d+)进行匹配的数字 %}
        # 模板层使用
            reverse('index', args=(能与(\d+)进行匹配的数字, ))

    # 有名分组反向解析
        # 路由层配置
            url(r'^index/(?P<year>\d+), views.index, name='index')
        # 视图层使用
            {% url 'index' 能与(\d+)进行匹配的数字 %}
            {% url 'index' year=能与(\d+)进行匹配的数字 %}
        # 模板层使用
            reverse('index', args=(能与(\d+)进行匹配的数字, ))
            reverse('index', kwargs=({"year": 能与(\d+)进行匹配的数字}))            

3. 路由分发能够实现的前提是什么,需要注意什么,名称空间什么时候使用?

# 路由分发实现前提
    每个应用之间都因该有自己的static, urls.py, templates,
    这也可以减小总路由的压力, 也可以实现多人分组开发, 每个人只需要专注于开发自己的app即可,
    当django路由匹配特别多的时候 那么总路由可以不再直接干匹配和触发函数运行而仅仅只是做一步分发操作


# 路由分发实现
    # 总路由
        from django.conf.urls import url
        from django.conf.urls import include
        # 第一种写法:
            from app01 import urls as app01_urls
            from app02 import urls as app02_urls
            url(r'^app01/', include(app01_urls))
            url(r'^app02/', include(app02_urls))

        # 第二种写法: 推荐
            url(r'^app01/', include('app01.urls'))
            url(r'^app02/', include('app02.urls'))

    # 子路由
        # app01中urls.py配置
            from django.conf.urls import url
            from app01 import views
            url(r'^index/', views.index)

        # app02中urls.py配置
            from django.conf.urls import url
            from app02 import views
            url(r'^index/', views.index)

# 注意事项
    总路由中'^app02/'这里后面不要加任何的参数, 不然无法分发交给子路由处理

# 名称空间使用
    # 问题:
        在多应用的情况下, 路由层中为路由取别名的方式,
        如果匹配机制相同, 且别名相同的情况下,
        就会出造成后面的覆盖前面的, 导致前面的别名无法反向解析到对应的url
    # 名称空间使用
        # 总路由中配置名称空间参数
            url(r'^app01/', include('app01.urls', namespace='app01'))
            url(r'^app02/', include('app02.urls', namespace='app02'))

        # 子路由中配置
            # app01中urls.py配置
                url(r'^index/', views.index, name='index')
            # app02中urls.py配置
                url(r'^index/', views.index, name='index')

        # 子路由中使用名称空间
            # app01中使用
                # 视图层使用
                    {% url 'app01:index' %}
                # 模板层使用
                    reverse('app01:index'))
            # app02中使用
                # 视图层使用
                    {% url 'app02:index' %}
                # 模板层使用
                    reverse('app02:index'))

    # 其实可以不使用名称空间, 只要别名不冲突即可, 因此在设置别名的时候加上应用名作为前缀就行
        # app01中urls.py配置
            url(r'^index/', views.index, name='app01_index')
        # app02中urls.py配置
            url(r'^index/', views.index, name='app02_index')

4. 什么是虚拟环境,django1.X与django2.X/3.X的区别有哪些

# 虚拟环境
    通常情况下我们会给每一个项目单独配备该项目所需的模块,不需要的一概不装节省资源,
    创建一个虚拟环境就类似于重新下载了一个纯净的python解释器.

    虚拟环境的标志: venv文件夹

# django1.X与django2.X/3.X区别
    1. django1.X路由层中使用url, django2.X/3.X使用path
        url支持正则, path不支持正则, 但是提供了5种基本转换器
        django2.X/3.X中也提供了正则方法re_path, 也保留了url方法, 但是推荐使用re_path
    2. django2.X/3.X的5种基本转换器
        path('index/<int:id>', views.index)  # <int:id>匹配到的内容, 转换成int类型, 再当作关键字参数id传入index函数
    3. django2.X/3.X也支持自定义转换器
    4. django1.X在模型类中默认支持级联更新级联删除, django2.X/3.X没有指定, 需要手动指定
        指定方式: on_delete=models.CASCADE on_update=m

三. 视图层

1. request对象的方法有哪些,分别是干什么用的,请具体阐述细节及注意事项?

request.method           获取大写字符串格式的请求方式
request.POST             获取QueryDict对象, 包含url中?好后的所有参数形信息
request.GET              获取QueryDict对象, 包含参数信息
request.FILES            获取文件对象列表集合
request.body             获取原生浏览器发送过来的二进制数据
request.path             获取路由
request.path_info        获取路由
request.get_path_full()  获取路由+参数

2. 诠释为何跨语言传输数据以json格式为主,django返回json格式数据方式有哪些,又有哪些注意事项和配置参数

# 为何跨语言传输数据以json格式为主
    json格式支持跨语言数据传输

# django返回json格式数据方式有哪些
    1. 使用json+HttpResponse
    2. 使用JsonResponse
        from django.http import JsonResponse
        注意1: data传入是非字典类型需要指定safe=False
        注意2: 如果想要序列化时中文不编码指定json_dumps_params={'ensure_ascii': False}

3. 简述 django FBV 和 CBV?

# FBV与CBV
    FBV 全称 Function Based View 基于函数的视图
    CBV 全称 Class Based View 基于类的视图
    CBV特点: 内部原理能够直接更具请求方式的不同获取的字符串, 进而使用反射隐射成对应的对象的方法
    # 路由层使用
        url(r'^my_index/', views.MyIndex.as_view())
    # 视图层使用
        from django.views import View
        class MyIndex(View):
            def get(self, request):
                pass
            def post(self, request):
                pass

4. 如何给 django CBV 的函数设置添加装饰器?

from django.views import View
from django.utils.decorators import method_decorator
"""
CBV中django不建议你直接给类的方法加装饰器
无论该装饰器能都正常给你 都不建议直接加
"""

# @method_decorator(login_auth, name='get')  # 方式2: 可以添加多个针对不同的方法加不同的装饰器
# @method_decorator(login_auth, name='post')
class MyIndex(View):
    @method_decorator(login_auth)            # 方式3: 它会直接作用于当前类里面的所有的方法
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request,*args,**kwargs)
    # @method_decorator(login_auth)          # 方式1: 指名道姓
    def get(self,request):
        return HttpResponse("get请求")

    def post(self,request):
        return HttpResponse('post请求')

四. 模版层

1. django 的模板中 filter、simple_tag、inclusion_tag 的区别?

# 三步骤:
    1. 先在需要使用过滤器的应用中创建templatetags文件夹
    2. 接着进入文件夹中创建任意名称的.py文件. -->  mytag.py
    3. 写入以下固定格式的内容:
        from django import template
        register = template.Library()

# 自定义过滤器: 最多2个参数
    # 视图层定义
        from templatetags.mytag import register
         @register.filter(name='过滤器名称 -> my_sum')
         def 任意函数名(v1, v2):
            return v1 + v2
    # 模板层使用
        {% load mytag %}
        {{ v1|my_sum:v2 }}

# 自定义标签: 任意参数
    # 视图层定义
        from templatetags.mytag import register
        @register.simple_tag(name='标签名称 -> my_join')
        def 任意函数名(a, b, c, d):
            return f'{a}-{b}-{c}-{d}'

    # 模板层使用
        {% load mytag %}
        {{ my_join 111 222 333 444 }}

# 自定义inclusion_tag
    # 视图层定义
       from templatetags.mytag import register
        @register.inclusion_tag('需要传递数据的html文件 -> index.py')
        def left(n):
            data = [f'第{i}项' for i in range(n)]
            return locals()          # 传递数据方式1
            # return {"data": data}  # 传递数据方式2

    # index.py定义
        <ul>
        {% for item in data %}
            <li>{{ item }}</li>
        {% endfor %}
        </ul>

    # 模板层使用
        {% load mytag %}
        {% left 5 %}

2. 模板文件是在什么时候完成渲染的?

在后端渲染完,只要出了django框架,就是完整的html,css和js

五. 模型层

1. django自带的数据库是什么,如何换成其他数据库例如MySQL,如何配置更换

1. 配置数据库: 找到settings.py文件中的DATABASES输入如下:
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'HOST': 'IP地址',
            'PORT': 3306,
            'USER': '登录用户',
            'PASSWORD': '用户密码',
            'NAME': '库名',
            'CHARSET': 'utf8',
        }
    }
2. 代码声明: 使用pymysql替换django自带的数据库模块MySQLdb.
    前提: 在项目文件夹下或者任意的应用文件夹下__init__.py中书写代码声明
    import pymysql
    pymysql.install_as_MySQLdb()

2. 什么是django orm,如何使用django orm,数据库迁移命令如何书写

# 什么是django orm
    ORM 全称 object relational mapping 对象关系映射
    功能: 通过ORM实现对操作对象的操作模式来操作数据库中的数据
    实现: 通过models中的类来对应数据库中的一个表,一个对象对应一个数据行,一个属性对应数据库中的一个字段
    缺陷: 封装程度太高, 有时候会出现创建sql语句的效率问题.

# 如何使用django orm
    前提: ORM不会帮你创建库, 只能创建到表的成面
    1. 配置数据库: 找到settings.py文件中的DATABASES输入如下:
        DATABASES = {
            'default': {
                'ENGINE': 'django.db.backends.mysql',
                'HOST': 'IP地址',
                'PORT': 3306,
                'USER': '登录用户',
                'PASSWORD': '用户密码',
                'NAME': '库名',
                'CHARSET': 'utf8',
            }
        }
    2. 代码声明: 使用pymysql替换django自带的数据库模块MySQLdb.
        前提: 在项目文件夹下或者任意的应用文件夹下__init__.py中书写代码声明
        import pymysql
        pymysql.install_as_MySQLdb()
    3. 使用: 进入models.py中书写模型类

# 数据库迁移命令如何书写?
    前提: 执行终端命令行当前路径一定要在项目文件夹下, 且配置了python的环境变量
    生成数据库迁移记录, 记录到migrations文件夹中: python3 manage.py makemigrations
    将数据迁移提交: python3 manage.py migrate

3. orm字段的增删改查与数据的增查如何实现(待定)

3.1 orm字段的增删改查:

# 增:
    1. 在执行了生成数据库迁移记录命令之后在终端命令行中输入默认值
    2. 直接为字段指定可以为空
        username = models.CharField(max_length=32, null=True)
    3. 为字段指定默认值
        username = models.CharField(max_length=32, default='我是默认值')
# 删:
    只要将需要删除的字段注释以后执行数据库迁移命令即可
    注意(危险): 删除的字段对应的数据也将会删除
# 改:
    直接在原来的字段的基础之上进行修改即可

3.2 orm数据的增删改查方法:

# 增:
    方法一:
        models.User.objects.create(**kwargs)
    方法二:
        user_obj = models.User(**kwargs)
        user_obj.save()

# 删:  真正的删除应二次确认.
    不做2次确认的删除: 直接删除:
        models.User.objects.filter(**kwargs).delete()
    因该用is_delete进行状态的标志而不是删除 用0 1进行标志.

# 改:
    方法一: 推荐. 批量操作对象. 只会批量修改被更新的字段
        models.User.objects.filter(**kwargs).update(**kwargs)

    方法二:  单独操作对象.  会从头到尾将字段更新.  效率低
        user_obj = models.User.objects.filter(**kwargs).first()

        user_obj.username = username
        user_obj.password = password
        user_obj.save()

# 查:
    查单个QuerySet对象:
        user_queryset = models.User.objects.filter(**kwargs)
        方式一:  索引取值, 索引不能为负数
            user_obj = user_queryset[0]
        方式二:  推荐. 内部使用以上方式实现
            user_obj = user_queryset.first()

    查多个QuerySet对象:
        方式一:
            user_queryset = models.User.objects.filter()
        方式二: 推荐. 见名知意
            user_queryset = models.User.objects.all()

4. 表关系如何判定,django orm中如何建立表关系,有什么特点和注意事项(待定)

# 表关系判定
    分为4中表关系: 一对一, 一对多, 多对多, 无关系
    判断: 站在两个角度, 两个方向思考成立情况.

# django orm中建立表关系
    一对一:
        author_detail = models.OneToOneField(to='AuthorDetail')
    一对多:
        publish = models.ForeignKey(to='Publish')
    多对多:
        authors = models.ManyToManyField(to='Book')
    拓展: 还可以有另一种书写方式, 不过这种方式必须放在被关联的类后. 这里必须放在Publish定义之后
        publish = models.ForeignKey(to=Publish)

# 特点和注意事项:
    1. 先建立基表最后再建立外键关系, 没有sql中建立外键必须先建立被关联表, 加入记录先插入被关联表这么一说, 直接建立就行.
    2. django 1.x版本无序指定级联更新级联删除, 默认会帮你指定.
    3. 一对多, 一对一无需在需要关联的字段后面加_id, 默认会帮你加. 例如: publish -> publish_id
    4. 一对多的表关系外键字段建立在多的一方
    5. 多对多的表关系无需类似于sql语句需要建立中间表, 会默认帮你创建虚拟的中间表
    6. 一对一, 多对多的表关系外键字段建立在查询频率较高的地方.

5. 列举 django orm 中你了解的所有方法?

# 返回QuerySet对象
    .all()          获取所有
    .filter()       过滤. 不指定参数获取所有. 指定字段查询结果不存在返回空的QuerySet对象. 布尔值为False. 多个参数直接默认是and连接
    .distinct()     去重. 要去重必须排除主键 或者 唯一字段. filter无法满足, 一般用在values 或者 values_list后面
    .order_by()     排序. 默认升序. 在需要降序的字段前加`-`.
    .reverse()      反转. 要反转必须针对排序过后的QuerySet对象. 也就是说必须在order_by之后使用
    .exclude()      排除. 排除指定的字段, 获取剩下所有.

# 返回特殊的QuerySet对象
    .values()       返回QuerySet之内部包含列表套字典格式. 指定的字段参数作为字典的key, value就是字段对应的数据.
    .values_list()  返回QuerySet之内部包含列表套元组格式. 元组中值得顺序和指定字段参数得顺序一致.
    注意: 如果自定的字段不存在, 则报错.

# 返回数据对象
    .first()        获取QuerySet对象中第一个数据对象.   如果QuerySet对象为空再继续使用first()返回结果为None
    .last()         获取QuerySet对象中最后一个数据对象.  如果QuerySet对象为空再继续使用last()返回结果为None
    .get()          直接获取对象. 只能指定一个参数. 如果指定得字段返回结果有多个 或者 查询结果不存在 则报错.

# 返回数字
    .count()        统计QuerySet对象中数据对象的个数

# 返回布尔值
    .exist()        统计 QuerySet对象中是否存在自定的字段. 返回True 或者 False

5-1 django 中 filter 和 exclude 的区别

.filter()       过滤. 不指定参数获取所有. 指定字段查询结果不存在返回空的QuerySet对象. 布尔值为False. 多个参数直接默认是and连接

.exclude()      排除. 排除指定的字段, 获取剩下所有.

5-2 django 中 values 和 values_list 的区别?

.values()       返回QuerySet之内部包含列表套字典格式. 指定的字段参数作为字典的key, value就是字段对应的数据.

.values_list()  返回QuerySet之内部包含列表套元组格式. 
元组中值得顺序和指定字段参数得顺序一致.
    注意: 如果自定的字段不存在, 则报错.

5-3 Django里QuerySet的get和filter方法的区别?

.get()          直接获取对象. 只能指定一个参数. 如果指定得字段返回结果有多个 或者 查询结果不存在 则报错.

 .filter()       过滤. 不指定参数获取所有. 指定字段查询结果不存在返回空的QuerySet对象. 布尔值为False. 多个参数直接默认是and连接

5-4 django 对数据查询结果排序怎么做, 降序怎么做?

.order_by()     排序. 默认升序. 在需要降序的字段前加`-`.

6. 简述神奇的双下划线查询都有哪些方法,作用是什么

# 提示: 以下都是争对字段
# 大于 小于 大于等于 小于登录
    __gt         __lt
    __gte        --lte
# 成员查询
    __in=[]
# 范围查询: 顾头也顾尾
     __range=[start, stop]
# 模糊查询: i -> ignore 忽略大些小
    __contains   __icontains
# 起始与结束查询
    __startswith __istartswith
    __endswith   __iendswith
# 按照年份, 月份, 天数... 查询
     __year  __month    __day

7. 针对多对多外键字段的增删改查方法有哪些,各有什么特点?

# 提示:
    实际字段使用 id
    虚拟字段使用 对象
# 增 add    可以指定多个括号内可以传对象也可以传数字
# 删 remove 可以指定多个括号内可以传对象也可以传数字
# 改 set    可以指定多个
    注意: set中的参数指定的是一个可迭代对象. 例如: set([])
    set本质是一种新增操作. 一上来会将指定的参数之外的清空, 如果不存在的则会新增.
    如果你想更新, 但是要保留原来的, 必须要对原来的进行重复指定.

# 清空 clear 无需给任何参数. 直接清空任何数据.

# 查 子查询 或者 连表查询
    1. 正向查询按字段
        含外键字段的一端查询不含外键字段的一端
        如果查询结果有多个使用.all()
    2. 反向查询按表名小写
        不含外键字段的一端查询含外键字段的一端
        如果查询结果有多个再表名小写的基础之上_set.all()
    # 对应sql中得连表语法
        inner join   外连接之内链接(只拼接2张表中共有得数据部分)
        left  join   外连接之左链接(左表所有得数据都展示出来, 没有对应得项就用null)
        right join   外连接之左链接(右表所有得数据都展示出来, 没有对应得项就用null)
        union        外连接之全连接(左右两表所有得数据都展示出来)
        full join    mysql不支持全外链接, 而是使用union配合left join和right join实现. oracle支持全外链接.

8. 什么是正反向的概念,及查询口诀,你能否总结一下正反向查询不同情况下点击不同字段的规律

# 1. 正向查询按字段
    含外键字段的一端查询不含外键字段的一端
    如果查询结果有多个使用.all()
# 2. 反向查询按表名小写
    不含含外键字段的一端查询含外键字段的一端
    如果查询结果有多个再表名小写的基础之上_set.all()
它们都是与Date系列独有得参数. 如: DateField  DateTimeField
auto_now: 指的就是记录中数据的更新时间
auto_now_add:  指的就是第一次往记录中插入数据的时间. 作用: 一般用于注册时间

9. orm数据库查询优化相关有哪些各有什么特点? only和defer的区别?. select_related和prefetch_related的区别?

# 查询的惰性, 不执行就不走数据库
# only  defer
    only括号内指定的字段, 在查询的时候不走数据库
    defer括号内指定的字段, 在查询的时候走数据库

# select_related   prefetch_related
    select_related 内部使用连表查询
        括号内只能放外键字段. 且只支持一对一, 一对多的表关系. 多对多不支持.
        内部通过1次性将2表查询出来封装成对象中, 下次查询这2表就无序走数据库了.
    prefetch_related 内部使用子查询
        内部通过2次性将子查询结果查询出封装成对象中.下次查询这2表就无序走数据库了

10. F与Q查询的功能,他们的导入语句是什么,针对Q有没有其他用法?

# F查询: 能够获取到表中指定字段对应的数据
    # 使用:
        from django.db.models import F
        # 基本使用
            models.Book.objects.filter(sale__gt=F('stock'))
        # 争对F中指定得字段对应得数据是数字类型可以进行数学运算
            models.Book.objects.filter(sale__gt=F('stock')+500)
        # 争对F中指定得字段对应得数据不可以直接进行拼接操作, 需要借助Concat和Value方法
            from django.db.models.functions import Concat
            from django.db.models import Value
            models.Book.objects.filter(title=Concat(F("title"), Value("爆款"))
            注意: 如果直接进行字符串的拼接操作, 指定字段对应的所有数据会边为空值

# Q查询: filter默认and连接语法. 使用Q可以支持and, or, not连接语法
    # 基本使用:
        from django.db.models import Q
        # and连接语法符: &
            models.Book.objects.filter(sale__gt=100, stock__lt=200)
            models.Book.objects.filter(Q(sale__gt=100), Q(stock__lt=200))
            models.Book.objects.filter(Q(sale__gt=100) & Q(stock__lt=200))
        # or连接语法符:  |
            models.Book.objects.filter(Q(sale__gt=100) | Q(stock__lt=200))
        # not连接语法符: ~
            models.Book.objects.filter(~Q(sale__gt=100) | ~Q(stock__lt=200))

    # 高阶使用: 条件的左边指定的sale__gt都是变量的形式. 实现条件的左边是字符串的形式.
        q = Q()
        q.connector = 'or'  # 指定连接符.  默认不写and连接
        q.children.append(('sole__gt', 100))
        models.Book.object.filter(q)

10-1 django 中的 F 的作用?

像之前我们所了解的一些过滤的例子和操作都是在针对字段值和某一个常量之间作比较,但是如果我们要针对两个字段值作比较的话就不行了,这就涉及到这个F查询了

10-2 django 中的 Q 的作用?

filter默认and连接语法. 使用Q可以支持and, or, not连接语法

11. 列举常见的数据库字段及主要参数(越多越好)

# 常见的数据库字段
    AutoField
        primary_key=True    AutoField不指定默认就是创建id作为主键
    CharField
        max_length
    IntegerField
    BigIntegerField
    DateTimeField
    DateField
        auto_now=True       记录更新的时间
        auto_now_add=True   第一次记录插入数据的时间  注册
    EmailField
    DecimalField
        max_digits
        decimal_places
    TextField
    FileField
        upload_to='指定文件存放的路径/data/'  该字段对应的数据存放的就是文件的路径/data/a.txt
    BooleanField
        该字段传布尔值(False/True) 数据库里面存0/1


# 外键字段及参数
    to       设置要关联的表
    to_field 设置置要关联的表的字段  默认不写关联的就是另外一张的主键字段.
    db_index 如果db_index=True 则代表着为此字段设置索引
    on_delete on_update  设置级联更新级联删除 1.x自动 2.x和3.x手动

# 了解 一对一其实可以有两种指定方式
    ForeignKey(unique=Ture) OneToOneField

11-1 django 的 Model 中的 ForeignKey 字段中的 on_delete 参数有什么作用?

on_delete on_update  设置级联更新级联删除 1.x自动 2.x和3.x手动

12. 聚合查询,分组查询的关键字各是什么,各有什么特点或者注意事项

# 聚合查询 aggregate
    # 作用: 聚合函数是用在分组之后的, aggregate可以在不分组的情况下使用
    # 使用:
        from django.db.models import Max, Min, Avg, Sum, Count
        单个: models.Book.objects.aggregate(Max('price'))
        多个: models.Book.objects.aggregate(Max('price'), Max('price'), Min('price'), Sum('price'), Count('pk'))
    # 返回字典格式的数据: {'price__avg': ''}

# 分组查询 annotate
    # 作用: 分组
    # 注意事项: 分组之后只能拿到分组的依据 和 组中数据举和的结果 (补充: 如果是多个分组, 那么就能拿到多个分组的依据...)
    # MySQL设置全局的分组严格模式: set global sql_mode=only_full_group_by;
    # 使用:
        from django.db.models import Max, Min, Avg, Sum, Count
        # 默认分组: 对models后面指定得表进行分组
            models.Book.objects.aggregate(author_count=Count('authors__id')).values('title', 'author_count')
            models.Book.objects.aggregate(author_count=Count('authors')).values('title', 'author_count')
        # 指定分组: 分组依据publish__name
            models.Book.objects.values('publish__name').annotate(book_sum=Count('title')).values('book_sum', 'publish__name')

13. 使用Django中model中的filter条件过滤方法,把下边sql语句转化成python 代码

select * from company where title like "%abc%" or me_count>999 order by create_time desc;

from django.db.models import Q
res = models.Company.objects.filter(Q(me_count__gt=999) | Q(title__contains='abc')).order_by('-create_time').values()
print(res)

14. 模型类关系

# django orm中建立表关系
    一对一:
        author_detail = models.OneToOneField(to='AuthorDetail')
    一对多:
        publish = models.ForeignKey(to='Publish')
    多对多:
        authors = models.ManyToManyField(to='Book')
    拓展: 还可以有另一种书写方式, 不过这种方式必须放在被关联的类后. 这里必须放在Publish定义之后
        publish = models.ForeignKey(to=Publish)

        
# 特点和注意事项:
    1. 先建立基表最后再建立外键关系, 没有sql中建立外键必须先建立被关联表, 加入记录先插入被关联表这么一说, 直接建立就行.
    2. django 1.x版本无序指定级联更新级联删除, 默认会帮你指定.
    3. 一对多, 一对一无需在需要关联的字段后面加_id, 默认会帮你加. 例如: publish -> publish_id
    4. 一对多的表关系外键字段建立在多的一方
    5. 多对多的表关系无需类似于sql语句需要建立中间表, 会默认帮你创建虚拟的中间表
    6. 一对一, 多对多的表关系外键字段建立在查询频率较高的地方.

15. 如何使用 django orm 批量创建数据?

# 注意: 批量插入数据利用ORM的惰性原则, 不执行就不走数据库
book_generator = (models.Book(title='图书{}'.format(i+10)) for i in range(100))
models.Book.objects.bulk_create(book_generator)

六. Django与Ajax, 批量插入数据, 自定义分页器, form组件, Cookie与Session组件, 中间件, Auth认证模块, ContentType组件

1. django 中想要验证表单交是否格式正确需要用到 form 中的那个方法

A.  form.save()
B.  form.save(commit=False)
C.  form.verify()
D.  form.is_valid()           


# 答案: D

2. cookie与session与token

以下是自己的理解

早期的浏览器基于HTTP发送请求, 服务端基于请求响应. 但是HTTP协议本身是无状态的.
这种无状态带来的影响就是, 在用户访问需要通过认证去访问的的网页时, 每次的请求响应,
客户端都需要重新输入密码效验认证, 基于这种情况之下, 就诞生了cookie.

cookie它是在用户认证成功以后, 服务端返回的数据中, 通知浏览器, 将用户的用户名, 密码
保存在用户本地. 但是这种情况之下, 用户名, 密码将会容易暴漏, 安全性大大降低. 因此有人
就想, 那我保存在服务端好了. 我只需要返回一个随机的字符串, 给客户端. 客户端每次访问时
只需要通过这个随机字符串就可以访问到用户正真的数据, 通过这种映射对应关系来达到目的.
因此也就诞生了session.

但是session保存在服务端带来的问题也很明显, 因为服务端的资源是宝贵的, 每来一个用户, 服务端
都需要保存这种session对于关系, 基于这种情况, 有人就想能不能保存在客户端. 因此token就诞生了.
token的原理可以理解为在原来的cookie之上做了加密效验, 现在不返回用户名,密码这些敏感的信息了.
服务端将用户的某些标识性的(不是密码)信息, 进行加密, 将加密的内容拼接到刚刚之前的用户的标志性信息之后,
返回给客户端保存, 客户端登录成功以后请求的时候只需要拿着对于的key:value对象提交给服务端,
服务端将这种耦合的性息进行拆解, 拆解出用户标志性信息以及加密的标签. 再对用户提交的标志性信息进行刚刚服务端保留的特殊的加密方式进行加密,
效验对比一同提交过来的标签, 如果一致的话, 那么就可以明确这是合法的用户.

七. (Rest Framework): RESTful API介绍, 序列化, 视图组件, 分页组件, 认证、权限、限制, 解析器与渲染器, 版本控制

posted @ 2020-05-25 19:37  给你加马桶唱疏通  阅读(242)  评论(2编辑  收藏  举报