Django介绍

介绍Django是Python语言中的一个Web框架,Python语言中主流的web框架有Django、Tornado、Flask等多种
优势:大而全,框架本身集成了ORM、模型绑定、模板引擎、缓存、Session等功能,是一个全能型框架,拥有自己的Admin数据管理后台,第三方工具齐全,性能折中
缺点:功能太多,数据分表复杂,高性能扩展复杂、重量级

Django安装

pip安装:在cmd命令窗口中,输入:

1
pip install django

官方文档

提示

  • 点击页面右下角的language按钮,可以选择zh-hans,显示中文,只有部分页面有中文翻译
  • 点击页面右下角的Documentation version,可以选择版本

专业词汇

B/S和C/S

Django是用于开发B/S架构的软件的,软件主要分为B/S架构和C/S架构:

  • B/S:全称Browser/Server(浏览器/服务器)
  • C/S:全称Client/Server(客户端/服务器)

MVC和MTV

MVC

MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进个性化定制界面及用户交互的同时,不需要重新编写业务逻辑

  • M:管理应用程序的状态(通常存储到数据库中),并约束改变状态的行为(或者叫做“业务规则”)。
  • V:负责把数据格式化后呈现给用户。
  • C:接受外部用户的操作,根据操作访问模型获取数据,并调用“视图”显示这些数据。控制器是将“模型”和“视图”隔离,并成为二者之间的联系纽带。

MTV

Django也是一个MVC框架。但是在Django中,控制器接受用户输入的部分由框架自行处理,所以Django里更关注的是模型、模板(Template)和视图,称为MTV模式:

  • M:代表模型,即数据存取层。该层处理与数据相关的所有事务:如何存取、如何验证有效性、包含哪些行为以及数据之间的关系等。
  • T:代表模板(Template),即表现层。该层处理与表现相关的决定:如何在页面或其他类型文档中进行显示。
  • V:代表视图(View),即业务逻辑层。该层包含存取模型及调取恰当模板的相关逻辑。你可以把它看作模型与模板之间的桥梁。

ORM

ORM就是通过实例对象的语法,完成关系型数据库的操作的技术,是”对象-关系映射”(Object/Relational Mapping)的缩写

ORM:把数据库映射成对象

举例来说,下面是一行SQL语句。

1
2
3
4
SELECT id, first_name, last_name, phone,
birth_date, sex
FROM persons
WHERE id = 10

程序直接运行SQL,操作数据库的写法如下。

1
2
res = db.execSql(sql);
name = res[0]["FIRST_NAME"];

改成ORM的写法如下。

1
2
p = Person.get(10);
name = p.first_name;

比较一下就可以发现,ORM使用对象,封装了数据库操作,因此可以不碰SQL语言。开发者只使用面向对象编程,与数据对象直接交互,不用关心底层数据库
ORM有下面这些优点

  • 数据模型都在一个地方定义,更容易更新和维护,也利于重用代码
  • ORM有现成的工具,很多功能都可以自动完成,比如数据初始化、事务等等
  • 它迫使你使用MVC架构,ORM就是天然的Model,最终使代码更清晰
  • 基于ORM的业务代码比较简单,代码量少,语义性好,容易理解
  • 不必编写性能不佳的SQL

ORM也有很突出的缺点

  • ORM库不是轻量级工具,需要花很多精力学习和设置
  • 对于复杂的查询,ORM要么是无法表达,要么是性能不如原生的SQL
  • ORM抽象掉了数据库层,开发者无法了解底层的数据库操作,也无法定制一些特殊的SQL

Django项目搭建

创建项目

在命令行中执行代码

1
2
django-admin startproject demo

  • django-admin为内部命令
  • startproject为参数
  • demo项目名

备注
避免使用Python或Django的内部保留字来命名项目。比如说,避免使用像django(会和Django自己产生冲突)或test(会和Python的内置组件产生冲突)这样的名字

项目结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
demo/     #项目的名称

manage.py #管理Django项目的命令行工具,启动和结束等

