Django学习笔记

2022-06-12
5分钟阅读时长

利用Django进行web开发时编写的笔记

1 Django介绍
起源
  • 2005年,采用python编写的开源web框架
  • 早期Django主要做新闻和内容管理
  • 重量级的python web框架,django配备了常用的大部分组件,包含:
    • 基本配置文件/路由系统
    • 模型层M/模板层T/视图层V
    • cookies和session
    • 分页及发邮件
    • admin管理后台
用途
  • 网站/微信公众号/小程序后端开发
  • 人工智能平台融合
  • ……
2 Django项目结构
创建项目
  • 成功安装后,虚拟机终端出现django-admin命令
  • 执行 django-admin startproject project_name ,即可创建出项目文件夹
启动项目
  • cd进入到项目文件夹
  • 执行 py manage.py runserver
  • 访问http://127.0.0.1:8000
关闭服务
  • 方式1:在runserver启动终端下执行ctrl+c
  • 方式2:在其他终端下,执行 sudo lso -i:8000 查询django的id,执行 kill -9 对应的django进程id
manage.py
  • py manage.py runserver 启动服务
  • py manage.py startapp 创建应用
  • py manage.py migrate 数据库迁移
  • 直接执行 py manage.py 查询所有的django子命令
项目同名文件夹
  • __init__ :python包的初始化文件
  • wsgi.py :web服务网相关的配置文件
  • urls.py :项目的主路由配置——http请求进入django时,优先调用该文件
  • settings.py:项目的配置文件——包含项目启动时需要的配置
settings.py
  • 配置项分为公有配置和自定义配置
  • 公有配置为django官方提供的基础配置
    • ALLOWED_HOSTS:设置允许访问到本项目的host头值
      • [] 空列表则只有localhost可以访问
      • [‘*’] 表示任何请求头的host都可以访问到该项目
      • 指定网络设备如果内网环境下其他主机想要访问该站点,需要加 ALLOWED_HOSTS=[‘内网ip’]
    • BASE_DIR:用于绑定当前项目的绝对路径,所有文件夹都依赖于该路径
    • DEBUG:用于配置django的启动模式,True 表示开发环境中使用,False 表示当前项目运行在生产环境中
    • INSTALLED_APPS:指定当前项目中安装的应用列表
    • MIDDLEWARE:用于注册中间件
    • TEMPLATES:用于指定模板的配置信息
    • DATABASES:用于指定数据库的配置信息
    • LANGUAGE_CODETIME_ZONE
    • ROOT_URLCONF 用于配置主url配置
urls.py
  • 定义:unifrom resourse locator

  • 作用:表示互联网上某个资源的地址

  • 格式:protocol :// hostname[:port] / path [?query][#fragment]

    • protocol
      • http通过HTTP访问该资源
      • https通过安全的HTTPS访问该资源
      • file是本地计算机上的文件
    • hostname:存放资源的服务器的DNS主机名、域名或IP地址
    • port
      • 整数,可选,省略时使用方案的默认端口
      • 各种传输协议都有默认的端口号,如http的默认端口为80
    • path
    • query
      • 可选,用于给动态网页传递参数
      • 可以有多个参数,用 & 隔开,每个参数的名和值用 = 隔开
    • fragment
  • 处理url请求

    • django从配置文件中根据ROOT_URLCONF找到主路由文件
    • 加载主路由文件中的 urlpatterns 变量
    • 依次匹配 urlpatterns 中的 path,匹配到第一个合适的中断后续匹配
    • 匹配成功:调用对应的视图函数处理请求,返回相应;匹配失败:返回404相应
  • 视图函数

    • 用于接收一个浏览器请求(HttpRequest对象)并通过 HttpResponse 对象返回相应的函数

    • #语法
      def xxx_view(request[,else]):
          return HttpResponse
      
      #样例
      from django.http import HttpResponse
      def page1_view(request):
          html = '<h1>这是第一个页面</h1>'
          return HttoResponse(html)
      
  • 路由配置

    • #path()函数
      from django.urls import path
      path(route, views, name=None)
      
      #path转换器样例
      path('page/<int:page>', views.xxx)
      
      #re_path()
      #注意正则表达式的使用
      re_path(reg, view, name=xxx)
      
