查看: 333|回复: 0

Django新手教程:从创建项目到自动化测试的完整实践

[复制链接]
发表于 1 小时前 | 显示全部楼层 |阅读模式
Django 是 Python 生态中最常用的 Web 框架之一,很多初学者在看完官方文档后仍然不清楚如何把项目跑起来。本文以官方 demo 为主线,从安装、创建项目、编写视图、配置数据库、管理后台,一直到自动化测试,完整演示一个投票应用(polls)的开发过程。

一、安装 Django 并创建项目

建议使用 Python 3.8 及以上版本,安装命令很简单:
  1. pip install django
复制代码

进入工作目录后,用 django-admin 创建项目:
  1. django-admin startproject mysite
复制代码

此时会生成如下结构:
  1. mysite/
  2.     manage.py
  3.     mysite/
  4.         __init__.py
  5.         settings.py
  6.         urls.py
  7.         asgi.py
  8.         wsgi.py
复制代码

其中 manage.py 是项目管理入口,mysite/settings.py 负责全局配置,urls.py 是根路由。

二、启动开发服务器

进入项目目录:
  1. python manage.py runserver
复制代码

浏览器访问 http://127.0.0.1:8000/ 即可看到 Django 的欢迎页。这个开发服务器自带热加载,改完代码保存后会自动重启。

三、创建应用并实现第一个视图

项目和应用是两个概念:一个项目可以包含多个应用。这里创建名为 polls 的应用:
  1. python manage.py startapp polls
复制代码

生成目录中最重要的两个文件是 views.py 和 models.py。

先写一个最简单的视图,编辑 polls/views.py:
  1. from django.http import HttpResponse
  2. def index(request):
  3.     return HttpResponse("Hello, world. You're at the polls index.")
复制代码

光有视图还不够,必须配置路由。在 polls 目录下新建 urls.py:
  1. from django.urls import path
  2. from . import views
  3. urlpatterns = [
  4.     path('', views.index, name='index'),
  5. ]
复制代码

然后在项目根路由 mysite/urls.py 中挂载 poll 应用的路由:
  1. from django.contrib import admin
  2. from django.urls import include, path
  3. urlpatterns = [
  4.     path('polls/', include('polls.urls')),
  5.     path('admin/', admin.site.urls),
  6. ]
复制代码

重启开发服务器后,访问 http://127.0.0.1:8000/polls/ 就能看到刚才返回的字符串。

四、配置数据库并创建模型

Django 默认使用 SQLite,适合开发和学习。在迁移前先执行初始化操作:
  1. python manage.py migrate
复制代码

migrate 会根据已安装的应用创建数据表。接下来定义两个模型:Question(问题)和 Choice(选项)。

编辑 polls/models.py:
  1. from django.db import models
  2. class Question(models.Model):
  3.     question_text = models.CharField(max_length=200)
  4.     pub_date = models.DateTimeField('date published')
  5. class Choice(models.Model):
  6.     question = models.ForeignKey(Question, on_delete=models.CASCADE)
  7.     choice_text = models.CharField(max_length=200)
  8.     votes = models.IntegerField(default=0)
复制代码

Question 包含问题文本和发布日期;Choice 通过外键关联到 Question,并记录选项文本和票数。on_delete=models.CASCADE 表示当问题被删除时,其下的选项也会被级联删除。

要在后台管理该模型,还需要打开 polls/admin.py 注册:
  1. from django.contrib import admin
  2. from .models import Question
  3. admin.site.register(Question)
复制代码

同时在 settings.py 的 INSTALLED_APPS 中加入 'polls.apps.PollsConfig',然后生成并应用迁移:
  1. python manage.py makemigrations polls
  2. python manage.py migrate
复制代码

django-admin 创建应用时在 apps.py 里生成了 PollsConfig 类,所以这样配置即可。

五、使用 Django Shell 调试模型

Django 提供了一个交互式环境,方便验证模型逻辑。启动 shell:
  1. python manage.py shell
复制代码

在 shell 中可以用 Python 语法操作数据库。更重要的是,Django 官方建议把系统的当前时间统一使用 timezone 获取,而不是裸用 datetime.datetime.now()。所以在相关代码中需要导入:
  1. import datetime
  2. from django.utils import timezone
复制代码

这样可以避免时区不一致导致的日期判断错误。

六、创建后台管理账号

Django 自带一个强大的 admin 后台。先创建超级用户:
  1. python manage.py createsuperuser
复制代码

按提示输入用户名、邮箱和密码。然后访问 http://127.0.0.1:8000/admin/ 登录,就可以看到 Question 的管理入口。

