python Web 框架Django学习之路 官网

安装Django

1
pip install django

创建项目

1
django-admin startproject [project_name]

项目目录结构

1
2
3
4
5
6
7
8
9
[project_name]
│ manage.py # 管理项目的命令行工具 【不要动】 【常常使用】

└─[project_name] # 项目配置目录
│ asgi.py # 接收网络请求 【异步】 【不要动】
│ settings.py # 项目配置文件 【常常修改】
│ urls.py # url 和 python 函数的映射关系 【常常修改】
│ wsgi.py # 接收网络请求 【同步】 【不要动】
└─ __init__.py

APP

创建应用

1
python manage.py startapp [app_name]

应用目录结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[project_name]
│ manage.py # 管理项目的命令行工具 【不要动】

├─[app_name] # 应用程序目录
│ │ admin.py # 管理后台配置 【固定,不用动】
│ │ apps.py # 应用程序配置 【固定,不用动】
│ │ migrations # 数据库迁移目录 【固定,不用动】
│ │ └─ __init__.py
│ │
│ │ models.py # 数据模型 【对数据库进行操作】
│ │ tests.py # 测试代码 【固定,不用动】
│ │ views.py # 视图函数 【重要,常常编写】
│ └─ __init__.py

└─[project_name] # 项目配置目录
│ asgi.py # 接收网络请求 【异步】 【不要动】
│ settings.py # 项目配置文件 【常常修改】
│ urls.py # url 和 python 函数的映射关系 【常常修改】
│ wsgi.py # 接收网络请求 【同步】 【不要动】
└─ __init__.py

一个项目可以包含多个应用,但是我们开发一般比较简洁,一个项目就一个应用

1
2
3
4
5
- 项目
- APP 包含独立的功能模块(表结构、函数、HTML模板、CSS)
- APP 包含独立的功能模块
- APP 包含独立的功能模块
...

注册应用

1
2
3
4
5
6
7
# [project_name]/settings.py
# 这里以 app 名为 'app01' 为例
INSTALLED_APPS = [
...
'app01.apps.App01Config', # 也可以直接写 'app01'
...
]

app01.apps.App01Config实际链接处

启动运行项目

注意:

  • 确保app已注册
  • 编写URL和视图函数
1
python manage.py runserver

快速上手

添加新页面

编写URL和视图函数

1
2
3
4
5
6
7
8
# [project_name]/urls.py
from django.urls import path
from app01 import views

urlpatterns = [
path('index/', views.index),
path('login/', views.login),
]
1
2
3
4
5
6
7
8
# app01/views.py
from django.shortcuts import render

def index(request):
return render(request, 'index.html')

def login(request):
return render(request, 'login.html')

url和函数的对应关系

template 模板

在app目录下创建 templates 文件夹,并在其中创建 index.html 和 login.html 文件

默认会在 [app_name]/templates/ 目录下寻找模板文件,需要注意的是,他其实并不是在当前的 app 目录下面找,
而是根据 app 的注册顺序,逐一去他们的 templates 目录下查找,先找到谁的同名模版就用谁的!!!

模板查找原理

如果在 setting.py 中配置了 TEMPLATESDIRS,则会在配置的路径下查找模板文件
没找到,则会在 APP_DIRS 中配置的路径下查找

TEMPLATES 的 DIRS 有配置时

静态资源文件

在app目录下创建 static 文件夹,并在其中创建 css、js、images、plugins 文件夹。官方文档

  1. 确保文件包含在应用程序中
  2. setting.py 中定义 STATIC_URL,例如:

    1
    STATIC_URL = '/static/'
  3. 在模板中使用template标签构建,使用配置的别名给定相对路径,例如:

    1
    2
    {% load static %}
    <img src="{% static 'my_app/example.jpg' %}" alt="My image">
  4. 将静态资源文件存储在app(APP_DIR)中,例如:PROJECT_DIR/APP_DIR/static/img/example.jpg

项目中可能还会包含没有绑定到项目中的资源文件,除了在app内使用目录外,还可以在 settings.py 中 配置 STATICFILES_DIRS,Django 也会在其中查找静态文件。例如:

1
2
3
4
STATICFILES_DIRS = [
BASE_DIR / "static",
"/var/www/static/",
]

模板语法

本质上是在html中写一些占位符,然后由数据对这些展位符进行处理。
这里有个例子:使用视图函数和模板引擎来渲染一个简单的网页

基础语法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

<!-- 变量 -->
<p>{{ 变量名 }}</p>

<!-- 标签 -->
<p>{% 标签名 %}</p>

<!-- 过滤器 -->
<p>{{ 变量名|过滤器 }}</p>

