Django

2005年发布,采用Python语言编写的开源web框架,早期的时候Django主做新闻和内容管理的,重量级的PythonWeb框架,Django配备了常用的大部分组件。

官网:https://www.djangoproject.com/
中文文档:https://docs.djangoproject.com/zh-hans/4.1/
*所有演示基于Django 2.2.12版本

组件包含:

基本配置文件/路由系统
M(模型) T(模板) V(视图)
Cookies 和 Session
分页及邮件系统
Admin后台管理

MTV 设计模式

Model 主要用于对数据库的封装
Templete 用于处理呈现内容
View 用于处理请求,获取数据,返回结果

快速入门指南

#创建项目
root@7cc741924537:~# django-admin startproject mydjango
#启动项目
root@7cc741924537:~/mydjango# python manage.py runserver 5000

###配置setting.py 文件
#通常设置为域名和本机ip,设置为*时允许所有请求头访问
ALLOWED_HOSTS = ['*']
# 指定项目语言 中文为 zh-Hans 
LANGUAGE_CODE = 'zh-Hans'
#用于指定时区 中国可以使用'Asia/Shanghai'
TIME_ZONE = 'Asia/Shanghai'
#设置模板文件夹
DIRS: [os.path.join(BASE_DIR,'templates')]

###模板使用与传参
from django.shortcuts import render
def index(request):
    dic = {'name': 'Mek'}
    return render(request, 'index.html', dic)

安装Django

pip 安装

#安装最新版本
pip install django
#安装指定版本
pip install django==2.2.12

离线安装

安装包下载地址:https://www.djangoproject.com/download/
tar -xvf Django-2.2.28.tar.gz
cd Django-2.2.28
python3 setup.py install

创建Django项目

django-admin startproject mydjango #mydjango为项目名

root@7cc741924537:~# django-admin startproject mydjango
root@7cc741924537:~# ls
mydjango
root@7cc741924537:~#
启动测试
#python manage.py runserver 5000
#5000 为端口号,默认端口号为8000
root@7cc741924537:~/mydjango# python manage.py runserver 5000
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).

You have 17 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.

September 18, 2022 - 10:11:31
Django version 2.2.12, using settings 'mydjango.settings'
Starting development server at http://127.0.0.1:5000/
Quit the server with CONTROL-C
项目结构文件分析
root@7cc741924537:~# tree mydjango/
mydjango/
├── db.sqlite3								#数据库文件,默认的。启动后生成
├── manage.py								#项目管理脚本
└── mydjango								#项目初始化包
    ├── __init__.py
    ├── __pycache__
    │   ├── __init__.cpython-38.pyc
    │   ├── settings.cpython-38.pyc
    │   ├── urls.cpython-38.pyc
    │   └── wsgi.cpython-38.pyc
    ├── settings.py							#项目配置*重点
    ├── urls.py								#配置路由信息
    └── wsgi.py								#用于适配uwsgi,用于正式部署使用

2 directories, 10 files
root@7cc741924537:~#

manage.py 命令详解

python manage.py check appNAME					#检查整个Django项目是否存在常见问题
python manage.py diffsettings					#显示当前设置文件与Django的默认设置之间的差异
python manage.py flush							#从数据库中删除所有数据。已应用的迁移不会被清除。只删除具体数据,不删除数据表
python manage.py makemigrations app1 app2		#根据检测到的模型创建新的迁移。迁移的作用,更多的是将数据库的操作,以文件的形式记录下来,方便以后检查、调用、重做等等。尤其是对于Git版本管理,它无法获知数据库是如何变化的,只能通过迁移文件中的记录来追溯和保存
python manage.py migrate						#使数据库状态与当前模型集和迁移集同步。说白了,就是将对数据库的更改,主要是数据表设计的更改,在数据库中真实执行。例如,新建、修改、删除数据表,新增、修改、删除某数据表内的字段等等
python manage.py runserver						#启用Django为我们提供的轻量级的开发用的Web服务器
python manage.py shell							#启动带有Django环境的Python交互式解释器
python manage.py startapp app_name				#创建新的app
python manage.py startproject project_name		#新建工程