demo/ #项目主应用,它是一个Python包

__init__.py #一个空文件,告诉Python这个目录是一个Python包

settings.py #项目的配置文件,有关于数据库、编码、时区等

urls.py #项目的url路由配置,即url路由与其函数的对应配置

wsgi.py #用于项目与WSGI兼容的Web服务器入口,用于项目部署

启动项目

  • 命令行窗口中,进入最外层的demo
  • 运行命令
    • python manage.py runserver
    • 额外参数
      • python manage.py runserver 8000
      • python manage.py runserver 127.0.0.1:8001
  • 查看运行日志
  • 检查服务,查看欢迎页面
    在浏览器输入:http://127.0.0.1:8000或者http://localhost:8000

第一个Django程序

  • 创建一个子应用

    1
    python manage.py startapp myapp01
  • 修改settings.py配置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    INSTALLED_APPS=[
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'myapp01' #子应用必须配置,否则不起作用
    ]
  • 修改urls.py配置

    1
    2
    3
    4
    5
    6
    from first_app import views

    urlpatterns=[
    path('admin/',admin.site.urls),
    path('test/',views.first_test),
    ]
  • 修改views.py配置

    1
    2
    3
    4
    5
    6
    7
    from django.http import HttpResponse
    #Createyourviewshere.

    deffirst_test(request):
    print('第一个Django项目views')

    return HttpResponse('Django项目第一次请求成功')

Django配置文件-初识

介绍

Django项目创建后,在主应用中,会有一个settings.py文件,这个就是该项目的配置文件

  • settings文件包含Django安装的所有配置
  • settings文件是一个包含模块级变量的python模块,所以该模块本身必须符合python规则,并且可以使用python的语法
  • settings中的所有配置项的key必须全部大写
  • settings中每一个配置项都有默认值,默认配置内容在django/conf/global_settings.py中可以查看到,项目中不需要导入该模块,django框架会自动获取
  • settings中可以添加自定义的配置项

配置文件的使用

  • manage.py启动
    1
    python manage.py runserver

程序中获取配置项

如果在项目代码中需要获取settings中的配置项,这样获取:

1
2
3
4
5
#切记不要导入具体的settings模块的路径,会形成高耦合
#这样的方式是不可取的:from mysite import settings
from django.conf import settings

d=settings.DEBUG

URL调度器-介绍

当一个用户请求Django站点的一个页面,下面是Django系统决定执行哪个Python代码使用的算法:

  • Django确定要使用的根URLconf模块,一般是在settings中的ROOT_URLCONF设置的值,但是如果传入HttpRequest对象具有一个urlconf属性(由中间件设置),则其值将用于代替ROOT_URLCONF设置。
  • Django加载该URLconf模块并查找变量urlpatterns,它是一个列表django.urls.path()和/或django.urls.re_path()实例。
  • Django按顺序遍历每个URL模式,并停在与请求的URL匹配的第一个URL模式,需要特别注意编写的顺序
  • 一旦某个URL模式匹配,Django就会导入并调用给定的视图,该视图是一个简单的Python函数(或基于类的视图方法)。该视图通过以下参数传递:
    • 一个HttpRequest实例。
    • 如果匹配的URL模式没有返回任何命名组,则来自正则表达式的匹配作为位置参数提供。
    • 关键字参数由路径表达式匹配的任何命名部分组成,并由可选的kwargs参数传给django.urls.path()或django.urls.re_path()。
  • 如果没有URL模式匹配,或者在此过程中的任何点发生异常,Django将调用适当的错误处理视图

URL调度器-基本使用

配置子应用urls.py

1
2
3
4
5
6
7
8
from django.urls importpath
urlpatterns=[
path('user/',user),
path('user/info/',user_info),
path('user/<id>/',user_id),
path('user/<id>/<year>/',user_id_year),
path('user/<int:id>/',user_int),
]

注意

  • 从URL中捕获值,请使用尖括号
  • 捕获的值可以选择包含转换器类型。例如,用于int:name捕获,前面的int指整数参数,name是参数的名称
  • 没有必要添加一个前导斜杠,因为每个URL都有,例如,使用articles而不是/articles

