Python Web 框架 Django 核心功能与实战
Django Web 框架的核心功能与实战应用。涵盖安装、项目结构、模型 ORM、视图、模板、表单、路由及认证权限管理。通过产品管理系统案例,演示了增删改查、分类管理与搜索功能实现。帮助开发者理解 MVC 架构,快速构建安全可扩展的 Web 应用。

Django Web 框架的核心功能与实战应用。涵盖安装、项目结构、模型 ORM、视图、模板、表单、路由及认证权限管理。通过产品管理系统案例,演示了增删改查、分类管理与搜索功能实现。帮助开发者理解 MVC 架构,快速构建安全可扩展的 Web 应用。

学习目标:掌握 Django 框架的核心功能,包括模型、视图、模板、表单、认证、权限管理等;理解 Django 的 MVC 架构;通过实战案例开发一个完整的 Web 应用。
学习重点:Django 项目结构、模型定义、视图函数、模板渲染、表单处理、用户认证、权限管理、数据库操作。
Django 是一个开源的 Python Web 框架,遵循 MVT(Model-View-Template)架构,提供了完整的 Web 开发解决方案,包括数据库操作、表单处理、用户认证、权限管理等。
pip install django
django-admin startproject myproject
cd myproject
python manage.py startapp myapp
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
# 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
python manage.py makemigrations
python manage.py migrate
# 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})
# myapp/forms.py
from django import forms
from myapp.models import Product
class ProductForm(forms.ModelForm):
class Meta:
model = Product
fields = ['name', 'price', 'description']
<!-- 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/[email protected]/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/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
<!-- 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 %}
<!-- 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 %}
<!-- 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 %}
<!-- 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 %}
# 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'),
]
# myproject/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('myapp.urls')),
]
# 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',
]
python manage.py createsuperuser
# 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']
# myproject/settings.py
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static'),
]
<!-- 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>
开发一个产品管理系统,支持以下功能:
# 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
# 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']
# 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})
# 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'),
]
<!-- 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 %}
<!-- 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 %}
<!-- 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 %}
<!-- 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 %}
<!-- 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 %}
通过产品管理系统,我们可以实现以下功能:

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML 转 Markdown 互为补充。 在线工具,Markdown 转 HTML在线工具,online
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML 转 Markdown在线工具,online
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online