settings.py 配置文件详解

"""
Django settings for mydjango project.

Generated by 'django-admin startproject' using Django 2.2.12.

For more information on this file, see
https://docs.djangoproject.com/en/2.2/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/2.2/ref/settings/
"""

import os

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)

#项目文件路径 
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'vlx8+$5#^bawl!siwyqylv+!-0x*4uc6p2retodl_rx828kia1'

# 开始DEBUG模式,在项目开发阶段启用功能项目有改动对自动重启
DEBUG = True

#运行访问的请求头 *重要
#DEBUG模式下默认只有127.0.0.1和localhost
#通常设置为域名和本机ip,设置为*时允许所有请求头访问
ALLOWED_HOSTS = ['*']


# Application definition
#用于配置Django应用
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

# ROOT_URLCONF 指定该项目主路由文件位置
ROOT_URLCONF = 'mydjango.urls'

# 模板
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'mydjango.wsgi.application'


# Database
# https://docs.djangoproject.com/en/2.2/ref/settings/#databases
# 数据库配置
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}


# Password validation
# https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/2.2/topics/i18n/

# 指定项目语言 中文为 zh-Hans 
LANGUAGE_CODE = 'zh-Hans'

#用于指定时区 中国可以使用'Asia/Shanghai'
TIME_ZONE = 'Asia/Shanghai'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.2/howto/static-files/
# 指定静态资源路径
STATIC_URL = '/static/'
settings.py中也可以添加开发人员自定义的配置
配置建议:名字尽量个性化以防覆盖掉公有配置
例如:ALIPAY_KEY=xxxxxx
settings.py中的所有配置项,都可以按需的在代码中引入
引入方式:from django.conf import settings

编写路由和视图函数

路由文件 urls.py

from django.contrib import admin
from django.urls import path
from .views import *					#导入视图函数

#urlpatterns路由列表
# path() 语法关联试图函数
# path(route,views,name=None)
# route 请求路径
# views 处理请求的视图函数
# name 地址别名

urlpatterns = [
    # http://localhost/
    path('',index,name="index"),		#关联视图函数index
    # http://localhost/admin/
    path('admin/', admin.site.urls),	
    # http://localhost/b/
    path('a/', page_A_view),			#关联视图函数page_A_view
    # http://localhost/b/
    path('b/', page_B_view),			#关联视图函数page_B_view
]

视图文件 views.py

# 导入处理响应的类
from django.http import HttpResponse


def index(request):
    html = '这是我的首页'
    return HttpResponse(html)


def page_A_view(request):
    html = '这是A页面'
    return HttpResponse(html)


def page_B_view(request):
    html = '这是B页面'
    return HttpResponse(html)

url传参

编写规则
##urls.py
# 路由路径/<类型:参数名称>,视图函数
path('page/<int:page>',vies.def)
#支持类型:
		##str		除'/'之外的任意一个非空字符串
    	##int		匹配0和任意整数
        ##slug		匹配任意字母或数字已经链接字符
        ##path		匹配非空字段,包括'/',用于路径传参
        
##views.py
# 试图函数接收参数
def page_A_view(request,page):
    html = '这是%s页面'%(page)
    return HttpResponse(html)

#传参转换器可以连续使用
path('page/<int:page>/<str:id>',vies.def)

def page_id(request,page,id)
html = 'holle,%s,这是第%s页!'%(id,page)

