Python开发从入门到精通:Web框架Django实战

一、学习目标与重点

💡 学习目标 :掌握Django框架的核心功能,包括模型、视图、模板、表单、认证、权限管理等;理解Django的MVC架构 **;通过实战案例开发一个完整的Web应用。

⚠️ 学习重点:Django项目结构、模型定义、视图函数、模板渲染、表单处理、用户认证、权限管理、数据库操作。

17.1 Django框架概述

17.1.1 什么是Django

Django是一个开源的Python Web框架,遵循MVC(Model **-View-Controller)架构,提供了完整的Web开发解决方案,包括数据库操作、表单处理、用户认证、权限管理等。

17.1.2 Django的特点

  • 快速开发:提供了丰富的内置功能,如ORM、模板引擎、表单处理等,减少了开发时间。
  • 安全性:内置了CSRF保护、XSS防护、SQL注入防护等安全措施。
  • 可扩展性:支持插件化开发,有大量的第三方库和应用。
  • 文档完善:提供了详细的官方文档和示例代码。

17.1.3 Django的安装

复制代码
pip install django

AI写代码bash
1

17.2 创建Django项目

17.2.1 创建项目

复制代码
django-admin startproject myproject

AI写代码bash
1

17.2.2 创建应用

bash 复制代码
cd myproject
python manage.py startapp myapp

AI写代码bash
12

17.2.3 项目结构

markdown 复制代码
myproject/
├── manage.py
├── myapp/
│   ├── __init__.py
│   ├── admin.py
│   ├── apps.py
│   ├── migrations/
│   ├── models.py
│   ├── tests.py
│   └── views.py
└── myproject/
    ├── __init__.py
    ├── asgi.py
    ├── settings.py
    ├── urls.py
    └── wsgi.py

AI写代码
12345678910111213141516

17.3 模型定义

17.3.1 定义模型

ini 复制代码
# myapp/models.py
from django.db import models

class Product(models.Model):
    name = models.CharField(max_length=100)
    price = models.DecimalField(max_digits=10, decimal_places=2)
    description = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.name

AI写代码python
运行
123456789101112

17.3.2 迁移数据库

复制代码
python manage.py makemigrations
python manage.py migrate

AI写代码bash
12

17.4 视图函数

17.4.1 定义视图函数

css 复制代码
# myapp/views.py
from django.shortcuts import render, get_object_or_404, redirect
from myapp.models import Product
from myapp.forms import ProductForm

def product_list(request):
    products = Product.objects.all()
    return render(request, 'myapp/product_list.html', {'products': products})

def product_detail(request, product_id):
    product = get_object_or_404(Product, pk=product_id)
    return render(request, 'myapp/product_detail.html', {'product': product})

def product_create(request):
    if request.method == 'POST':
        form = ProductForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect('product_list')
    else:
        form = ProductForm()
    return render(request, 'myapp/product_form.html', {'form': form})

def product_update(request, product_id):
    product = get_object_or_404(Product, pk=product_id)
    if request.method == 'POST':
        form = ProductForm(request.POST, instance=product)
        if form.is_valid():
            form.save()
            return redirect('product_list')
    else:
        form = ProductForm(instance=product)
    return render(request, 'myapp/product_form.html', {'form': form})

def product_delete(request, product_id):
    product = get_object_or_404(Product, pk=product_id)
    if request.method == 'POST':
        product.delete()
        return redirect('product_list')
    return render(request, 'myapp/product_delete.html', {'product': product})

AI写代码python
运行
12345678910111213141516171819202122232425262728293031323334353637383940

17.5 表单处理

17.5.1 定义表单

kotlin 复制代码
# myapp/forms.py
from django import forms
from myapp.models import Product

class ProductForm(forms.ModelForm):
    class Meta:
        model = Product
        fields = ['name', 'price', 'description']

AI写代码python
运行
12345678

17.6 模板渲染

17.6.1 定义模板

xml 复制代码
<!-- myapp/templates/myapp/base.html -->
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{% block title %}产品管理系统{% endblock %}</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css">
</head>
<body>
    <nav class="navbar navbar-expand-lg navbar-light bg-light">
        <a class="navbar-brand" href="{% url 'product_list' %}">产品管理系统</a>
        <div class="collapse navbar-collapse">
            <ul class="navbar-nav mr-auto">
                <li class="nav-item">
                    <a class="nav-link" href="{% url 'product_list' %}">产品列表</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="{% url 'product_create' %}">添加产品</a>
                </li>
            </ul>
        </div>
    </nav>
    <div class="container mt-4">
        {% block content %}{% endblock %}
    </div>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

