Django web 框架
什么是 Django?
Django 是一个用 Python 写的免费开源的 Web 框架,就像是一个现成的工具箱,帮你快速搭建网站。它遵循"快速开发,清晰实用"的设计理念,让你不用从零开始写所有代码。
为什么选择 Django?
- 快速开发:Django 提供了很多现成的功能,比如用户认证、后台管理、数据库操作等
- 安全可靠:内置了很多安全防护措施,帮你避免常见的 Web 安全问题
- 功能丰富:自带 ORM(数据库操作工具)、模板系统、表单处理等
- 文档完善:官方文档非常详细,社区活跃
安装 Django
首先确保你已经安装了 Python,然后运行以下命令:
pip install django
检查安装是否成功:
python -m django --version
创建第一个 Django 项目
1. 创建项目
django-admin startproject mywebsite
cd mywebsite
这会创建一个名为mywebsite的文件夹,里面包含项目的基本结构。
2. 项目结构说明
mywebsite/
├── manage.py # 项目管理脚本
└── mywebsite/ # 项目配置文件夹
├── __init__.py
├── settings.py # 项目设置
├── urls.py # URL路由配置
└── wsgi.py # Web服务器接口
3. 运行开发服务器
python manage.py runserver
然后在浏览器中访问 http://127.0.0.1:8000/,你会看到 Django 的欢迎页面。
创建应用(App)
Django 项目由多个应用组成,每个应用负责特定的功能。
python manage.py startapp blog
应用结构
blog/
├── __init__.py
├── admin.py # 后台管理配置
├── apps.py # 应用配置
├── models.py # 数据模型
├── tests.py # 测试文件
└── views.py # 视图函数
注册应用
在 mywebsite/settings.py 中的 INSTALLED_APPS 列表里添加你的应用:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'blog', # 添加这一行
]
创建数据模型
数据模型就是定义你的数据在数据库中如何存储。
示例:博客文章模型
在 blog/models.py 中:
from django.db import models
from django.contrib.auth.models import User
class Post(models.Model):
title = models.CharField(max_length=200, verbose_name='标题')
content = models.TextField(verbose_name='内容')
author = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name='作者')
created_date = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
published_date = models.DateTimeField(blank=True, null=True, verbose_name='发布时间')
def __str__(self):
return self.title
class Meta:
verbose_name = '博客文章'
verbose_name_plural = '博客文章'
创建数据库迁移
python manage.py makemigrations
python manage.py migrate
创建视图
视图就是处理用户请求并返回响应的函数。
示例:显示博客文章列表
在 blog/views.py 中:
from django.shortcuts import render
from .models import Post
def post_list(request):
"""显示所有已发布的博客文章"""
posts = Post.objects.filter(published_date__isnull=False).order_by('-published_date')
return render(request, 'blog/post_list.html', {'posts': posts})
def post_detail(request, pk):
"""显示单篇博客文章的详细内容"""
post = Post.objects.get(pk=pk)
return render(request, 'blog/post_detail.html', {'post': post})
配置 URL 路由
项目级 URL 配置
在 mywebsite/urls.py 中:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('blog.urls')), # 包含blog应用的URL
]
应用级 URL 配置
创建 blog/urls.py:
from django.urls import path
from . import views
app_name = 'blog'
urlpatterns = [
path('', views.post_list, name='post_list'),
path('post/<int:pk>/', views.post_detail, name='post_detail'),
]
创建模板
模板就是 HTML 文件,用来显示数据。
创建模板目录
blog/
└── templates/
└── blog/
├── base.html
├── post_list.html
└── post_detail.html
基础模板 (base.html)
<!DOCTYPE html>
<html>
<head>
<title>{% block title %}我的博客{% endblock %}</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 20px;
}
.container {
max-width: 800px;
margin: 0 auto;
}
.post {
border: 1px solid #ddd;
padding: 15px;
margin: 10px 0;
border-radius: 5px;
}
.post h2 {
color: #333;
margin-top: 0;
}
.post-meta {
color: #666;
font-size: 0.9em;
}
</style>
</head>
<body>
<div class="container">
<header>
<h1><a href="{% url 'blog:post_list' %}">我的博客</a></h1>
</header>
<main>{% block content %} {% endblock %}</main>
</div>
</body>
</html>
文章列表模板 (post_list.html)
{% extends 'blog/base.html' %} {% block title %}博客文章列表{% endblock %} {%
block content %}
<h2>最新文章</h2>
{% if posts %} {% for post in posts %}
<article class="post">
<h2>
<a href="{% url 'blog:post_detail' pk=post.pk %}">{{ post.title }}</a>
</h2>
<div class="post-meta">
作者: {{ post.author.username }} | 发布时间: {{
post.published_date|date:"Y-m-d H:i" }}
</div>
<p>{{ post.content|truncatewords:30 }}</p>
</article>
{% endfor %} {% else %}
<p>暂无文章</p>
{% endif %} {% endblock %}
文章详情模板 (post_detail.html)
{% extends 'blog/base.html' %} {% block title %}{{ post.title }}{% endblock %}
{% block content %}
<article class="post">
<h1>{{ post.title }}</h1>
<div class="post-meta">
作者: {{ post.author.username }} | 发布时间: {{
post.published_date|date:"Y-m-d H:i" }}
</div>
<div class="post-content">{{ post.content|linebreaks }}</div>
</article>
<p><a href="{% url 'blog:post_list' %}">← 返回文章列表</a></p>
{% endblock %}
后台管理
Django 自带一个强大的后台管理系统。
创建超级用户
python manage.py createsuperuser
注册模型到后台
在 blog/admin.py 中:
from django.contrib import admin
from .models import Post
@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
list_display = ('title', 'author', 'created_date', 'published_date')
list_filter = ('created_date', 'published_date', 'author')
search_fields = ('title', 'content')
date_hierarchy = 'created_date'
ordering = ('-created_date',)
访问 http://127.0.0.1:8000/admin/ 就可以使用后台管理系统了。
完整案例:简单的博客系统
让我们创建一个完整的博客系统,包括创建、编辑、删除文章的功能。
1. 扩展模型
# blog/models.py
from django.db import models
from django.contrib.auth.models import User
from django.urls import reverse
class Post(models.Model):
title = models.CharField(max_length=200, verbose_name='标题')
content = models.TextField(verbose_name='内容')
author = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name='作者')
created_date = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
published_date = models.DateTimeField(blank=True, null=True, verbose_name='发布时间')
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('blog:post_detail', kwargs={'pk': self.pk})
class Meta:
verbose_name = '博客文章'
verbose_name_plural = '博客文章'
2. 添加更多视图
# blog/views.py
from django.shortcuts import render, get_object_or_404, redirect
from django.contrib.auth.decorators import login_required
from django.utils import timezone
from .models import Post
from .forms import PostForm
def post_list(request):
posts = Post.objects.filter(published_date__isnull=False).order_by('-published_date')
return render(request, 'blog/post_list.html', {'posts': posts})
def post_detail(request, pk):
post = get_object_or_404(Post, pk=pk)
return render(request, 'blog/post_detail.html', {'post': post})
@login_required
def post_new(request):
if request.method == "POST":
form = PostForm(request.POST)
if form.is_valid():
post = form.save(commit=False)
post.author = request.user
post.save()
return redirect('blog:post_detail', pk=post.pk)
else:
form = PostForm()
return render(request, 'blog/post_edit.html', {'form': form})
@login_required
def post_edit(request, pk):
post = get_object_or_404(Post, pk=pk)
if request.method == "POST":
form = PostForm(request.POST, instance=post)
if form.is_valid():
post = form.save(commit=False)
post.author = request.user
post.published_date = timezone.now()
post.save()
return redirect('blog:post_detail', pk=post.pk)
else:
form = PostForm(instance=post)
return render(request, 'blog/post_edit.html', {'form': form})
@login_required
def post_delete(request, pk):
post = get_object_or_404(Post, pk=pk)
post.delete()
return redirect('blog:post_list')
3. 创建表单
创建 blog/forms.py:
from django import forms
from .models import Post
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ('title', 'content',)
widgets = {
'title': forms.TextInput(attrs={'class': 'form-control'}),
'content': forms.Textarea(attrs={'class': 'form-control', 'rows': 10}),
}
4. 更新 URL 配置
# blog/urls.py
from django.urls import path
from . import views
app_name = 'blog'
urlpatterns = [
path('', views.post_list, name='post_list'),
path('post/<int:pk>/', views.post_detail, name='post_detail'),
path('post/new/', views.post_new, name='post_new'),
path('post/<int:pk>/edit/', views.post_edit, name='post_edit'),
path('post/<int:pk>/delete/', views.post_delete, name='post_delete'),
]
5. 创建编辑模板
创建 blog/templates/blog/post_edit.html:
{% extends 'blog/base.html' %} {% block title %} {% if form.instance.pk
%}编辑文章{% else %}新建文章{% endif %} {% endblock %} {% block content %}
<h2>{% if form.instance.pk %}编辑文章{% else %}新建文章{% endif %}</h2>
<form method="POST" class="post-form">
{% csrf_token %} {{ form.as_p }}
<button type="submit" class="btn btn-primary">保存</button>
<a href="{% url 'blog:post_list' %}" class="btn btn-secondary">取消</a>
</form>
{% endblock %}
6. 更新其他模板
更新 post_list.html 添加新建按钮:
{% extends 'blog/base.html' %} {% block title %}博客文章列表{% endblock %} {%
block content %}
<div style="margin-bottom: 20px;">
<a href="{% url 'blog:post_new' %}" class="btn btn-primary">写新文章</a>
</div>
<h2>最新文章</h2>
{% if posts %} {% for post in posts %}
<article class="post">
<h2>
<a href="{% url 'blog:post_detail' pk=post.pk %}">{{ post.title }}</a>
</h2>
<div class="post-meta">
作者: {{ post.author.username }} | 发布时间: {{
post.published_date|date:"Y-m-d H:i" }}
</div>
<p>{{ post.content|truncatewords:30 }}</p>
{% if user == post.author %}
<div class="post-actions">
<a
href="{% url 'blog:post_edit' pk=post.pk %}"
class="btn btn-sm btn-warning"
>编辑</a
>
<a
href="{% url 'blog:post_delete' pk=post.pk %}"
class="btn btn-sm btn-danger"
onclick="return confirm('确定要删除这篇文章吗?')"
>删除</a
>
</div>
{% endif %}
</article>
{% endfor %} {% else %}
<p>暂无文章</p>
{% endif %} {% endblock %}
常用 Django 命令
# 创建项目
django-admin startproject 项目名
# 创建应用
python manage.py startapp 应用名
# 创建数据库迁移
python manage.py makemigrations
# 应用数据库迁移
python manage.py migrate
# 创建超级用户
python manage.py createsuperuser
# 运行开发服务器
python manage.py runserver
# 收集静态文件
python manage.py collectstatic
# 进入Django shell
python manage.py shell
总结
Django 是一个功能强大的 Web 框架,通过这个简单的博客系统案例,你可以看到:
- 模型(Models):定义数据结构
- 视图(Views):处理业务逻辑
- 模板(Templates):展示数据
- URL 配置:路由请求
- 表单(Forms):处理用户输入
- 后台管理:管理数据
Django 的"MTV"架构(Model-Template-View)让代码结构清晰,易于维护。通过这个基础,你可以继续学习更多高级功能,如用户认证、API 开发、缓存、部署等。