路径转换器

  • str:匹配任何非空字符串,不包括路径分隔符’/‘。如果转换器不包含在表达式中,这是默认值。
  • int:匹配零或任何正整数。返回一个int。
  • slug:匹配由ASCII字母或数字组成的字符串,以及横线和下划线字符。例如:building-your-1st-django_site可以匹配,django_@site是不可以匹配的。
  • uuid:匹配格式化的UUID。为防止多个URL映射到同一页面,必须包含破折号,并且字母必须是小写。例如,075194d3-6885-417e-a8a8-6c931e272f00。返回一个UUID实例。
  • path:匹配任何非空字符串,包括路径分隔符’/‘,可以匹配完整的URL路径,而不仅仅是URL路径的一部分str,使用时要谨慎,因为可能造成后续的所有url匹配都失效。
    1
    path('articles/<uuid:uuid>/',views.article_uuid),
    1
    2
    3
    #获取uuid
    import uuid
    print(uuid.uuid1())

URL调度器所有使用方法

urls.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
from django.contrib import admin
from django.urls import path,register_converter,re_path
from url_app.views import *
from user.views import *
from url_converter.converters import YearConverter
from url_converter.views import test_converter
from re_app.views import *
from args_app.views import *

# 注册转换器
register_converter(YearConverter,'yy')

urlpatterns = [
path('admin/', admin.site.urls),
path('url/', test_url),
path('url/', test_url2),
# ------------------------------
path('user/',get_user),
path('user/info/',user_info),
path('user/<id>/',user_id),
# --------------类型转换器----------------
path('converter/<yy:year>/',test_converter),
# --------------正则表达式----------------
re_path('^re/(?P<year>[0-9]{4})/$',test_year),
re_path('^re/(?P<year>[0-9]{4})/(?P<mon>[0-9]{2})/$',test_year_mon),
# page-1 page-2 page-3
# re_path('^re/(?:page-(?p<num>\d+))/$',test_page_num),
re_path('^re/(?:page-(?P<num>\d+))/$', test_page_num),
# --------------默认值----------------
path('args/',get_info),
path('args/<int:page>/',get_info),
# --------------额外参数----------------
path('other_args/',other_arg,{'info':'2030年'}),

]

handler404 = 'error_app.views.page_not_found' # 错误处理

自定义路径转换器

  • 一个regex类属性,作为一个re匹配字符串
  • to_python(self, value)方法,它处理匹配的字符串转换成要传递到视图函数的类型
  • to_url(self, value)方法,用于处理将Python类型转换为URL中使用的字符串

使用正则表达式

正则表达辅助工具
使用正则表达式匹配路径,请使用re_path()而不是path()
在Python正则表达式中,命名正则表达式组的语法是(?Ppattern),其中name是组的名称,并且pattern是一些要匹配的模式

注意事项

  • 无论正则表达式匹配什么类型,每个捕获的参数都以字符串的形式发送到视图
  • 除了命名的组语法,例如(?P[0-9]{4}),也可以使用较短的未命名组,例如([0-9]{4}),但是不建议这样使用,会引起未知的匹配

错误处理

  • handler400-状态码400
  • handler403-状态码403
  • handler404-状态码404
  • handler500-状态码500
  1. 在settings中修改配置:
    1
    2
    3
    DEBUG = False

    ALLOWED_HOSTS = ['*']
  2. 在主应用的urls中配置:
    1
    handler404 = "polls.views.page_not_found"
  3. 在polls应用的views中添加函数page_not_found:
    1
    2
    def page_not_found(request,exception):
    return HttpResponse('自定义的404错误页面')
  4. 浏览器测试访问,找不到匹配的路由

URL调度器-URL反向解析

url调度器除了从用户发起请求,到匹配对应的view,还能在python程序中调用进行匹配,通过path或re_path中的name属性进行解析

  • 在模板中,使用url模板标签
  • 在Python代码中(主要是views),使用reverse()函数

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
from django.contrib import admin
from django.urls import path,include
from product_app.urls import urlpatterns as p_url #导入另一个应用的路由列表(导包) 2