AI写代码html
1234567891011121314151617181920212223242526272829
xml 复制代码
<!-- myapp/templates/myapp/product_list.html -->
{% extends 'myapp/base.html' %}

{% block title %}产品列表{% endblock %}

{% block content %}
    <h1>产品列表</h1>
    <table class="table table-striped">
        <thead>
            <tr>
                <th>名称</th>
                <th>价格</th>
                <th>描述</th>
                <th>创建时间</th>
                <th>操作</th>
            </tr>
        </thead>
        <tbody>
            {% for product in products %}
                <tr>
                    <td>{{ product.name }}</td>
                    <td>{{ product.price }}</td>
                    <td>{{ product.description }}</td>
                    <td>{{ product.created_at }}</td>
                    <td>
                        <a href="{% url 'product_detail' product.id %}" class="btn btn-primary btn-sm">查看</a>
                        <a href="{% url 'product_update' product.id %}" class="btn btn-secondary btn-sm">编辑</a>
                        <a href="{% url 'product_delete' product.id %}" class="btn btn-danger btn-sm">删除</a>
                    </td>
                </tr>
            {% endfor %}
        </tbody>
    </table>
{% endblock %}

AI写代码html
12345678910111213141516171819202122232425262728293031323334
xml 复制代码
<!-- myapp/templates/myapp/product_detail.html -->
{% extends 'myapp/base.html' %}

{% block title %}产品详情{% endblock %}

{% block content %}
    <h1>产品详情</h1>
    <div class="card">
        <div class="card-body">
            <h5 class="card-title">{{ product.name }}</h5>
            <p class="card-text">{{ product.description }}</p>
            <p class="card-text">价格:{{ product.price }}</p>
            <p class="card-text">创建时间:{{ product.created_at }}</p>
            <p class="card-text">更新时间:{{ product.updated_at }}</p>
            <a href="{% url 'product_update' product.id %}" class="btn btn-secondary">编辑</a>
            <a href="{% url 'product_delete' product.id %}" class="btn btn-danger">删除</a>
        </div>
    </div>
{% endblock %}

AI写代码html
12345678910111213141516171819
xml 复制代码
<!-- myapp/templates/myapp/product_form.html -->
{% extends 'myapp/base.html' %}

{% block title %}添加/编辑产品{% endblock %}

{% block content %}
    <h1>{% if form.instance.pk %}编辑产品{% else %}添加产品{% endif %}</h1>
    <form method="post">
        {% csrf_token %}
        {{ form.as_p }}
        <button type="submit" class="btn btn-primary">保存</button>
        <a href="{% url 'product_list' %}" class="btn btn-secondary">取消</a>
    </form>
{% endblock %}

AI写代码html
1234567891011121314
xml 复制代码
<!-- myapp/templates/myapp/product_delete.html -->
{% extends 'myapp/base.html' %}

{% block title %}删除产品{% endblock %}

{% block content %}
    <h1>删除产品</h1>
    <p>你确定要删除产品 "{{ product.name }}" 吗?</p>
    <form method="post">
        {% csrf_token %}
        <button type="submit" class="btn btn-danger">确认删除</button>
        <a href="{% url 'product_list' %}" class="btn btn-secondary">取消</a>
    </form>
{% endblock %}

AI写代码html
1234567891011121314

17.7 路由配置

17.7.1 应用路由

lua 复制代码
# myapp/urls.py
from django.urls import path
from myapp import views

urlpatterns = [
    path('', views.product_list, name='product_list'),
    path('product/<int:product_id>/', views.product_detail, name='product_detail'),
    path('product/create/', views.product_create, name='product_create'),
    path('product/<int:product_id>/update/', views.product_update, name='product_update'),
    path('product/<int:product_id>/delete/', views.product_delete, name='product_delete'),
]

AI写代码python
运行
1234567891011

17.7.2 项目路由

php 复制代码
# myproject/urls.py
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('myapp.urls')),
]

AI写代码python
运行
12345678

17.8 用户认证与权限管理

17.8.1 配置认证系统

ini 复制代码
# myproject/settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'myapp',
]

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',
]