<!-- 注释 -->
{# 注释内容 #}

<!-- 模板继承 -->
{% extends 'base.html' %}

<!-- 模板包含 -->
{% include 'nav.html' %}

<!-- 加载静态资源 -->
{% load static %}

常用标签

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

{% load static %} # 加载静态资源
{% static 'css/style.css' %} # 使用静态资源

{% csrf_token %} # 生成CSRF令牌

{% for item in list %} # 循环
{{ item }}
{% endfor %}

{% for key in list.keys() %} # 循环
{{ key }}
{% endfor %}

{% for value in list.values() %} # 循环
{{ value }}
{% endfor %}

{% for key,value in list.items %} # 循环
{{ key }} = {{ value }}
{% endfor %}

{% if condition %} # 条件判断
<p>条件为真</p>
{% else %}
<p>条件为假</p>
{% endif %}

{% extends 'base.html' %} # 继承模板
{% block block_name %} # 块
{% endblock %}

{% include 'nav.html' %} # 包含其他模板

常用过滤器

1
2
3
4
5
6
7
8
9
10

{{ 变量名|default:"默认值" }} # 如果变量为空,则使用默认值
{{ 变量名|length }} # 返回变量的长度
{{ 变量名|date:"Y-m-d H:i:s" }} # 格式化日期
{{ 变量名|safe }} # 将变量作为HTML渲染
{{ 变量名|truncatechars:10 }} # 截断字符串
{{ 变量名|filesizeformat }} # 格式化文件大小
{{ 变量名|add:10 }} # 加法运算
{{ 变量名|divisibleby:2 }} # 判断是否可被2整除

自定义过滤器

1
2
3
4
5
6
7
8
9

from django import template

register = template.Library()

@register.filter(name='add_ten')
def add_ten(value):
return value + 10

1
2
3

{{ 变量名|add_ten }}

自定义标签

1
2
3
4
5
6
7
8
9

from django import template

register = template.Library()

@register.simple_tag(name='add')
def add(a, b):
return a + b

1
2
{% add 10 20 %}

请求与响应

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
38
39
40
41
from django.http import render, HttpResponse, HttpResponseRedirect


def something(request):

# 获取GET请求参数
print(request.GET)

# 获取POST请求参数
print(request.POST)

# 获取上传的文件
print(request.FILES)

# 获取Cookie
print(request.COOKIES)

# 获取请求头)
print(request.META)

# 获取Session
print(request.session)

# 获取请求方法
print(request.method)

# 获取请求路径
print(request.path)


# 渲染模板并返回响应
response = render(request, 'index.html', {'name': '张三'})

# 返回字符串响应
response = HttpResponse('Hello World')

# 重定向到指定路径
response = HttpResponseRedirect('/index/')

return response

数据库操作 (ORM)

Django 操作数据库

ORM可以帮我们做两件事:

  • 创建、修改、删除数据库中的表
  • 操作数据库中表的数据

注意: ORM并不能帮我们创建数据库,需要自行创建数据库

Django操作数据库

安装 mysqlclient

1
pip install mysqlclient

配置数据库(官网)

1
2
3
4
5
6
7
8
9
10
11
# settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'test',
'USER': 'root',
'PASSWORD': '123456',
'HOST': '127.0.0.1',
'PORT': '3306',
}
}

创建模型

注意: 在创建模型之前,需要确保该app已经注册到settings.py中的INSTALLED_APPS中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from django.db import models

# 定义模型类继承自models.Model
class User(models.Model):
# models.CharField(max_length=32) 字符串类型,长度 32
# models.IntegerField(default=0) 数字整型,默认为 0
name = models.CharField(max_length=32)
password = models.CharField(max_length=64)
mobile = models.CharField(max_length=11)
role = models.IntegerField(default=0, null=True)

"""
以上代码会生成以下表结构(为了理解,底层不知道是不是这样)
CREATE TABLE `app01_user` (
`id` bigint AUTO_INCREMENT PRIMARY KEY,
`name` varchar(32) NOT NULL,
`password` varchar(64) NOT NULL,
`mobile` varchar(11) NOT NULL,
`role` int(11)
"""

生成迁移文件

生成迁移文件,用于记录数据库的变更,执行 [PROJECT_NAME]/manage.py 文件,参数为 makemigrations

1
python manage.py makemigrations

注意:

  • 每次修改模型后,需要执行该命令,生成迁移文件
  • 当数据表中已经存在数据时,添加表模型字段,需要设置默认值设置[null=True],否则可能会报错

执行迁移

执行迁移,将变更应用到数据库

1
python manage.py migrate

操作数据

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
from app01.models import User

# 创建数据
User.objects.create(name='admin', password='123456', mobile='12345678901', role=1)
User.objects.create(name='user', password='123456', mobile='12345678901', role=0)

# 查看数据
# data_list = [对象, 对象, 对象] QuesySet类型
data_list_1 = User.objects.all()
for row in data_list_2:
print(row.name, row.password, row.mobile, row.role)
# 虽然添加了name='admin',但是查询时,只有一条记录,返回的也是->列表里面包含一个对象
data_list_2 = User.objects.filter(name='admin')
# 只取第一条,这时候就是一个对象了
data_list_3 = User.objects.filter(name='admin').first()

# 修改数据,先筛选在操作
User.objects.all().update(role=0)
User.objects.filter(name='admin').update(password='654321')

# 删除数据

# 删除 先筛选在操作
User.objects.filter(name='admin').delete()
User.objects.all().delete()

简单案例