re_path
#匹配一个两位数的m 一个两位数的d和一个四位数的y
re_path(r'`ibirthday/(?P<m>\d{1,2})/(?P<d>\d{1,2})/(?P<y>\d{1,2})$,views.birthday_view)

请求和响应

  • 请求是指浏览器端通过HTTP协议发送给服务器端的数据
  • 响应是指服务器端接收到请求后做相应的处理后再回复给浏览器端的数据
GET					#请求页面信息,并返回响应主体
HEAD				#类似GET请求,请求的响应中没有具体内容,只获取响应头
POST				#向指定资源提交处理请求,例如提交表单/上传文件
在视图函数中第一个获取的传参即为请求体(HttpRequest)

def index(request):
    print(request.path_info)  # 获取请求路径
    print(request.method)  # 获取请求方法

    # GET    获取GET传参
    # POST   获取POST传参
    # FILES  获取类型字典的对象,包含文件
    # COOKIES 获取Cookie,返回字典
    # session 返回类似字典的对话
    # body    请求体的内容,获取POST或者PUT方法传参
    # META    请求中的元数据

    html = '这是我的首页'
    return HttpResponse(html)

常见状态码
-200		#请求成功
-301		#永久重定向
-302		#临时重定向
-404		#请求资源不存在
-500		#内部服务器错误
路由函数不同请求方式处理办法
def page_A_view(request):
    if request.method == 'GET':  # 此处处理GET请求
        
        a = request.GET.get('a', None)  # 获取传参,None为默认值
        a = request.GET['a']            # 获取传参,没有该值会报错
        a = request.GET.getlist('a')    # 获取传参列表

        return HttpResponse(a)

    elif request.method == 'POST':  # 处理POST请求
        
        #同GET获取传参方法
        pass
    else:
        html = '这是A页面'
        return HttpResponseNotFound()

总结
GET请求传参-查询字符串-少量数据-非敏感数据
POST请求传参-敏感数据

模板配置

在项目中创建模板文件夹 templates
在settings.py 中 TEMPLATES 配置项:
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

# BACKEND 		指定模板引擎
# DIRS			模板文件夹
# APP_DIRS 		是否要在应用中的 templates 中搜索模板
# OPTIONS		有关模板的选项
#设置模板文件夹
#'DIRS': [os.path.join(BASE_DIR,'templates')]
使用模板
from django.shortcuts import render
def index(request):

    return render(request, 'index.html')

模板传参
#视图函数,模板只接受字典传参
from django.shortcuts import render
def index(request):
    dic = {'name': 'Mek'}
    return render(request, 'index.html', dic)
#HTML模板端
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>Hello.{{name}}!</h1>	
</body>
</html>

#使用 {{key}} 获取传参
模板能接受到的参数类型
srt		#字符串
int		#整数
list	#列表
tuple	#元组
dict	#字典
func	#方法
obj		#实例化对象

#获取传参的方法
{{变量名}}				#用于字符串和整数
{{变量名.索引}}		   #用于列表或者元组
{{变量名.key}}			#用于字典
{{对象.属性}}			#用于实例化对象
{{函数名}}				#用于函数
模板标签语言
#if 判断式

{% if 表达式 %}
	运行体...
{% elif 表达式2 %}
	运行体...
{% elif 表达式3 %}
	运行体...
{% elif 表达式4 %}
	运行体...
{% else %}
	运行体...
{% endif %}

#for 循环语句
{% for 变量 in 迭代对象 %}
	循环语句...
{% empty %}
	无可迭代对象时语句...
{% endfor %}
模板过滤器和模板继承
过滤器的定义:在变量输出时对变量值进行处理

使用方法 : {{变量|过滤器:‘参数’}}

#常见过滤器
lower			#将字符串转换为小写
upper			#将字符串转换为大写
safe			#不对HTML标签进行转译
add:'n'			#将值增加n
模板继承可以使父模板内容复用,子模板可以直接继承父模板的全部内容并覆盖部分内容
#父模板预留block
{% block name %}

{% endblok name %}

#子模版继承
{% extend 'base.html' %}
{% block name %}
	该区块内容...
{% endblok name %}

url反向解析

url 反向解析是指在视图或模板中,用path定义的名称来动态查找

在路由中设置别名:

#通过name设置路由别名
urlpatterns = [
    # http://localhost/
    path('',index,name="index")]

在模板中使用:

#解析url
{% url '别名' %}
#解析并传递参数
{% url '别名' '参数1' '参数2' %}

#示例
{% url 'page' '20' %}
{% url 'q' age='18' name='Mek' %}

静态文件配置

静态文件路径配置在 settings.py 中默认存在

STATIC_URL = ‘/static/’

指定访问静态文件时通过/static/xxxxf访问

示例:http://127.0.0.1:8000/static/xxxx.js

STATIC_URL = '/static/'			# 配置静态资源url
STATICFILES_DIRS = (			# 配置静态资源存储路径
    os.path.join(BASE_DIR,'static')
)

在html中使用:

#直接访问
<img src="http://127.0.0.1:8000/static/image/demo.jpg">
#通过模板函数加载
{% load static %}						#加载模板函数
{% static '/image/demo.jpg' %}			#加载静态资源
<img src="{% static '/image/demo.jpg' %}">

ORM模型映射

安装mysql依赖

sudo apt-get install python3-dev default-libmysqlclient-dev
sudo pip3 install mysqlclient

在settings.py 中修改数据库配置

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',			#指定数据库引擎
        'NAME': 'db',									#指定数据库名
        'USER': 'root',									#指定用户名
        'PASSWORD': 'passwd',							#指定密码
        'HOST': '127.0.0.1',							#指定主机地址
        'PORT': 3306									#指定端口号
    }
}