3 请求与相应
  • 定义

    • 请求是浏览器通过HTTP协议发送给服务器端的数据
    • 响应是服务器接收到请求后做相应的处理后回复给浏览器的数据
  • Django收到http协议的请求后,会根据请求数据创建 HttpRequest 对象,其通过属性描述了请求的所有相关信息

    • path_info:URL字符串
    • method:字符串,表示请求方法(请求方法:GET HEAD POST PUT DELETE CONNECT OPTIONS TRACE
    • GETQueryDict查询字典的对象,包含 GET 请求方式的所有数据
    • POSTQueryDict查询字典的对象,包含 POST 请求方式的所有数据
    • FILES:类似于字典的对象,包含所有上传的文件信息
    • COOKIES:python字典,包含所有的cookie,键和值都是字符串
    • session:似于字典的对象,表示当前的对话
    • body:字符串,请求体的内容( POSTPUT )
    • scheme:请求协议
    • request.get_full_path():请求的完整路径
    • request.META:请求中的元数据,例如 request.META[‘REMOTE_ADDR’] 表示客户端IP地址
  • 响应状态码 Status Code

    • 200 请求成功
    • 301 永久重定向:转移到其他url
    • 404 不存在
    • 500 内部服务器错误
  • 响应对象

    • #构造函数格式:
      HttpResponse(content=响应体, content_type=响应体数据类型, status=状态码)
      
      #常见的content_type
      #'text/html'(默认,html), 'text/plain',
      #'text/css', 'text/javascript'...
      
  • GET 处理

    • 一般用于向服务器获取数据
    • 能够产生 GET 请求的场景
      • 浏览器地址栏输入URL回车后
      • <a href="…">
      • form表单中的 methodget
  • POST 处理

    • 一般用于向服务器提交大量/隐私数据
    • 客户端通过表单等 POST 请求将数据传递给服务器端
    • 取消 setting.py 中的 csrf 验证,否则django会拒绝客户端发来的 POST 请求并报403响应
4 Django设计模式与模板层
  • 传统的MVC(Model-View-Controller)

    • M模型层,主要用于对数据库层的封装
    • V视图层,主要向用户展示结果(WHAT+HOW)
    • C控制器,用于处理骑牛、获取数据、返回结果
  • Django的MTV(Model-Template-View)

    • M模型层,负责与数据库交互
    • T模板层,负责呈现内容到浏览器(HOW)
    • V视图层,是核心,负责接受请求、获取数据、返回结果(WHAT)
  • 模板

    • 模板可以根据视图中传递的字典数据动态生成相应的HTML网页

    • 模板配置

      • 创建模板文件夹 <项目名>/templates
      • 在settings.py中TEMPLATES配置项
        • BACKEND:指定模板的引擎
        • DIRS:模板的搜索目录(可以是一个或者多个)’DIRS’: [BASE_DIR / 'templates']
        • APP_DIRS:是否在应用的templates文件夹中搜索模板文件
        • OPTIONS:有关模板的选项
    • 加载方式

      • #方案一
        from django.template import loader
        t = loader.get_template('TemplateName')
        html = t.render()
        return HttpResponse(html)
        
      • #方案二
        from django.shortcuts import render
        return render(request, 'TemplateName',dic)
        
    • 视图层与模板层之间的交互

      • #视图函数将变量封装到字典传递到模板
        def xxx_view(request):
            dic = {
                'var1':'value1'
                'var2':'value2'
            }
            return render(request, 'xxx.html', dic)
        
      • 能够传递到模板的数据类型:str, int, list, tuple, dict, func, obj

      • 模板中通过 {{ var }} {{ var.index }} {{ var.key }} {{ obj.method }} {{ func }}来调用变量

    • 标签

      • {% 标签 %}
        ...
        {% 结束标签 %}
        
      • 内置变量forloop

    • 模板过滤器

      • 在变量输出时对变量的值进行处理
      • {{ var | lower }} {{ var | upper }} {{ var | safe }} {{ var | add: “n” }}
    • 模板的继承

      • 父模板中

        • 定义父模板中的block标签
        • 表示出哪些在子模块中可以被修改
        • block标签:在父模块中定义,在子模块中覆盖
      • 子模块中

        • #第一行
          {% entends 'base.html' %}
          #子模块重写父模块中的内容块
          {% block block_name %}
          ...
          {% endblock %}
          
      • 注意:模板继承时,服务器端的动态内容无法继承

5 再论url
  • 代码中url出现的位置

    • html中
      • <a href='url'>…</a>a>
      • <form action = ‘url’, method = ‘post'>
    • 视图函数中的302跳转 HttpResponseRedirect('url')
  • url书写规范

    • 绝对地址:http://127.0.0.1:8000/page/1
    • 相对地址:‘/page/1’‘page/1’ 的区别
  • url反向解析

    • 用path定义的名称来动态查找相应的路由

    • {% url ‘name’ ‘var1’ ‘var2’ %}

    • #在视图函数中可以用django的reverse方法反向解析
      from django.urls import reverse
      reverse('name', args=[], kwargs=[])
      
6 静态文件
  • 图片,css,js,音频,视频等

  • 静态文件配置 setting.py中

    • 配置静态文件的访问路径

    • #配置静态文件储存位置
      #file: setting.py
      STATICFILES_DIRS = (os.path.join(BASE_DIR, 'static'),)
      
    • #模板中访问静态文件
      {% load static %}
      <img src='{% static img/xxx.jpg' %}'
      
