Django 是一个由 Python 编写的一个开放源代码的 Web 应用框架。
Django 的哲学:
- DRY(Don't Repeat Yourself): 避免重复代码,提倡复用(如模板继承、模型继承)。
- 约定优于配置: 默认提供合理配置(如自动生成 Admin 界面),减少决策成本。
- 快速开发: 从原型到生产环境均可高效推进。
- MVT架构,Model View Template(模版)
Django 中采用了 MVT 设计模式,类似于 MVC,但有一些区别:
Model (模型):与数据库交互,处理数据的创建、读取、更新、删除。
Template (模板):负责页面渲染,生成最终的 HTML 内容。
View (视图):Django 的 View 更偏向于控制器的角色,接收请求并决定使用哪个模板和数据。
Django模版
HelloWorld/ # 项目根目录
├── manage.py # 项目管理脚本
├── db.sqlite3 # SQLite 数据库文件
├── __pycache__/ # Python 字节码缓存
└── HelloWorld/ # 项目配置目录(与项目同名)
├── __init__.py # 包标识文件
├── settings.py # 项目设置
├── urls.py # 主路由配置
├── asgi.py # ASGI 配置
└── wsgi.py # WSGI 配置
- manage.py文件,项目管理命令行工具,内置多种方式与项目进行交互。比如启动项目,创建app,数据管理等。
- settings.py 项目配置文件,所有工具都需要在该文件中进行配置。
- urls.py 项目的路由配置,设置网站的具体网址内容
- wsgi.py: pyhton的服务器网关接口,是python应用在web服务器之间的接口,用于Django项目在服务器上的部署和上线。。
- asgi.py: 开启一个ASGI服务,ASGI是异步网关协议接口。
一个Diango项目,可以有多个Diango应用


通过python manage.py startapp blog就可以创建blog的django应用。

如上,myproject就是django项目,而blog就是一个django 应用
views.py:视图处理的地方,在适当的时候调用model和template
models.py:ORM,业务对象与数据库的对象
template: 模版,负责如何把页面展示给用户。
admin.py: 定义admin模块管理对象的地方
urls.py: 路由分发器,将路由分到不同的views
apps.py: 声明应用的地方
tests.py 编写应用测试用例的地方

MTV
Django 视图 & Django 路由
创建一个视图
1 在blog的views.py创建hello world视图
python
from http.client import HTTPResponse
from django.shortcuts import render
# Create your views here.
# 视图
def hello_word(request):
return HTTPResponse("hello world")
2 在应用层的urls.py配置路由
python
from django.urls import path, include
import blog.views;
# 2 应用配置路由
urlpatterns = [
path("hello_word", blog.views.hello_word)
]
3 在项目层的urls配置路由
python
from django.contrib import admin
from django.urls import path, include
# 3 项目配置路由
urlpatterns = [
path('admin/', admin.site.urls),
# 如果是blog,就转发到blog.urls
path("blog/", include("blog.urls")),
]
如果是blog开头的,全部转发到blog.urls子路由去。
4 在项目的setting.py中配置app
python
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# 5 添加应用
'blog.apps.BlogConfig',
]
可以看到默认已经有了很多app,admin,auth等,在这里添加上我们blog的app,BlogConfig是在初始化的时候命名的。

这时候访问8080/blog/hello_word就路由到hello_word函数了。
模型层
模型层位于 视图层 和 数据库之间的,主要是将python对象和数据库表的数据进行转换。
模型层可以屏蔽不同数据库之间的差异。
让开发者专注业务逻辑的开发。