#其他数据库引擎
django.db.backends.mysql
django.db.backends.sqlite3
django.db.backends.oracle
django.db.backends.postgresql

定义模型

模型写法
# 导入模型类
from django.db import models

#创建新模型
class Person(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)
    
'''
class 模型名称(models.Mode):
	属性1 = models.模型属性('别名',模型属性)
	属性2 = models.模型属性('别名',模型属性)
	
	class Meta:
		de_table = '数据表名称
'''
迁移更新
模式可用属性
## 地址
# varchar
# 正则表达式邮箱,继承CharField
v = models.EmailField([max_length=75, **options])
 
# varchar
# 地址正则表达式,继承CharField
v = models.URLField([verify_exists=True, max_length=200, **options]) 
 
# varchar
# ip4正则表达式
v = models.IPAddressField([**options])
 
# varchar
v = models.GenericIPAddressField
 
 
## 时间
# datetime
# auto_now=True每次更新都会更新这个时间
# auto_now_add=True自动记录创建时间
v = models.DateField([auto_now=True,auto_now_add=True, **options])
 
# datetime
# 继承DateField
v = models.DateTimeField([auto_now=True,auto_now_add=True, **options])
 
# time
# 时间 HH:MM[:ss[.uuuuuu]]
v = models.TimeField([auto_now=False, auto_now_add=False, **options])
 
 
## 数字
# double
v = models.FloatField([**options])
 
# 小整型(-32768,32767)
v = models.SmallIntegerField([**options])
 
# int
# 整型(-2147483648,2147483647)
v = models.IntegerField([**options])
 
# 长整型(-9223372036854775808,9223372036854775807)
v = models.BigIntegerField([**options])
 
# 正小整型(0,32767)
v = models.PositiveSmallIntegerField([**options])
 
# 正整型(0,2147483647)
v = models.PositiveIntegerField([**options])
 
 
## 布尔
# boolean或bit
# 不允许为null
v = models.BooleanField([**options]) 
 
# boolean或bit
# 允许为null
v = models.NullBooleanField([**options])
 
# bit 存储二进制数据
v = models.BinaryField([**options]) 
 
# decimal
# 十进制小数类型,必须指定整数位max_digits和小数位decimal_places
v = models.DecimalField(max_digits=None, decimal_places=None[, **options]) 
 
## 字符串
# varchar
# 必须设置max_length  ***常用            
v = models.CharField(max_length=None[, **options])  
 
