一、学习目标与重点
💡 学习目标 :掌握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 实施过程
- 创建Django项目和应用。
- 定义模型、表单、视图函数。
- 配置路由和模板。
- 迁移数据库。
- 创建超级用户。
- 运行开发服务器。
17.10.4 最终效果
通过产品管理系统,我们可以实现以下功能:
- 产品的添加、删除、修改、查询。
- 用户的注册、登录、退出。
- 产品的分类管理。
- 产品的搜索功能。
总结
✅ 本文详细介绍了Django框架的核心功能,包括模型、视图、模板、表单、用户认证、权限管理等;通过实战案例开发了一个完整的产品管理系统。