Django 框架入门教程 — Python全功能Web框架

前置要求: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             # 测试指定应用


学习建议

  1. 先理解Django的MTV架构:Model-Template-View
  2. 掌握ORM操作,这是日常开发的核心
  3. 学会用Admin后台,快速验证数据
  4. 学习DRF,做REST API的标配
  5. 做一个完整项目,如博客或电商后台

下一步学习

返回首页