urlpatterns = [
path('admin/', admin.site.urls),
path('',include('user_app.urls')), #添加路径 1

path('product',include(p_url)), #2
path('',include('reverse_app.urls')), #反向解析

]

在模板中测试

  • views.py跳转到页面
    1
    2
    3
    4
    5
    6
    7
    8
    9
    from django.shortcuts import render, HttpResponse,HttpResponseRedirect
    from django.urls import reverse

    # Create your views here.
    def index(request):
    return HttpResponse("成功跳转到被反向解析的地方")

    def index_page(request,page):
    return HttpResponse(f"成功跳转到带参数的反向解析的地方,参数是{page}")

命名空间

命名空间主要用于配合url反向解析使用,多个不同的urls文件中可能配置同名的name,那么为了进行区分,给不同的urls进行不同的命名

注意
同一个项目下命名空间不能重复,切记!

命名空间基本使用

通过在url调度器的模块中,定义app_name = ‘polls’来命名

1
2
3
4
5
6
7
8
9
10
from django.contrib import admin
from django.urls import path,include
from product_app.urls import urlpatterns as p_url #导入另一个应用的路由列表(导包) 2

urlpatterns = [
path('admin/', admin.site.urls),

path('',include('n1_app.urls')), #命名空间1
path('',include('n2_app.urls')), #命名空间2
]

Django模型-介绍

模型,就是python中的类对应数据库中的表
ORM
ORM就是通过实例对象的语法,完成关系型数据库的操作的技术,是”对象-关系映射”(Object/Relational Mapping)的缩写

ORM把数据库映射成对象

示例

模型

1
2
3
4
5
6
from django.db import models

# Create your models here.
class User(models.Model):
first_name = models.CharField(max_length=32)
last_name = models.CharField(max_length=32)

说明

  1. 模型类必须继承models.Model
  2. 每个属性对应数据库表中的一个字段
  3. 表名自动使用应用_类名的小写(如:polls_question),可以覆盖重写
  4. 如果模型类中没有指定primary_key,那么会自动创建一个id字段,自增,主键

Django模型-MySQL和sqlite3的数据库迁移

当编写了模型之后,需要将模型应用到数据库中,具体步骤如下:

  1. 创建项目model_study,及子应用model_app
    1
    2
    3
    4
    5
    #创建项目
    django-admin startproject model_study

    #进入项目目录创建子应用
    python manage.py startapp model_app
  2. 配置应用,将模型对应的应用程序添加到项目的settings中:
    1
    2
    3
    INSTALLED_APPS=[
    'model_app'
    ]
  3. 在settings.py中配置正确的数据库连接:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    # mysql
    DATABASES = {
    'default': {
    'ENGINE': 'django.db.backends.mysql',
    'USER': 'root',
    'PASSWORD':'123456',
    'HOST':'localhost',
    'PORT':'3306',
    'NAME': 'django_demo'

    }
    }

    # sqlite3
    import os
    DATABASES = {
    'default': {
    'ENGINE': 'django.db.backends.sqlite3',
    'NAME': os.path.join(BASE_DIR,'db.sqlite3'),
    }
    }

    注意

    • 需要安装对应数据库的驱动
      • pip install mysqlclient
      • pip install pymysql
        1
        2
        3
        #__init__.py
        import pymysql
        pymysql.install_as_MySQLdb()
    • 需要在mysql数据库中创建数据库model_study

创建迁移

在项目根目录的cmd中运行:

1
python manage.py makemigrations model_app       #model_app是子应用的文件名

备注

  1. model_app是子应用的名称,如果不指定,那么就是对所有INSTALLED_APPS中的应用都进行预备迁移
  2. 指定该命令后,在对应的子应用下的migrations中会生成一个对应的迁移文件

正式迁移

1
python manage.py migrate