7 应用
  • 应用是在django中是一个独立的业务模块,可以包含自己的路由,模板,视图,模型

  • 创建应用

    • py manage.py startapp projectName
    • setting.py的INSTALLED_APPS列表中配置安装
  • 配置分布式路由

    • 主路由中调用include函数 include(‘app名字.url模块名’) 用于将当前路由转到各个应用的路由配置文件
    • 应用下配置urls.py
  • 应用下的模板

    • 应用下手动创建templates文件夹
    • settings.py中开启应用模板功能
8 模型层
  • django配置mysql

    • 创建数据库
    • 进入mysql数据库执行
    • 指定‘ENGINE’ ‘NAME’USER’ ‘PASSWORD’ ‘HOST’ ‘PORT’
  • 什么是模型

    • 一个python类,由django.db.models.Model派生出的自雷
    • 一个模型类代表数据库中的一张数据表
    • 模型类中每一个类属性都代表数据库中的一个字段
    • 模型是数据交互的接口,是表示和操作数据库的方法和方式
  • ORM框架

    • Object Relational Mapping
    • 只需要面向对象编程,不需要面向数据库编写代码
    • 实现了数据模型与数据库的解耦,屏蔽了不同数据库操作上的差异
    • 类→数据表,对象→数据行,属性→字段
  • 模型类定义

    • from django.db import models
      class 模型类名(models.Model):
          字段名 = models.字段类型(字段选项)
      
  • 数据库迁移

    • 生成迁移文件 执行 py manage.py makemigrations
    • 执行迁移脚本程序 执行 py manage.py migrate
  • 字段类型

    • BooleanField()
      • 数据库类型:tinyint(1)
    • CharField()
      • 数据库类型:varchar
      • 注意:必须要指定max_length参数值
    • DateField()
      • 数据库类型:date
      • 参数 auto_now=True/False auto_now_add=True/False default=xxxx-x-x 三选一
    • DateTimeField()
      • 数据库类型:datetime(6)
      • 参数同DateField
    • FloatField()
    • DecimalField()
      • 数据库类型:decimal(x,y)
      • 参数 max_digits decimal_places
    • EmailField()
    • IntergerField()
    • ImageField()
      • 数据库类型:varchar(100)
      • 保存为图片的路径
    • TextField()
      • 数据库类型:longtext
  • 字段选项

    • 多个选项用 , 隔开
    • primary_key:如果设置为True,则为主键,不创建id字段
    • blank:设置为True时,字段可以为空
    • null:如果设置为True,则表示该列值可以为空。默认为False,如果为false建议加入default选项设置默认值
    • default:设置所在列的默认值
    • db_index:如果为True,表示为该列添加索引
    • unique:如果为True,表示该字段在数据库中的值必须唯一
    • db_column:指定列的名称,不指定则采用属性名为列名
    • verbose_name:设置此字段在admin界面上的显示名称
  • 模型类-Meta类

    • 使用Meta类可以给模型赋予属性,meta类下有很多内建的类属性,可以对模型类做一些控制

    • #使用meta类更改当前模型类的表名
      class Book(models.Model):
          #...
          class Meta:
              db_table = 'book'
      
  • ORM操作

    • ORM CRUB核心 -> 模型类.管理器对象

      • 每个继承自models.Model的模型类,都会有一个objects对象被同样继承下来。这个对象就是管理器对象

      • #数据库的增删查改可以通过模型的管理器实现
        class MyModel(models.Model):
            #...
        MyModel.objects.create(...) #objects是管理对象
        
    • 创建数据

      • #方案一
        MyModel.objects.create(...)
        #成功:返回创建好的实体对象
        #失败:异常
        
      • #创建MyModel对象,并调用save()进行保存
        obj = MyModel(...)
        obj.property = value
        obj.save()
        
    • 查询操作

      • 查询方法: all() get() filter() values(‘列名’) values_list(‘列1’) order_by
      • 可以在模型类中定义 __str__ 方法,自定义输出QuerySet中的输出格式
      • 条件查询 filter(条件) exclude 多个条件为and关系
      • 查询谓词:类属性+‘__’+谓词
    • 更新操作

      • 一查二改三保存
      • 批量,使用QuerySet的 update()
    • 删除数据

      • 单个/批量数据删除 object.delete() !注意使用 try…except
      • 伪删除 is_active
    • F对象

      • 一个F对象代表数据库中某条记录的字段的信息

      • 作用

        • 通常是对数据库中的字段值在不获取的情况下进行操作
        • 用于类属性之间的比较
      • from django.db.models import F
        F('列名')
        
    • Q对象:查询时使用或、非等逻辑的操作