# varchar 
# 用逗号分割的数字
# 继承CharField,所以必须设置max_length
v = models.ComaSeparatedIntegerField(max_length=None[, **options])
 
## 文件路径
# varchar
# upload_to指定保存目录可带格式 
v = models.FileField(upload_to=None[, max_length=100, **options]) 
 
# varchar
v = models.FilePathField(path=None[, match=None, recursive=False, max_length=100, **options])
 
# 继承FileField 用于保存图片路径
v = models.ImageField(upload_to=None[, height_field=None, width_field=None, max_length=100, **options])
 
# text 文本
v = models.TextField([**options]) 
 
# text   xml文本
v = models.XMLField(schema_path=None[, **options]) 
   
 
## 其他
# 自增
# 如果没有的话,默认会生成一个名称为 id 的列
# 如果要显示的自定义一个自增列,必须将给列设置为主键 primary_key=True。
v = models.AutoField([**options])  
 
# varchar
# 标签,内含索引,减号、下划线、字母、数字
v = models.SlugField([max_length=50, **options])
 
# 外键,关联其它模型,创建关联索引
v = models.ForeignKey(othermodel, on_delete=None[, **options])
 
# 一对一
# 字段关联表属性
v = models.OneToOneField(othermodel[, parent_link=False, **options])
 
# 多对多
# 关联其它模型,创建关联表
v = models.ManyToManyField(othermodel[, **options])

模型可用选项

null=True # 数据库中字段是否可以为空
 
primary_key=False # 主键,对AutoField设置主键后,就会代替原来的自增 id 列
 
auto_now=True # 自动创建---无论添加或修改,都是当前操作的时间
 
auto_now_add=True # 自动创建---永远是创建时的时间
 
# 选择项
GENDER_CHOICE=(
(u'M', u'Male'),
(u'F', u'Female'),
)
choices=GENDER_CHOICE 
e.g.:gender = models.CharField(max_length=2,)
 
max_length=100 # 最大长度
 
default # 默认值
 
verbose_name  # admin中字段显示的名称
 
name|db_column # 数据库中字段的名称
 
unique=True # 不允许重复
 
db_index=True # 数据库索引
 
error_messages=None # 错图提示
 
auto_created=False # 自动创建
 
blank=True # 从django的Admin中添加数据时是否可允许空值
 
editable=True # 在admin中是否可编辑
关系映射

在关系型数据库中,通常不会把所有数据放在一张表中,常见的关系映射有:

  • 一对一
  • 一对多
  • 多对多
# 一对一映射

class A(models.Model):
    ....
class B(model.Model)
	....
    属性 = models.neoToOneField(A,on_delete=models.CASCASDE)

# on_delete设置级联删除规则
# models.CASCASDE		联级删除
# models.PROTECT		阻止引用对象被删除
# SET_NULL				设置外键为空,需要指定null=True
# SET_DEFAULT			将外键设置为默认值,需提前指定默认值

## 外键模型创建对象

b = B.objects.create(name='123',author=主键对象)
b = B.objects.create(name='123',author_id=主键对象id)

Cookie和session

服务端设置cookie
HttpResponse.set_cookie(key,value='',max_age=7200,expires=None)
# key		键
# value		值
# max_age	存活时间 秒
# expire	具体过期时间

服务端获取cookie或删除cookie

#删除指定key的cookie
HttpResponse.delete_cookie(key)
#获取cookie
request.COOKIES.get('key','默认值')
使用sessions

检测settings.py 文件session配置项是否正确,默认情况下是开启的

#settings.py


INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',									#检测此项
    'django.contrib.messages',
    'django.contrib.staticfiles',

]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',		#检测此项
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
#服务端保存session
request.session['Key'] = VALUE

#服务端获取session
value = request.session['KEY']
value = request.session.get('KEY',默认值)

#删除session
del request.session['KEY']