备注
没有添加子应用名,那么就会把django项目中所有的应用都迁移到数据库中

Django模型-更新数据库表结构

不管是新增模型,还是修改已有模型后,只需要执行行命令即可:

1
2
python manage.py makemigrations model_app       # 创建数据迁移    
python manage.py migrate # 正式迁移

设置表名

1
2
3
4
5
6
7
8
9
10
11
12
13
from django.db import models

# Create your models here.

class Person(models.Model):
first_name = models.CharField(max_length=32)
last_name = models.CharField(max_length=32)

class Meta:
db_table = 't_person'

def __str__(self):
return self.name

Django模型-逆向从数据库表生成模型类

  1. settings中设置好DATABASES配置
  2. 在对一个数据库中建立好表、约束和表关系等
  3. 在根目录的cmd中运行:
    1
    2
    3
    python manage.py inspectdb > model_app/models.py
    # model_app/models.py子应用的模型文件models.py

    • model_app是子应用名
  4. 第3步执行后会在models中生成对应的模型类
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    from django.db import models

    # Create your models here.

    class Person(models.Model):
    first_name = models.CharField(max_length=32)
    last_name = models.CharField(max_length=32)

    class Meta:
    db_table = 't_person' #对应的数据库中的表名

    def __str__(self):
    return self.name

Django模型-字段介绍

模型类的属性对应数据库中表的字段,都是对应的Field类的实例

字段命名限制

  • 字母,数字,下划线,首字母不能是数字
  • 字段名称不能是Python保留字
  • 由于Django查询查找语法的工作方式,字段名称不能在一行中包含多个下划线,譬如“abc__123”就是不允许的,一个下划线是可以的,如:’first_name’

主键的使用

默认会自动创建一个自增,主键的id列

如果指定了primary_key为其它列,那么不会自动创建id列

例如:

1
id = models.AutoField(primary_key=True)

常见的字段

官方文档

字段名 作用
AutoField 自增一个IntegerField,根据可用的ID自动递增
BooleanField 该字段的默认表单部件是checkbox,默认值是None
CharField 一个字符串字段
DateField 一个日期,在Python中用一个datetime.date实例表示
DateTimeField 一个日期和时间,在Python中用一个datetime.datetime实例表示
FloatField 在Python中用一个float实例表示的浮点数
SmallIntegerField 就是一个IntegerField,-3276832767的值
IntegerField 一个整数。从-21474836482147483647的值
TextField 一个大的文本字段。该字段的默认表单部件是一个Textarea

特别的说明

1
2
3
4
5
6
7
impor tuuid
from django.db import models

class MyUUIDModel(models.Model):
#uuid.uuid4千万别写成uuid.uuid4(),不要写()

id = models.UUIDField(primary_key=True, default=uuid.uuid4)

常见的属性

  • max_length:字段最大长度,用于字符串等,字符串类型CharField必须设置该值
  • null:如果True,Django将在数据库中存储NULL空值。默认是False
  • blank:如果True,该字段被允许为空白(“”)。默认是False。

    注意
    这不同于null。null纯粹是与数据库相关的,而blank与验证相关。如果一个字段有blank=True,表单验证将允许输入一个空值。如果一个字段有blank=False,该字段将是必需的

  • choices:
    示例:YEAR_IN_SCHOOL_CHOICES = ((‘FR’, ‘Freshman’),(‘SO’,’Sophomore’),(‘JR’, ‘Junior’),(‘SR’, ‘Senior’),(‘GR’, ‘Graduate’)) ,中文示例:SEX_CHOICES=((1, ‘男’),(2, ‘女’))元组中的第一个元素是将存储在数据库中的值,第二个元素是将在页面中显示的值,最常见用于下拉选择框select
  • default:字段的默认值
  • help_text:用于显示额外的“帮助”文本
  • primary_key:如果True,这个字段是模型的主键,默认是False
  • unique:如果True,该字段在整个表格中必须是唯一的
  • verbose_name:详细字段名,不指定则是属性名的小写,并且用空格替换’_’

Django模型-1对1关系映射