9 admin管理后台
  • 定义

    • django提供了比较完善的后台管理数据库的接口
    • django会搜集所有已注册的模型类,为这些模型类提供数据管理页面,供开发者使用
  • 注册自定义模型类

    • 如果要自己定义的模型类也能在/admin后台中显示和管理,需要将自己的类注册到后台管理页面
    • 在应用app中的admin.py中导入注册要管理的模型models类
    • 调用admin.site.register方法进行注册
  • 模型管理器类

    • 作用:为后台管理界面添加便于操作的新功能

    • 说明:后台管理器类须继承自django.contrib.admin里的ModelAdmin类

    • #使用方法
      #1.在<应用app>/admin.py里定义模型管理器类
      class XXXManager(admin.ModelAdmin):
          ...
      #2.绑定注册模型管理器和模型类
      from django.contrib import admin
      from .models import *
      admin.site.register(YYYY,XXXXManager)
      
  • 再谈Meta类

    • 通过Meta内嵌类定义模型类的属性,用法如下:
      	class Book(models.Model):
              title = CharField(...)
      
              class Meta:
                  #该模型所用数据表的名称(设置完成后需要立马更新同步数据库)
                  db_table='数据表名'
                  #给模型对象的一个易于理解的名称(单数),用于显示在/admin管理页面中
                  verbose_name='单数名'
                  #该对象复数形式的名称
                  verbose_name_plural='复数名'
      
10 关系映射
  • 常见的关系映射:一对一,一对多,多对多

  • 一对一

    • class A(model.Model):
          ...
      
      class B(model.Model):
          属性 = models.OneToOneField(A, on_delete=xxx)
      
    • on_delete级联删除

      • models.CASCADE
      • models.PROTECT
      • SET_NULL
      • SET_DEFAULT
    • 查询数据

  • 一对多

    • OneToOneField 换成 Foreign Key
    • 反向查询:使用 class_set.all()
  • 多对多

    • OneToOneField 换成 ManyToManyField
11 cookies和session
  • 会话

    • 从打开浏览器访问一个网站,到关闭浏览器结束此次访问,称之为一次会话
    • HTTP协议无状态,导致会话状态难以保持
  • cookie是保存在客户端浏览器上的存储空间

    • cookies在浏览器上是以键字对的形式储存的
    • 储存的数据是有生命周期的
    • cookies中的数据是按域存储隔离的,不同域之间无法访问
    • cookies内部的数据会在每次访问此网址时都会携带到服务器端,如果cookies过大会降低响应速度
  • cookie的使用

    • 存储:HttpResponse.set_cookie(key, value=‘’, max_age=None, expires=None)
  • session

    • session是在服务器上开辟一段空间用于保留浏览器和服务器交互时的重要数据

    • 实现方式

      • 使用session需要在浏览器客户端启动cookie,且在cookie中存储sessionid
      • 每个客户端都可以在服务器端有一个独立的session
      • 注意:不同的请求者之间不会共享这个数据,与请求者一一对应
    • session使用

      • #保存session值到服务器
        request.session['KEY']=VALUE
        #获取session的值
        value = request.session['KEY']
        value = request.session.get('KEY',默认值)
        #删除session
        del request.session['KEY']
        