模型层配置。
创建博客文章模型
设计博客模型,有点像数据库设计,nest的typeorm。
- id int (自增,主键)
- 标题 str
- 描述 str
- 创建时间 日期
模型层定义字段 - 数字类型: IntegerField
- 文本类型:TextField
- 日期类型:DateTimeField
- 自增id AutoField
- 主键: primary_key
在blog的models.py中定义模型
python
from django.contrib.auth.models import User
from django.db import models;
# Create your models here.
class Atricle(models.Model):
article_id = models.AutoField(primary_key=True)
title = models.TextField()
biref_content = models.TextField()
content = models.TextField()
publish_date = models.DateTimeField(auto_now=True)
create_date = models.DateTimeField(auto_now_add=True)
update_date = models.DateTimeField(auto_now=True)
然后终端执行
python3 manage.py makemigrations生成迁移文件
python3 manage.py migrate 同步迁移到Django的数据库
Django Shell
用于交互式的Python编程,会继承项目环境,可以调用模块。
python3 manage.py shell会进入一个编程环境

创建一个文章,.save保存到数据库。

可以看到正常加入了。
Django Admin模块
Django 的后台管理工具,可以管理模型数据。
Django Shell 太麻烦了,使用Admin模块比较方便。
python3 manage.py createsuperuser命令行输入创建admin用户,然后启动项目,访问/admin

可以看到有两个模块,然后需要在blog的admin.py文件中,注册blog到admin。
python
from django.contrib import admin
# Register your models here.
from .models import Atricle;
admin.site.register(Atricle)

刷新后就能看到了
Django 的模版系统
变量语法
{``{now}}


在blog创建templates目录,创建blog目录,创建index.html文件
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>学习Django</title>
</head>
<body>
{% for article in article_list %}
<div>{{article.title}}</div>
<div>{{article.content}}</div>
<div>{{article.publish_date}}</div>
{% endfor %}
</body>
</html>
然后,视图view.py定义加上
python
def get_index_page(request):
articles = Atricle.objects.all()
return render(request, 'blog/index.html', {'article_list': articles})
通过render渲染模版系统,像ejs。
python
# 2 应用配置路由
urlpatterns = [
path("hello_word", blog.views.hello_word),
path("article", blog.views.article),
path("index", blog.views.get_index_page)
]
加上路由,

正常显示。
动态路由
python
def get_detail_page(request, id):
article = Atricle.objects.get(article_id=id)
return render(request, 'blog/detail.html', {'article': article})
配置动态路由
python
urlpatterns = [
path("hello_word", blog.views.hello_word),
path("article", blog.views.article),
path("index", blog.views.get_index_page),
path("detail/<int:id>", blog.views.get_detail_page)
]
访问:

项目 settings.py文件

App列表内置:
admin: 后台管理系统
auth: 用户认证系统
contenttypes: 记录所有model元数据,Diango的ORM框架
sessions: session会画功能
messages: 消息提示功能
staticfiles: 查找静态资源路机
资源文件配置
静态资源+媒体资源(动态)
静态资源配置: STATIC_URL
python
STATIC_URL = "static/"
只能访问应用下的static下的文件
多个静态资源配置
pyhon
STATICFILES_DIRS = [ BASE_DIR / "static", BASE_DIR / "helloWorld / images" ]
表示访问根目录下的static和hellowrold.images
线上静态资源配置:
python
# 线上配置静态资源
STATIC_ROOT = BASE_DIR / 'static'
需要配合指令collectstatic来收集所有静态资源。
媒体资源配置:MEDIA
比如用户头像等。
python
# 设置媒体路由
MEDIA_URL = 'media/'
# 设置mediam目录的完整路径
MEDIA_ROOT = BASE_DIR / 'media'
此外,还需要在项目路由里面配置。
python
# 3 项目配置路由
urlpatterns = [
path('admin/', admin.site.urls),
# 如果是blog,就转发到blog.urls
path("blog/", include("blog.urls")),
re_path("media/(?P<path>.*)", serve, {'document_root': settings.MEDIA_ROOT}, name="media"),
]
模版配置

pytho
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE_DIR / 'templates', BASE_DIR / 'blog/templates'],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
数据库配置

python
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'python123',
'USER': 'root',
'PASSWORD': '1234',
'HOST': 'localhost',
'PORT': "3306",
}
}
需要安装
pip install mysqlclient
然后运行migrate命令,这样表都会更新到mysql里面了。

