Django
Django框架介绍
Django版本和Python版本
https://docs.djangoproject.com/zh-hans/5.1/faq/install/#faq-python-version-supportDjango设计模式 Django遵循MVC思想,但是有自己的一个名词,叫做MVT: Django Model(模型): Django View(视图): Django Template(模板):
快速开始
- 安装Django
pip install django
- 创建项目
django-admin startproject [项目名称]
- 创建APP
python manage.py startapp [APP名称]
- 运行项目
python manage.py runserver
项目文件架构
django_project → 项目根目录
├── manage.py → 项目的管理,启动项目、创建app、数据管理(常使用)
└── django_project → 项目配置目录(与项目同名)
├── __init__.py → 标识为Python包
├── settings.py → 全局配置(常修改)
├── urls.py → 主路由配置(常修改)
├── asgi.py → ASGI服务器配置, 异步接收网络请求
└── wsgi.py → WSGI服务器配置, 同步接收网络请求
APP
在 Django 中,APP(应用) 是一个可重用的功能模块,用于实现特定的业务逻辑。它是 Django 项目的基本组成单元,遵循 "一个APP只做一件事" 的设计原则。
- 独立性: 每个APP是一个独立的Python包,包含完整的功能闭环(模型、视图、模板等)
- 低耦合:APP之间应通过公共接口通信,尽量减少直接依赖
- 可复用:每个APP可以单独摘出来跨项目复用
- 配置分离:敏感配置应放在项目settings中,而非APP内
- 项目
- 业务APP: 用户管理、订单系统等(需自行开发)
- 通用APP: 评论系统、API接口等(可第三方安装)
- 内置APP: admin(后台)、auth(认证)、sessions 等
创建APP
在项目根目录下执行bashpython manage.py startapp blog
会在此项目文件夹下创建新app如下:
markdownblog # APP名称(Python包) ├── migrations/ # 数据库变更记录(自动生成) │ ├── __init__.py │ ├── templates/ # 专属模板目录(html文件) │ └── blog/ # 推荐加APP名前缀避免命名冲突 │ ├── base.html │ ├── post_list.html │ └── post_detail.html │ ├── static/ # 专属静态文件(图片、css、js等文件) │ └── blog/ │ ├── js/ │ ├── plugins/ # 推荐加APP名前缀避免命名冲突 │ ├── css/ │ │ └── style.css │ └── images/ │ └── logo.png │ ├── __init__.py ├── admin.py # django默认提供了admin后台管理 ├── apps.py # APP配置类(自动生成) ├── models.py # 数据模型定义(重要,数据库操作相关) ├── tests.py # 单元测试 ├── urls.py # 子路由配置(需手动创建) └── views.py # 视图逻辑(重要,函数)
注册APP
将新创建的app添加到项目同名目录下的settings.py
文件中的INSTALLED_APPS
列表中,格式为'app_name.apps.App_nameConfig'
。pythonINSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'blog.apps.BlogConfig', # 注册新创建的app ]
静态文件
静态文件一般存放图片、css、js、plugin等内容,在html中引入static文件夹下的文件时,使用{% load static %}
标签加载静态文件。html{% load static %} <link rel="stylesheet" type="text/css" href="{% static 'blog/css/style.css' %}">
URL与视图
主路由与子路由
主路由是指项目文件夹下的urls.py
,子路由是指每个应用(app)目录下的urls.py
。
主路由负责将请求分发到各个子路由,子路由负责将请求分发到具体的视图函数或视图类。
# mysite/mysite/urls.py
from django.urls import path, include
from blog import urls
urlpatterns = [
path('admin/', admin.site.urls),
path('blog/', include('blog.urls')), # 将blog/的请求交给blog/urls.py处理
]
# mysite/blog/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('articles/', views.article_list), # 显示所有文章列表
path('article/<int:id>/', views.article_detail),
]
# mysite/blog/views.py
def article_list(request):
# 示例1:返回HTTP页面
# 注意:django会根据app的注册顺序(项目名/settings.py - INSTALLED_APPS),
# 在每个app的templates文件夹中寻找article_list.html
return render(request, "article_list.html")
def article_detail(request, id)
# 示例2:返回文本内容
return HttpResponse(f"文章ID:{id}")
上面这些代码是如何工作的呢?
- 当用户访问 https://xxxx/blog/article/1/ 时,Django先检查主路由
mysite/urls.py
, 发现blog/
由include('blog.urls')
处理。 - 然后 Django 查找
blog/urls.py
,匹配到article/<int:id>/
,并调用views.article_detail(request, id=1)
。
path 和 re_path 方法
如何通过URL把参数传递给视图View
呢?Django提供了两种设计URL的方法:path
和 re_path
, 它们均支持想视图函数或类传递参数。
- path方法python
# 使用<变量类型:变量名> or <变量名>传递, 例如 <int:id> 或 <username> urlpatterns = [ path('blog/articles/<int:id>/', views.article_detail, name = 'article_detail'), ]
- re_path方法python
# `re_path`方法是采用正则表达式regex匹配 # 采用命名组(?P<变量名>表达式)的方式传递参数 # 使用re_path时不一定总是以$结尾 urlpatterns = [ re_path(r'^blog/articles/(?P<id>\d+)/$', views.article_detail, name='article_detail'), ]
path
和 re_path
支持传递的数据类型只有 str
, int
, slug
, uuid
四种。一般来说 re_path
更强大,但写起来更复杂一些:
# 示例一,PATH
from django.urls import path
from . import views
urlpatterns = [
path('articles/2003/', views.special_case_2003),
path('articles/<int:year>/', views.year_archive),
path('articles/<int:year>/<int:month>/', views.month_archive),
path('articles/<int:year>/<int:month>/<slug:slug>/', views.article_detail),
]
# 示例二:RE_PATH,与上例等同
from django.urls import path, re_path
from . import views
urlpatterns = [
path('articles/2003/', views.special_case_2003),
re_path(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),
re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<slug>[\w-]+)/$', views.article_detail),
]
URL的命名
同样以博客为例,如果你希望设计不同的URL分别对应负责增删改查操作的视图函数或类,你可以按如下设计:
# mysite/blog/urls.py
from django.urls import path, re_path
from . import views
app_name = 'blog' # 命名空间
urlpatterns = [
path('blog/articles/', views.article_list, name = 'article_list'),
path('blog/articles/create/', views.article_create, name = 'article_create'),
path('blog/articles/<int:id>/', views.article_detail, name = 'article_detail'),
path('blog/articles/<int:id>/update/', views.article_update, name = 'article_update'),
path('blog/articles/<int:id>/delete/', views.article_update, name = 'article_delete'),
]
在上述博客示例中,我们给每个URL取了一个名字,比如第一个path()
中的name = article_list
。它可以让你能够在Django的任意处,尤其是Template中直接引用它。假设你需要在某个模版中通过链接指向一篇具体的文章,就可以以下面方式引用:
<!-- 等同于:"blog/articles/article.id"-->
<a herf="% url 'article_detail' article.id %">{{article.title}}</a>
url
是一个模版标签,其作用是对命名的url进行反向解析,动态生成链接。
在View中使用命名URL
Django提供了 reverse()
方法在视图中可以对命名URL进行反向解析,生成动态链接:
from django.urls import reverse
# output blog/articles/id
reverse('blog:article_detail', args=[id])
URL指向基于类的视图(View)
path
和 re_path
都只能指向视图View里的一个函数或方法,而不能直接指向一个基于类的视图(Class-based View)。Django提供了一个额外的as_view()
方法,可以将一个类伪装成方法。这在当你使用Django自带的类视图或自定义类视图时非常重要。
使用方式如下
# blog/urls.py
from django.urls import path, re_path
from . import views
urlpatterns = [
# path('blog/articles/', views.article_list, name = 'article_list'),
path('blog/articles/', views.ArticleList.as_view(), name='article_list'),
]
# blog/views.py
from django.views.generic import ListView
from .views import Article
class ArticleList(ListView):
queryset = Article.objects.filter(date__lte=timezone.now()).order_by('date')[:5]
context_object_name = 'article_list'
template_name = 'blog/article_list.html'
通过URL传递额外的参数
在你配置URL时,还可以通过字典的形式传递额外的参数给视图,且不用把这个参数写在链接里,如下所示:
# blog/urls.py
from django.urls import path, re_path
from . import views
urlpatterns = [
path('', views.ArticleList.as_view(), name='article_list', {'blog_id': 3})
]
<更新中...>