12 缓存
  • 定义:一类可以更快的读取数据的介质的统称,也指其他可以加快数据读取的储存方式。一般用来存储临时数据。

  • 意义:视图渲染有一定成本,数据库的频繁查询过高,所以对于低频变动的页面可以考虑使用缓存技术,减少实际渲染次数,用户拿到相应的时间成本会更低

  • django设置缓存

    • 数据库缓存

    • #数据库缓存配置,需要手动执行 创建表 的 命令
      CACHES = {
          'default':{
              'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
              'LOCATION': 'my_cache_table',
              'TIMEOUT': 300, #缓存保存时间,单位秒,默认300
              'OPTIONS':{
                  'MAX_ENTRIES': 300,  #缓存最大数据条数
                  'CULL_FREQUENCY': 2, #缓存条数达到最大值时,删除1/x的缓存数据
              }
          }
      }
      
  • 使用缓存

    • #视图函数中
      from django.views.decorators.cache import cache_page
      
      @cache_page(30) #单位s
      def my_view(request):
          ...
      
    • #路由中
      from django.views.decorators.cache import chae_page
      urlpagtterns = [
          path('foo/', chae_page(60)(my_view))
      ]
      
13 中间件
  • 定义

    • 中间件是django请求/响应处理的钩子框架。它是一个轻量级的、低级的“插件”系统,用于全局改变django的输入和输出
    • 中间件以类的形式体现
    • 每个中间件组件负责做一些特定的功能
  • 编写中间件

    • 中间件继承自 django.utils.deprecation.MiddlewareMixin
    • 中间件类实现下列五个方法的一个或多个
      • process_request(self, request) 执行路由之前被调用,在每个请求上调用返回NONE或HttpResponse对象
      • process_view(self, request, callback, callback_args, callback_kwargs) 调用视图之前被调用,在每个请求上调用返回NONE或HttpResponse对象
      • process_response(self, request, response) 所有响应返回浏览器被调用,在每个请求上调用,返回HttpResponse对象
      • process_exception(self, request, exception) 当处理过程中抛出异常时调用,返回一个HttpResponse对象
      • process_template_response(self, request, response) 在视图函数执行完毕且试图返回的对象中包含有render时被调用;该方法需要返回实现了render方法的响应对象
    • 中间件大多数方法在返回none时表示忽略当前操作进入下一项事件,当返回httpresponse对象时表示请求结束,直接返回给客户端
  • 注册中间件

    • #setting.py
      MIDDLEWARE = [
          ...
      ]
      
    • 注意:中间件被调用时以“先上到下”再“由下到上”的顺序调用

  • CSRF攻击

    • 跨站伪造请求攻击:某些恶意网站上包含链接、表单按钮或者jvascript,它们会利用登录过的用户再浏览器中的认证方式试图在网站上完成某些操作

    • 防范:django采用‘对比暗号’机制防范攻击。cookies中存储暗号1,模板中表单里藏着暗号2,用户只有在本网站下提交数据,暗号2才会随表单提交给服务器,django对比两个暗号,对比成功,则认为是合法请求,否则是违法请求-403

    • 配置:在模板中,form标签下添加标签 {% csrf_token %}

    • 特殊说明:如果某个试图不需要django进行csrf保护,可以用装饰器关闭对此视图的检查

      • from django.views.decorators.csrf import csrf_exempt
        
        @csrf_exempt
        def my_view(request):
            ...
        
14 分页
  • 在web页面有大量数据需要显示,为了阅读方便在每个分页中显示部分数据
  • django提供了Paginator类实现分页功能,位于 django.core.paginator 模块中
  • paginator对象:Paginator(object_list, per_page)
    • object_list 需要分页数据的对象列表
    • per_page 每页数据个数
    • 返回值paginator对象
  • paginator属性
    • count 需要分页数据的对象总数
    • num_pages 分页后的页面总数
    • page_range 从1开始的range对象,用于记录当前页面页码
    • per_page 每页数据的个数
  • paginator方法
    • .page(number) 返回当前Number页的对应页信息,如果不存在,抛出invalidpage异常
    • .has_next() 如果有下一页返回true
    • .has_previous()
    • .has_other_pages()
    • .next_page_number() 返回下一页的页码
    • .previous_page_number
15 内建用户系统
  • Django带有一个用户认证系统。它处理用户账号、组、权限以及基于cookie的用户会话。用户可以直接使用django自带的用户表
  • 基本字段
    • from django.contrib.auth.models import User