Django 基础 初识

学习视频

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参数也是一样

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)

相关推荐
好家伙VCC3 小时前
# Pytest发散创新:从基础测试到智能断言的实战进阶指南在现代软
java·python·pytest
talen_hx2963 小时前
《零基础入门Spark》学习笔记 Day 04
大数据·笔记·学习·spark
研究点啥好呢3 小时前
3月26日Github热榜推荐 | AI代理工具链专栏
人工智能·驱动开发·python·ai
钝挫力PROGRAMER3 小时前
Linux systemd服务获取不到用户环境变量
linux·运维·python
剑穗挂着新流苏3123 小时前
200_深度学习的地基:PyTorch 数据操作与 Pandas 预处理实战
人工智能·pytorch·python·深度学习
进击的小头3 小时前
第19篇:卡尔曼滤波器与MPC模型预测控制器的结合实战
python·算法
中屹指纹浏览器3 小时前
2026指纹浏览器技术选型与性能优化实践
经验分享·笔记
skywalk81633 小时前
windows10安装python3.14
开发语言·python
wangchilong3 小时前
Flask:后端框架使用
后端·python·flask