中间件
对请求/输出做额外的处理,比如统一输出结果等。

python
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',
]
自带中间件

自定义中间件

路由变量

正则路由

路由重定向


namespace

路由命名+反向解析reverse 与 resolve
python
def article(request):
str = reverse("blog:article");
result = resolve(str)
print(f"result: {result}")
articles = Atricle.objects.all()
return HttpResponse(articles)

可以反向获得路由地址以及对象
视图状态

重定向

二进制文件下载响应


Http请求和请求类


query参数,post body参数也是一样

会话管理 cookie & sessionId
python
request.COOKIES.get('key')
request.get_signed_cookie(key, default=RAISE_ERROR, slat="", max_age=None)
设置cookie

Session
request.session.get('k1', None)


文件上传

视图类
Django 视图 - FBV 与 CBV
-
FBV(function base views) 基于函数的视图,就是在视图里使用函数处理请求。
-
CBV(class base views) 基于类的视图,就是在视图里使用类处理请求。
之前我们一直使用的是基于函数的视图 FBV,就是在views.py中定义一个函数,然后接受request字段,使用的时候是
paht("user", user.view.get_index_page, name="test")
而CBV是基于类的视图,需要继承View
不同请求可以在类中通过定义不同方法来处理。
urlpatterns = [ path("login/", views.Login.as_view()), ]
使用的时候是as_view
python
rom django.shortcuts import render,HttpResponse
from django.views import View
class Login(View):
def get(self,request):
return HttpResponse("GET 方法")
def post(self,request):
user = request.POST.get("user")
pwd = request.POST.get("pwd")
if user == "runoob" and pwd == "123456":
return HttpResponse("POST 方法")
else:
return HttpResponse("POST 方法 1")
get请求就走到get方法,post请求就走到post方法
列表视图ListView



可以将数据库的数据,传给模版平铺展示
详细视图DetailView

模版引擎



过滤器: {{ msg | capfirst }},对数据进行操作。
模型定义与使用
Django的ORM框架,实现数据库的连接和读写操作。
在settings.py中配置数据库,在models新建模型类(指定表字段),通过migrate数据库迁移生成表。
在其他模块比如视图函数中,调用模型对数据库进行增删改查

ForeignKey是关联模型
Meta是嵌套类,可以指定表的名字,以及描述
执行makemigration生成数据库迁移文件,然后在执行migrage执行迁移文件,同步到数据库中。
模型查询

model.objects.all() 查询表格所有数据。

分页,select指定字段,根据id查询。
where查询:

or查询是.filter( Q(id=1) | Q(price=88))
exclude: 不满足条件
python
# 也可以使用exclude 返回满足条件之外的数据 实现不等于查询
bookList = BookInfo.objects.exclude(id=1)
count,distinct,取数量,去重
order_by排序,加负数就是倒排
python
# 使用count()方法,返回满足查询条件后的数据量
t = BookInfo.objects.filter(id=2).count()
print(t)
# distinct()方法,返回去重后的数据
bookList = BookInfo.objects.values('bookName').distinct()
# 使用order_by设置排序
# bookList = BookInfo.objects.order_by("price")
bookList = BookInfo.objects.order_by("-id")
聚合查询,数值求和,求平均值等
python
# annotate类似于SQL里面的GROUP BY方法
# 如果不设置values,默认对主键进行GROUIP BY分组
# SQL: select bookType_id,SUM(price) AS 'price_sum' from t_book GROUP BY
bookType_id
r = BookInfo.objects.values('bookType').annotate(Sum('price'))
# SQL: select bookType_id,AVG(price) AS 'price_sum' from t_book GROUP BY
bookType_id
r2 = BookInfo.objects.values('bookType').annotate(Avg('price'))
分页查询
python
bookList = BookInfo.objects.all()
# Paginator(object_list ,per_page)
# object_list 结果集/列表
# per_page 每页多少条记录
p = Paginator(bookList, 2)
# 获取第几页的数据
bookListPage = p.page(2)
print("总记录数:", BookInfo.objects.count())
高级查询
用大于、不等于或模糊查询的匹配方法