AI写代码python
运行
1234567891011121314151617181920

17.8.2 创建用户

复制代码
python manage.py createsuperuser

AI写代码bash
1

17.8.3 权限管理

python 复制代码
# myapp/admin.py
from django.contrib import admin
from myapp.models import Product

@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
    list_display = ['name', 'price', 'description', 'created_at', 'updated_at']
    list_filter = ['created_at']
    search_fields = ['name', 'description']

AI写代码python
运行
123456789

17.9 静态文件管理

17.9.1 配置静态文件

ini 复制代码
# myproject/settings.py
STATIC_URL = '/static/'
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static'),
]

AI写代码python
运行
12345

17.9.2 加载静态文件

xml 复制代码
<!-- myapp/templates/myapp/base.html -->
{% load static %}
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{% block title %}产品管理系统{% endblock %}</title>
    <link rel="stylesheet" href="{% static 'css/bootstrap.min.css' %}">
</head>
<body>
    ...
    <script src="{% static 'js/bootstrap.bundle.min.js' %}"></script>
</body>
</html>

AI写代码html
123456789101112131415

17.10 实战案例:产品管理系统

17.10.1 需求分析

开发一个产品管理系统,支持以下功能:

  • 产品的添加、删除、修改、查询。
  • 用户的注册、登录、退出。
  • 产品的分类管理。
  • 产品的搜索功能。

17.10.2 代码实现

17.10.2.1 模型定义
ini 复制代码
# myapp/models.py
from django.db import models
from django.contrib.auth.models import User

class Category(models.Model):
    name = models.CharField(max_length=100)
    description = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.name