七、为视图增加模板

目前 index 视图只是返回字符串。真实环境中,我们通常会使用模板。创建一个模板目录:
  1. polls/templates/polls/index.html
复制代码

Django 的 TEMPLATES 配置默认开启 APP_DIRS=True,因此它会在每个已安装应用的 templates 子目录下查找模板。更新 polls/views.py,让视图读取数据库中最新的 5 条问题:
  1. from django.http import HttpResponse
  2. from .models import Question
  3. def index(request):
  4.     latest_question_list = Question.objects.order_by('-pub_date')[:5]
  5.     output = ', '.join([q.question_text for q in latest_question_list])
  6.     return HttpResponse(output)
复制代码

然后使用 render 简化模板渲染代码,并处理列表为空的情况。

八、从展示逻辑改为通用视图

官方教程建议在业务逻辑成熟后切换到通用视图,可以大幅减少重复代码。需要做三步:调整 URLconf、删除旧的 index/detail 视图、引入基于类的 ListView/DetailView。通用视图默认使用“应用名/模型名_list.html”和“应用名/模型名_detail.html”作为模板,同时通过 context_object_name 指定模板变量名,例如:
  1. class IndexView(generic.ListView):
  2.     template_name = 'polls/index.html'
  3.     context_object_name = 'latest_question_list'
  4.     def get_queryset(self):
  5.         return Question.objects.order_by('-pub_date')[:5]
复制代码

这种写法在大型项目中更容易维护。

九、编写自动化测试

Django 的测试框架基于 unittest,测试文件放在应用的 tests.py 中。

先发现一个 Bug:Question.was_published_recently() 在 pub_date 为未来时间时也会返回 True。我们编写测试来暴露它:
  1. import datetime
  2. from django.test import TestCase
  3. from django.utils import timezone
  4. from .models import Question
  5. class QuestionModelTests(TestCase):
  6.     def test_was_published_recently_with_future_question(self):
  7.         future_question = Question(pub_date=timezone.now() + datetime.timedelta(days=30))
  8.         self.assertIs(future_question.was_published_recently(), False)
复制代码

运行测试:
  1. python manage.py test polls
复制代码

此时测试会失败,因为当前方法的实现不满足未来时间返回 False 的要求。

修复方法很简单:在 was_published_recently() 中增加时间范围判断:
  1. def was_published_recently(self):
  2.     now = timezone.now()
  3.     return now - datetime.timedelta(days=1) <= self.pub_date <= now
复制代码

为了更全面地覆盖边界条件,还应该增加“一天内发布返回 True”和“超过一天返回 False”的测试。

十、视图也要测试

某些用户的浏览器时间设置可能与服务器不同,Django 的测试客户端可以直接模拟请求。例如验证未来发布的问题不出现在索引页:
  1. def test_future_question_not_in_index(self):
  2.     future_question = Question(pub_date=timezone.now() + datetime.timedelta(days=30))
  3.     response = self.client.get('/polls/')
  4.     self.assertNotContains(response, future_question.question_text)
复制代码

这种测试能防止后续重构时回归。

十一、自定义界面和样式

Django 的静态文件查找机制与模板类似。在 polls 应用下创建:
  1. polls/static/polls/style.css
复制代码

在模板中通过 {% load static %} 和 {% static 'polls/style.css' %} 引入。背景图可以放在 polls/static/polls/images/ 目录,然后在 CSS 中指定路径。

十二、自定义后台表单和关联对象

默认后台只显示 Question 本身的字段,无法同时编辑关联的 Choice。可以在 admin.py 中使用 TabularInline:
  1. from django.contrib import admin
  2. from .models import Question, Choice
  3. class ChoiceInline(admin.TabularInline):
  4.     model = Choice
  5.     extra = 3
  6. class QuestionAdmin(admin.ModelAdmin):
  7.     inlines = [ChoiceInline]
  8. admin.site.register(Question, QuestionAdmin)
复制代码

这样管理页面就能同时维护问题和选项,减少反复切换页面的麻烦。

总结

本文从一个空目录开始,完成了 Django 项目的搭建、模型定义、数据库迁移、后台注册、模板渲染、通用视图改造以及自动化测试。其中最值得记住的是:视图尽量只做调度,业务逻辑放在模型层;日期时间必须用 timezone;每个 bug 都应该先写一个失败的测试再修复。这套流程不仅是官方 demo 的重复,也是正式开发的基础范式。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-9-2 11:38 , Processed in 0.023115 second(s), 18 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部