python
# 模糊查询图书名称含有"编程"的所有数据
# bookList = BookInfo.objects.filter(bookName__contains='编程')
# 查询图书价格大于等于50的所有数据
bookList = BookInfo.objects.filter(price__gte=50)
多表查询
多表查询需要在数据表之间建立表关系才能够实现。一对多或一对一的表关系是通过外键实现关联的,而多表查询分为正向查询和反向查询。
以模型BookInfo和BokkTypeInfo为例,如果查询主题是BookInfo,通过外键bookType_id去查询BooKTypeInfo的关联数据,那么该查询称为正向查询;如果查询对象的主题是模型BookTypeInfo,要查询它与模型BookInfo的关联数据,那么该查询称为反向查询
python
def bookList2(request):
"""
多表查询 正常查询 和反向查询
:param request:
:return:
"""
# 正向查询
book: BookInfo = BookInfo.objects.filter(id=2).first()
print(book.bookType.bookTypeName)
# 反向查询
bookType = BookTypeInfo.objects.filter(id=1).first()
print(bookType.bookinfo_set.first().bookName)
print(bookType.bookinfo_set.all())
content_value = {"title": "图书列表"}
return render(request, 'book/list.html')
直接通过BookInfo.objects.会自动正向查询。
使用表名小写_set可以反向查询获取。
数据操作
python
def add(request):
"""
图书添加
:param request:
:return:
"""
# print(request.POST.get("bookName"))
# print(request.POST.get("publishDate"))
# print(request.POST.get("bookType_id"))
# print(request.POST.get("price"))
book = BookInfo()
book.bookName = request.POST.get("bookName")
book.publishDate = request.POST.get("publishDate")
book.bookType_id = request.POST.get("bookType_id")
book.price = request.POST.get("price")
book.save()
# 数据添加后,获取新增数据的主键id
print(book.id)
return bookList(request)
跟nest差不多,创建一个实例,然后传入数据,save一下。
update更简单,直接book.id = 1,再save一下,就可以修改di为1的数据了,
删除则是delete方法
python
# 删除所有数据
BookInfo.objects.all().delete()
# 删除指定id数据
BookInfo.objects.get(id=1).delete()
# 根据条件删除多条数据
BookInfo.objects.filter(price__gte=90).delete()
执行sql语句

ORM数据库事务
事务应该具有4个属性:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation),持久性
(Durability),这4个属性通常称为ACID特性
模拟转账
python
def transfer2(request):
"""
模拟转账
:param request:
:return:
"""
a1 = AccountInfo.objects.filter(user='张三')
a1.update(account=F('account') + 100)
a2 = AccountInfo.objects.filter(user='李四')
a2.update(account=F('account') - 100)
return HttpResponse("OK")
Django5主要有4个事务方法:
atomic():在视图函数或视图类里使用事务。
savepoint():开启事务。
savepoint_rollback():回滚事务。
savepoint_commit():提交事务。
python
@transaction.atomic
def transfer(request):
"""
模拟转账
:param request:
:return:
"""
# 开启事务
sid = transaction.savepoint()
try:
a1 = AccountInfo.objects.filter(user='张三')
a1.update(account=F('account') + 100)
a2 = AccountInfo.objects.filter(user='李四')
a2.update(account=F('account') - 100 / 0)
# 提交事务 (如不设置,当程序执行完成后,会自动提交事务)
transaction.savepoint_commit(sid)
except Exception as e:
print("异常信息:", e)
# 事务回滚
transaction.savepoint_rollback(sid)
return HttpResponse("OK")
使用装饰器@transcation.atomic,然后transaction.savepoint()开启事务,如果程序执行挖成,transaction.savepoint_commit(sid)提交事务,表示完成,如果失败了,就要回滚transaction.savepoint_rollback(sid)