第一个Django项目
本章将带你创建第一个Django项目,了解Django项目的基本结构,并运行你的第一个Web应用程序。
创建Django项目
使用django-admin创建项目
bash
# 确保虚拟环境已激活
(venv) $ django-admin startproject mysite
# 查看创建的项目结构
cd mysite
tree . # Linux/macOS
# 或
dir /s # Windows项目结构解析
mysite/
├── manage.py # Django项目管理脚本
└── mysite/ # 项目配置包
├── __init__.py # Python包标识文件
├── settings.py # 项目设置文件
├── urls.py # URL配置文件
├── asgi.py # ASGI配置文件
└── wsgi.py # WSGI配置文件manage.py详解
python
#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import os
import sys
def main():
"""Run administrative tasks."""
# 设置Django设置模块
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings')
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv)
if __name__ == '__main__':
main()manage.py的主要用途:
- 运行开发服务器
- 创建应用程序
- 执行数据库迁移
- 创建超级用户
- 收集静态文件
settings.py详解
python
# mysite/settings.py
"""
Django settings for mysite project.
Generated by 'django-admin startproject' using Django 4.2.7.
"""
from pathlib import Path
# 项目根目录
BASE_DIR = Path(__file__).resolve().parent.parent
# 安全密钥 - 生产环境中应该保密
SECRET_KEY = 'django-insecure-your-secret-key-here'
# 调试模式 - 生产环境中应该设为False
DEBUG = True
# 允许的主机列表
ALLOWED_HOSTS = []
# 应用程序定义
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',
]
# URL配置
ROOT_URLCONF = 'mysite.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应用程序
WSGI_APPLICATION = 'mysite.wsgi.application'
# 数据库配置
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
# 密码验证
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',
},
]
# 国际化
LANGUAGE_CODE = 'zh-hans' # 中文
TIME_ZONE = 'Asia/Shanghai' # 中国时区
USE_I18N = True
USE_TZ = True
# 静态文件 (CSS, JavaScript, Images)
STATIC_URL = 'static/'
# 默认主键字段类型
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'urls.py详解
python
# mysite/urls.py
"""mysite URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/4.2/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path
urlpatterns = [
path('admin/', admin.site.urls),
]运行开发服务器
启动服务器
bash
# 在项目根目录(包含manage.py的目录)
python manage.py runserver
# 输出信息
Watching for file changes with StatReloader
Performing system checks...
System check identified no issues (0 silenced).
You have 18 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.
December 15, 2023 - 10:30:00
Django version 4.2.7, using settings 'mysite.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.访问网站
打开浏览器访问 http://127.0.0.1:8000/,你应该看到Django的欢迎页面:
html
<!-- Django欢迎页面显示内容 -->
The install worked successfully! Congratulations!
You are seeing this message because this Django installation is working correctly.
Next, start your first app by running python manage.py startapp [app_label].自定义服务器配置
bash
# 指定端口
python manage.py runserver 8080
# 指定IP和端口
python manage.py runserver 0.0.0.0:8000
# 使用不同的设置文件
python manage.py runserver --settings=mysite.settings_dev数据库初始化
执行初始迁移
bash
# 应用数据库迁移
python manage.py migrate
# 输出信息
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying admin.0003_logentry_add_action_flag_choices... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying auth.0009_alter_user_last_name_max_length... OK
Applying auth.0010_alter_group_name_max_length... OK
Applying auth.0011_update_proxy_permissions... OK
Applying auth.0012_alter_user_first_name_max_length... OK
Applying sessions.0001_initial... OK创建超级用户
bash
# 创建管理员账户
python manage.py createsuperuser
# 按提示输入信息
Username (leave blank to use 'yourname'): admin
Email address: admin@example.com
Password:
Password (again):
Superuser created successfully.访问管理后台
访问 http://127.0.0.1:8000/admin/ 并使用刚创建的超级用户账户登录。
创建第一个应用
Django项目 vs 应用
项目 (Project)
├── 应用1 (App) - 博客功能
├── 应用2 (App) - 用户管理
├── 应用3 (App) - 评论系统
└── 项目配置项目:整个Web站点的容器 应用:实现特定功能的Python包
创建应用
bash
# 创建名为polls的应用
python manage.py startapp polls
# 查看应用结构
tree polls/ # Linux/macOS应用结构解析
polls/
├── __init__.py # Python包标识
├── admin.py # 管理后台配置
├── apps.py # 应用配置
├── migrations/ # 数据库迁移文件
│ └── __init__.py
├── models.py # 数据模型
├── tests.py # 测试文件
└── views.py # 视图函数应用文件详解
apps.py - 应用配置
python
# polls/apps.py
from django.apps import AppConfig
class PollsConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'polls'
verbose_name = '投票应用' # 在管理后台显示的名称models.py - 数据模型
python
# polls/models.py
from django.db import models
# Create your models here.views.py - 视图函数
python
# polls/views.py
from django.shortcuts import render
# Create your views here.admin.py - 管理后台
python
# polls/admin.py
from django.contrib import admin
# Register your models here.编写第一个视图
创建视图函数
python
# polls/views.py
from django.http import HttpResponse
def index(request):
return HttpResponse("Hello, world. You're at the polls index.")
def detail(request, question_id):
return HttpResponse(f"You're looking at question {question_id}.")
def results(request, question_id):
response = "You're looking at the results of question %s."
return HttpResponse(response % question_id)
def vote(request, question_id):
return HttpResponse(f"You're voting on question {question_id}.")配置URL路由
1. 创建应用URL配置
python
# polls/urls.py (新建文件)
from django.urls import path
from . import views
urlpatterns = [
# ex: /polls/
path('', views.index, name='index'),
# ex: /polls/5/
path('<int:question_id>/', views.detail, name='detail'),
# ex: /polls/5/results/
path('<int:question_id>/results/', views.results, name='results'),
# ex: /polls/5/vote/
path('<int:question_id>/vote/', views.vote, name='vote'),
]2. 在项目URL配置中包含应用URL
python
# mysite/urls.py
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path('polls/', include('polls.urls')),
path('admin/', admin.site.urls),
]注册应用
python
# mysite/settings.py
INSTALLED_APPS = [
'polls.apps.PollsConfig', # 添加polls应用
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]测试视图
bash
# 启动开发服务器
python manage.py runserver
# 访问以下URL测试
http://127.0.0.1:8000/polls/
http://127.0.0.1:8000/polls/34/
http://127.0.0.1:8000/polls/34/results/
http://127.0.0.1:8000/polls/34/vote/URL配置详解
URL模式语法
python
from django.urls import path, re_path
from . import views
urlpatterns = [
# 基本路径
path('', views.index),
# 带参数的路径
path('articles/<int:year>/', views.year_archive),
path('articles/<int:year>/<int:month>/', views.month_archive),
path('articles/<slug:slug>/', views.article_detail),
# 正则表达式路径
re_path(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
# 可选参数
path('blog/', views.blog_index),
path('blog/page/<int:num>/', views.blog_index),
]路径转换器
python
# Django内置路径转换器
str # 匹配除了'/'之外的非空字符串
int # 匹配正整数,包含0
slug # 匹配字母、数字、连字符、下划线
uuid # 匹配格式化的UUID
path # 匹配任何非空字符串,包含路径分隔符'/'
# 使用示例
urlpatterns = [
path('articles/<int:year>/', views.year_archive),
path('articles/<str:title>/', views.article_detail),
path('users/<uuid:user_id>/', views.user_profile),
path('files/<path:file_path>/', views.file_download),
]自定义路径转换器
python
# converters.py
class FourDigitYearConverter:
regex = '[0-9]{4}'
def to_python(self, value):
return int(value)
def to_url(self, value):
return '%04d' % value
# urls.py
from django.urls import path, register_converter
from . import views, converters
register_converter(converters.FourDigitYearConverter, 'yyyy')
urlpatterns = [
path('articles/<yyyy:year>/', views.year_archive),
]URL命名和反向解析
python
# urls.py
from django.urls import path
from . import views
app_name = 'polls' # 应用命名空间
urlpatterns = [
path('', views.IndexView.as_view(), name='index'),
path('<int:pk>/', views.DetailView.as_view(), name='detail'),
path('<int:pk>/results/', views.ResultsView.as_view(), name='results'),
path('<int:question_id>/vote/', views.vote, name='vote'),
]python
# 在视图中使用
from django.urls import reverse
from django.http import HttpResponseRedirect
def vote(request, question_id):
# ... 投票逻辑 ...
return HttpResponseRedirect(reverse('polls:results', args=(question_id,)))html
<!-- 在模板中使用 -->
<a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a>项目配置优化
环境变量配置
python
# settings.py
import os
from pathlib import Path
# 从环境变量读取配置
DEBUG = os.environ.get('DEBUG', 'False').lower() == 'true'
SECRET_KEY = os.environ.get('SECRET_KEY', 'your-default-secret-key')
ALLOWED_HOSTS = os.environ.get('ALLOWED_HOSTS', 'localhost,127.0.0.1').split(',')
# 数据库配置
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
# 如果设置了DATABASE_URL环境变量,使用它
DATABASE_URL = os.environ.get('DATABASE_URL')
if DATABASE_URL:
import dj_database_url
DATABASES['default'] = dj_database_url.parse(DATABASE_URL)分离配置文件
mysite/
├── settings/
│ ├── __init__.py
│ ├── base.py # 基础配置
│ ├── development.py # 开发环境配置
│ ├── production.py # 生产环境配置
│ └── testing.py # 测试环境配置python
# settings/base.py
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent.parent.parent
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'polls.apps.PollsConfig',
]
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 = 'mysite.urls'
WSGI_APPLICATION = 'mysite.wsgi.application'
# ... 其他通用配置python
# settings/development.py
from .base import *
DEBUG = True
ALLOWED_HOSTS = ['localhost', '127.0.0.1']
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
# 开发工具
INSTALLED_APPS += [
'debug_toolbar',
'django_extensions',
]
MIDDLEWARE += [
'debug_toolbar.middleware.DebugToolbarMiddleware',
]
INTERNAL_IPS = ['127.0.0.1']python
# settings/production.py
from .base import *
import os
DEBUG = False
ALLOWED_HOSTS = os.environ.get('ALLOWED_HOSTS', '').split(',')
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.environ.get('DB_NAME'),
'USER': os.environ.get('DB_USER'),
'PASSWORD': os.environ.get('DB_PASSWORD'),
'HOST': os.environ.get('DB_HOST', 'localhost'),
'PORT': os.environ.get('DB_PORT', '5432'),
}
}
# 安全配置
SECURE_BROWSER_XSS_FILTER = True
SECURE_CONTENT_TYPE_NOSNIFF = True
X_FRAME_OPTIONS = 'DENY'使用不同配置
bash
# 开发环境
python manage.py runserver --settings=mysite.settings.development
# 生产环境
python manage.py migrate --settings=mysite.settings.production
# 或设置环境变量
export DJANGO_SETTINGS_MODULE=mysite.settings.development
python manage.py runserver常用管理命令
项目管理命令
bash
# 创建项目
django-admin startproject mysite
# 创建应用
python manage.py startapp myapp
# 运行开发服务器
python manage.py runserver
python manage.py runserver 8080
python manage.py runserver 0.0.0.0:8000
# 检查项目
python manage.py check
python manage.py check --deploy # 部署检查数据库管理命令
bash
# 创建迁移文件
python manage.py makemigrations
python manage.py makemigrations myapp
# 应用迁移
python manage.py migrate
python manage.py migrate myapp
# 查看迁移状态
python manage.py showmigrations
# 查看SQL语句
python manage.py sqlmigrate myapp 0001用户管理命令
bash
# 创建超级用户
python manage.py createsuperuser
# 修改用户密码
python manage.py changepassword username其他有用命令
bash
# 收集静态文件
python manage.py collectstatic
# 清理会话
python manage.py clearsessions
# 进入Django shell
python manage.py shell
# 运行测试
python manage.py test
python manage.py test myapp
# 生成密钥
python manage.py shell -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())"项目部署准备
生产环境检查清单
python
# 安全检查
python manage.py check --deploy
# 常见检查项目
SECURITY_WARNING = [
'DEBUG = False',
'SECRET_KEY 不能暴露',
'ALLOWED_HOSTS 必须设置',
'HTTPS 配置',
'CSRF 保护',
'XSS 保护',
]requirements.txt
bash
# 生成依赖文件
pip freeze > requirements.txt
# requirements.txt 内容示例
Django==4.2.7
psycopg2-binary==2.9.7
gunicorn==21.2.0
whitenoise==6.6.0
python-decouple==3.8静态文件配置
python
# settings.py
STATIC_URL = '/static/'
STATIC_ROOT = BASE_DIR / 'staticfiles'
STATICFILES_DIRS = [
BASE_DIR / 'static',
]
# 使用WhiteNoise处理静态文件
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware', # 添加这行
# ... 其他中间件
]
# 静态文件压缩
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'本章小结
本章详细介绍了如何创建第一个Django项目:
关键要点:
- 项目创建:使用django-admin startproject创建项目
- 项目结构:理解Django项目的文件组织
- 应用创建:使用manage.py startapp创建应用
- URL配置:设置URL路由和视图映射
- 开发服务器:运行和测试Django应用
重要概念:
- 项目 vs 应用:项目是容器,应用是功能模块
- MVT架构:Model-View-Template设计模式
- URL路由:将URL映射到视图函数
- 配置管理:使用settings.py管理项目配置
最佳实践:
- 为每个功能创建独立的应用
- 使用有意义的URL模式和命名
- 分离不同环境的配置文件
- 使用环境变量管理敏感信息
- 遵循Django的项目结构约定
开发流程:
- 创建项目和应用
- 配置URL路由
- 编写视图函数
- 测试功能
- 优化配置
在下一章中,我们将深入学习Django的基础概念,包括设置、中间件、应用配置等核心知识。