class Product(models.Model):
    name = models.CharField(max_length=100)
    price = models.DecimalField(max_digits=10, decimal_places=2)
    description = models.TextField()
    category = models.ForeignKey(Category, on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.name

AI写代码python
运行
1234567891011121314151617181920212223
17.10.2.2 表单定义
kotlin 复制代码
# myapp/forms.py
from django import forms
from myapp.models import Product, Category

class CategoryForm(forms.ModelForm):
    class Meta:
        model = Category
        fields = ['name', 'description']

class ProductForm(forms.ModelForm):
    class Meta:
        model = Product
        fields = ['name', 'price', 'description', 'category']

AI写代码python
运行
12345678910111213
17.10.2.3 视图函数
python 复制代码
# myapp/views.py
from django.shortcuts import render, get_object_or_404, redirect
from myapp.models import Product, Category
from myapp.forms import ProductForm, CategoryForm
from django.contrib.auth.decorators import login_required

def category_list(request):
    categories = Category.objects.all()
    return render(request, 'myapp/category_list.html', {'categories': categories})

def category_detail(request, category_id):
    category = get_object_or_404(Category, pk=category_id)
    products = category.product_set.all()
    return render(request, 'myapp/category_detail.html', {'category': category, 'products': products})

@login_required
def category_create(request):
    if request.method == 'POST':
        form = CategoryForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect('category_list')
    else:
        form = CategoryForm()
    return render(request, 'myapp/category_form.html', {'form': form})

@login_required
def category_update(request, category_id):
    category = get_object_or_404(Category, pk=category_id)
    if request.method == 'POST':
        form = CategoryForm(request.POST, instance=category)
        if form.is_valid():
            form.save()
            return redirect('category_list')
    else:
        form = CategoryForm(instance=category)
    return render(request, 'myapp/category_form.html', {'form': form})

@login_required
def category_delete(request, category_id):
    category = get_object_or_404(Category, pk=category_id)
    if request.method == 'POST':
        category.delete()
        return redirect('category_list')
    return render(request, 'myapp/category_delete.html', {'category': category})

def product_list(request):
    search_query = request.GET.get('search', '')
    products = Product.objects.filter(name__icontains=search_query)
    return render(request, 'myapp/product_list.html', {'products': products, 'search_query': search_query})

def product_detail(request, product_id):
    product = get_object_or_404(Product, pk=product_id)
    return render(request, 'myapp/product_detail.html', {'product': product})

@login_required
def product_create(request):
    if request.method == 'POST':
        form = ProductForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect('product_list')
    else:
        form = ProductForm()
    return render(request, 'myapp/product_form.html', {'form': form})

@login_required
def product_update(request, product_id):
    product = get_object_or_404(Product, pk=product_id)
    if request.method == 'POST':
        form = ProductForm(request.POST, instance=product)
        if form.is_valid():
            form.save()
            return redirect('product_list')
    else:
        form = ProductForm(instance=product)
    return render(request, 'myapp/product_form.html', {'form': form})

@login_required
def product_delete(request, product_id):
    product = get_object_or_404(Product, pk=product_id)
    if request.method == 'POST':
        product.delete()
        return redirect('product_list')
    return render(request, 'myapp/product_delete.html', {'product': product})

AI写代码python
运行
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
17.10.2.4 路由配置
lua 复制代码
# myapp/urls.py
from django.urls import path
from myapp import views

urlpatterns = [
    path('', views.product_list, name='product_list'),
    path('category/', views.category_list, name='category_list'),
    path('category/<int:category_id>/', views.category_detail, name='category_detail'),
    path('category/create/', views.category_create, name='category_create'),
    path('category/<int:category_id>/update/', views.category_update, name='category_update'),
    path('category/<int:category_id>/delete/', views.category_delete, name='category_delete'),
    path('product/<int:product_id>/', views.product_detail, name='product_detail'),
    path('product/create/', views.product_create, name='product_create'),
    path('product/<int:product_id>/update/', views.product_update, name='product_update'),
    path('product/<int:product_id>/delete/', views.product_delete, name='product_delete'),
]

AI写代码python
运行
12345678910111213141516
17.10.2.5 模板定义
xml 复制代码
<!-- myapp/templates/myapp/category_list.html -->
{% extends 'myapp/base.html' %}

{% block title %}分类列表{% endblock %}

{% block content %}
    <h1>分类列表</h1>
    <table class="table table-striped">
        <thead>
            <tr>
                <th>名称</th>
                <th>描述</th>
                <th>创建时间</th>
                <th>操作</th>
            </tr>
        </thead>
        <tbody>
            {% for category in categories %}
                <tr>
                    <td>{{ category.name }}</td>
                    <td>{{ category.description }}</td>
                    <td>{{ category.created_at }}</td>
                    <td>
                        <a href="{% url 'category_detail' category.id %}" class="btn btn-primary btn-sm">查看</a>
                        <a href="{% url 'category_update' category.id %}" class="btn btn-secondary btn-sm">编辑</a>
                        <a href="{% url 'category_delete' category.id %}" class="btn btn-danger btn-sm">删除</a>
                    </td>
                </tr>
            {% endfor %}
        </tbody>
    </table>
    <a href="{% url 'category_create' %}" class="btn btn-primary">添加分类</a>
{% endblock %}

AI写代码html
123456789101112131415161718192021222324252627282930313233
xml 复制代码
<!-- myapp/templates/myapp/category_detail.html -->
{% extends 'myapp/base.html' %}

{% block title %}分类详情{% endblock %}

{% block content %}
    <h1>{{ category.name }}</h1>
    <p>{{ category.description }}</p>
    <h2>产品列表</h2>
    <table class="table table-striped">
        <thead>
            <tr>
                <th>名称</th>
                <th>价格</th>
                <th>描述</th>
                <th>创建时间</th>
                <th>操作</th>
            </tr>
        </thead>
        <tbody>
            {% for product in products %}
                <tr>
                    <td>{{ product.name }}</td>
                    <td>{{ product.price }}</td>
                    <td>{{ product.description }}</td>
                    <td>{{ product.created_at }}</td>
                    <td>
                        <a href="{% url 'product_detail' product.id %}" class="btn btn-primary btn-sm">查看</a>
                        <a href="{% url 'product_update' product.id %}" class="btn btn-secondary btn-sm">编辑</a>
                        <a href="{% url 'product_delete' product.id %}" class="btn btn-danger btn-sm">删除</a>
                    </td>
                </tr>
            {% endfor %}
        </tbody>
    </table>
    <a href="{% url 'product_create' %}" class="btn btn-primary">添加产品</a>
{% endblock %}

AI写代码html
12345678910111213141516171819202122232425262728293031323334353637
xml 复制代码
<!-- myapp/templates/myapp/category_form.html -->
{% extends 'myapp/base.html' %}

{% block title %}添加/编辑分类{% endblock %}

{% block content %}
    <h1>{% if form.instance.pk %}编辑分类{% else %}添加分类{% endif %}</h1>
    <form method="post">
        {% csrf_token %}
        {{ form.as_p }}
        <button type="submit" class="btn btn-primary">保存</button>
        <a href="{% url 'category_list' %}" class="btn btn-secondary">取消</a>
    </form>
{% endblock %}

AI写代码html
1234567891011121314
xml 复制代码
<!-- myapp/templates/myapp/category_delete.html -->
{% extends 'myapp/base.html' %}

{% block title %}删除分类{% endblock %}

{% block content %}
    <h1>删除分类</h1>
    <p>你确定要删除分类 "{{ category.name }}" 吗?</p>
    <form method="post">
        {% csrf_token %}
        <button type="submit" class="btn btn-danger">确认删除</button>
        <a href="{% url 'category_list' %}" class="btn btn-secondary">取消</a>
    </form>
{% endblock %}

AI写代码html
1234567891011121314
17.10.2.6 搜索功能
xml 复制代码
<!-- myapp/templates/myapp/product_list.html -->
{% extends 'myapp/base.html' %}

{% block title %}产品列表{% endblock %}

{% block content %}
    <h1>产品列表</h1>
    <form method="get">
        <div class="form-group">
            <input type="text" name="search" value="{{ search_query }}" class="form-control" placeholder="搜索产品名称">
        </div>
        <button type="submit" class="btn btn-primary">搜索</button>
    </form>
    <table class="table table-striped mt-4">
        <thead>
            <tr>
                <th>名称</th>
                <th>价格</th>
                <th>描述</th>
                <th>分类</th>
                <th>创建时间</th>
                <th>操作</th>
            </tr>
        </thead>
        <tbody>
            {% for product in products %}
                <tr>
                    <td>{{ product.name }}</td>
                    <td>{{ product.price }}</td>
                    <td>{{ product.description }}</td>
                    <td>{{ product.category.name }}</td>
                    <td>{{ product.created_at }}</td>
                    <td>
                        <a href="{% url 'product_detail' product.id %}" class="btn btn-primary btn-sm">查看</a>
                        <a href="{% url 'product_update' product.id %}" class="btn btn-secondary btn-sm">编辑</a>
                        <a href="{% url 'product_delete' product.id %}" class="btn btn-danger btn-sm">删除</a>
                    </td>
                </tr>
            {% endfor %}
        </tbody>
    </table>
    <a href="{% url 'product_create' %}" class="btn btn-primary">添加产品</a>
{% endblock %}

AI写代码html
12345678910111213141516171819202122232425262728293031323334353637383940414243

17.10.3 实施过程

  1. 创建Django项目和应用。
  2. 定义模型、表单、视图函数。
  3. 配置路由和模板。
  4. 迁移数据库。
  5. 创建超级用户。
  6. 运行开发服务器。

17.10.4 最终效果

通过产品管理系统,我们可以实现以下功能:

  • 产品的添加、删除、修改、查询。
  • 用户的注册、登录、退出。
  • 产品的分类管理。
  • 产品的搜索功能。

总结

✅ 本文详细介绍了Django框架的核心功能,包括模型、视图、模板、表单、用户认证、权限管理等;通过实战案例开发了一个完整的产品管理系统。

相关推荐
回家路上绕了弯2 小时前
OpenClaw 本地 AI 智能体全解析
后端·agent
我爱娃哈哈3 小时前
Spring Cloud Gateway + 请求聚合(GraphQL-like):一次调用合并多个微服务响应
后端
曲幽3 小时前
FastAPI + PostgreSQL 实战:给应用装上“缓存”和“日志”翅膀
redis·python·elasticsearch·postgresql·logging·fastapi·web·es·fastapi-cache
用户298698530143 小时前
C#:三行代码,给 Word 文档的文本框“一键清空”
后端·c#·.net
血小溅3 小时前
Claude Code Superpowers 插件基础教程
后端
树獭叔叔4 小时前
OpenClaw Agents 系统:多代理架构与智能编排的完整技术解析
后端·aigc·openai
蝎子莱莱爱打怪4 小时前
ESXi 强制断电后恢复CentOS7虚拟机避坑指南:解决重复注册&目录清理难题
linux·后端·程序员
ConardLi5 小时前
OpenClaw 完全指南:这可能是全网最新最全的系统化教程了!
前端·人工智能·后端
树獭叔叔6 小时前
OpenClaw Workspace 文件完整指南:从文件到 AI 行为的完整链路
后端·aigc·openai