前置要求:Python基础、HTTP基础
学习时长:约3-5天(每天4小时)
Django版本:5.0+
适用场景:内容管理系统、企业应用、API后端
一、Django 是什么?
Django 是 Python 生态中最全功能的 Web 框架,"自带电池"(Batteries Included),提供了ORM、Admin后台、认证系统等开箱即用的功能。
| 特点 | 说明 |
|---|---|
| 核心理念 | 快速开发、DRY原则、安全优先 |
| 学习曲线 | ★★★☆☆(功能多,概念多) |
| 核心优势 | 自带Admin后台、ORM强大、安全机制完善 |
| 适用场景 | CMS、企业应用、内容型网站 |
| 代表项目 | Instagram、Pinterest、Disqus |
二、快速开始
2.1 安装
# 创建虚拟环境
python3 -m venv venv
source venv/bin/activate # Linux/macOS
# venv\Scripts\activate # Windows
# 安装Django
pip install django
# 创建项目
django-admin startproject myproject
cd myproject
# 创建应用
python manage.py startapp myapp
# 运行开发服务器
python manage.py runserver
# 访问 http://localhost:8000
2.2 项目结构
myproject/
├── manage.py # 管理命令
├── myproject/ # 项目配置
│ ├── __init__.py
│ ├── settings.py # 配置文件
│ ├── urls.py # URL配置
│ ├── wsgi.py # WSGI入口
│ └── asgi.py # ASGI入口
├── myapp/ # 应用
│ ├── __init__.py
│ ├── admin.py # Admin配置
│ ├── apps.py # 应用配置
│ ├── models.py # 数据模型
│ ├── views.py # 视图函数
│ ├── urls.py # 应用URL
│ ├── serializers.py # 序列化器(DRF)
│ ├── tests.py # 测试
│ └── migrations/ # 数据库迁移
└── templates/ # 模板文件
2.3 配置文件
# myproject/settings.py
# 数据库配置
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'mydb',
'USER': 'root',
'PASSWORD': 'your_password',
'HOST': 'localhost',
'PORT': '3306',
'OPTIONS': {
'charset': 'utf8mb4',
},
}
}
# 安装应用
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework', # DRF
'corsheaders', # 跨域
'myapp', # 自定义应用
]
# 中间件
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware', # 跨域(放最前面)
'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',
]
# 跨域配置
CORS_ALLOW_ALL_ORIGINS = True # 开发环境
# 国际化
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
# 静态文件
STATIC_URL = '/static/'
STATIC_ROOT = BASE_DIR / 'staticfiles'
# 媒体文件
MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR / 'media'
三、模型(Models)
# myapp/models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
# 自定义用户模型
class User(AbstractUser):
phone = models.CharField('手机号', max_length=20, blank=True)
avatar = models.ImageField('头像', upload_to='avatars/', blank=True)
bio = models.TextField('简介', blank=True)
created_at = models.DateTimeField('创建时间', auto_now_add=True)
updated_at = models.DateTimeField('更新时间', auto_now=True)
class Meta:
db_table = 'users'
verbose_name = '用户'
verbose_name_plural = verbose_name
ordering = ['-created_at']
def __str__(self):
return self.username
# 文章模型
class Post(models.Model):
STATUS_CHOICES = [
('draft', '草稿'),
('published', '已发布'),
('archived', '已归档'),
]
title = models.CharField('标题', max_length=200)
slug = models.SlugField('URL别名', unique=True)
content = models.TextField('内容')
status = models.CharField('状态', max_length=20, choices=STATUS_CHOICES, default='draft')
author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='posts', verbose_name='作者')
tags = models.ManyToManyField('Tag', blank=True, related_name='posts', verbose_name='标签')
views = models.PositiveIntegerField('浏览量', default=0)
published_at = models.DateTimeField('发布时间', null=True, blank=True)
created_at = models.DateTimeField('创建时间', auto_now_add=True)
updated_at = models.DateTimeField('更新时间', auto_now=True)
class Meta:
db_table = 'posts'
verbose_name = '文章'
verbose_name_plural = verbose_name
ordering = ['-created_at']
def __str__(self):
return self.title
# 标签模型
class Tag(models.Model):
name = models.CharField('标签名', max_length=50, unique=True)
slug = models.SlugField('URL别名', unique=True)
class Meta:
db_table = 'tags'
verbose_name = '标签'
def __str__(self):
return self.name
# 数据库迁移
python manage.py makemigrations
python manage.py migrate
四、视图(Views)
4.1 函数视图
# myapp/views.py
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_http_methods
from .models import User
import json
# GET /api/users
@require_http_methods(["GET"])
def user_list(request):
keyword = request.GET.get('keyword', '')
page = int(request.GET.get('page', 1))
size = int(request.GET.get('size', 10))
users = User.objects.all()
if keyword:
users = users.filter(username__icontains=keyword) | users.filter(email__icontains=keyword)
# 分页
start = (page - 1) * size
end = start + size
total = users.count()
data = [
{
'id': u.id,
'username': u.username,
'email': u.email,
'created_at': u.created_at.isoformat(),
}
for u in users[start:end]
]
return JsonResponse({
'code': 200,
'data': {
'items': data,
'total': total,
'page': page,
'size': size,
}
})
# POST /api/users
@csrf_exempt
@require_http_methods(["POST"])
def user_create(request):
try:
data = json.loads(request.body)
except json.JSONDecodeError:
return JsonResponse({'code': 400, 'message': '无效的JSON'}, status=400)
# 验证
if not data.get('username'):
return JsonResponse({'code': 422, 'message': '用户名不能为空'}, status=422)
if User.objects.filter(username=data['username']).exists():
return JsonResponse({'code': 409, 'message': '用户名已存在'}, status=409)
user = User.objects.create_user(
username=data['username'],
email=data.get('email', ''),
password=data['password'],
)
return JsonResponse({
'code': 201,
'message': '创建成功',
'data': {'id': user.id, 'username': user.username},
}, status=201)
4.2 类视图
# myapp/views.py
from django.views import View
from django.http import JsonResponse
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt
from .models import User
import json
@method_decorator(csrf_exempt, name='dispatch')
class UserView(View):
def get(self, request, user_id=None):
if user_id:
try:
user = User.objects.get(id=user_id)
return JsonResponse({
'code': 200,
'data': {
'id': user.id,
'username': user.username,
'email': user.email,
}
})
except User.DoesNotExist:
return JsonResponse({'code': 404, 'message': '用户不存在'}, status=404)
else:
users = User.objects.all()[:10]
data = [{'id': u.id, 'username': u.username} for u in users]
return JsonResponse({'code': 200, 'data': data})
def post(self, request):
data = json.loads(request.body)
user = User.objects.create_user(
username=data['username'],
password=data['password'],
)
return JsonResponse({'code': 201, 'data': {'id': user.id}}, status=201)
def put(self, request, user_id):
user = User.objects.get(id=user_id)
data = json.loads(request.body)
user.username = data.get('username', user.username)
user.save()
return JsonResponse({'code': 200, 'data': {'id': user.id}})
def delete(self, request, user_id):
User.objects.filter(id=user_id).delete()
return JsonResponse({'code': 200, 'message': '删除成功'})
五、URL配置
# myproject/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('myapp.urls')),
]
# myapp/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('users/', views.user_list, name='user-list'),
path('users/<int:user_id>/', views.user_detail, name='user-detail'),
]
六、Django REST Framework(DRF)
pip install djangorestframework
# myapp/serializers.py
from rest_framework import serializers
from .models import User, Post
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['id', 'username', 'email', 'created_at']
read_only_fields = ['id', 'created_at']
class PostSerializer(serializers.ModelSerializer):
author = UserSerializer(read_only=True)
class Meta:
model = Post
fields = ['id', 'title', 'content', 'status', 'author', 'created_at']
# myapp/views.py
from rest_framework import viewsets, permissions, status
from rest_framework.decorators import action
from rest_framework.response import Response
from .models import User, Post
from .serializers import UserSerializer, PostSerializer
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
@action(detail=False, methods=['get'])
def me(self, request):
serializer = self.get_serializer(request.user)
return Response(serializer.data)
class PostViewSet(viewsets.ModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
def get_queryset(self):
queryset = super().get_queryset()
keyword = self.request.query_params.get('keyword')
if keyword:
queryset = queryset.filter(title__icontains=keyword)
return queryset
def perform_create(self, serializer):
serializer.save(author=self.request.user)
# myapp/urls.py
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from . import views
router = DefaultRouter()
router.register('users', views.UserViewSet)
router.register('posts', views.PostViewSet)
urlpatterns = [
path('', include(router.urls)),
]
七、Admin 后台
# myapp/admin.py
from django.contrib import admin
from .models import User, Post, Tag
@admin.register(User)
class UserAdmin(admin.ModelAdmin):
list_display = ['id', 'username', 'email', 'is_active', 'created_at']
list_filter = ['is_active', 'created_at']
search_fields = ['username', 'email']
list_per_page = 20
@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
list_display = ['id', 'title', 'author', 'status', 'views', 'created_at']
list_filter = ['status', 'created_at']
search_fields = ['title', 'content']
raw_id_fields = ['author']
list_per_page = 20
@admin.register(Tag)
class TagAdmin(admin.ModelAdmin):
list_display = ['id', 'name', 'slug']
# 创建管理员
python manage.py createsuperuser
# 访问 http://localhost:8000/admin/
八、Django 命令速查
# 项目管理
python manage.py runserver # 启动开发服务器
python manage.py createsuperuser # 创建管理员
python manage.py shell # 进入Python Shell
# 数据库
python manage.py makemigrations # 创建迁移文件
python manage.py migrate # 执行迁移
python manage.py showmigrations # 查看迁移状态
# 静态文件
python manage.py collectstatic # 收集静态文件
# 测试
python manage.py test # 运行测试
python manage.py test myapp # 测试指定应用
学习建议
- 先理解Django的MTV架构:Model-Template-View
- 掌握ORM操作,这是日常开发的核心
- 学会用Admin后台,快速验证数据
- 学习DRF,做REST API的标配
- 做一个完整项目,如博客或电商后台