本文章项目开源地址:
https://codechina.csdn.net/csdn-django-web/django_kaoshi_demo
提示:需要下载代码的朋友可以去上面的开源项目库中拉代码,想参与一起学习的同学可以一起加入项目组中开发
零基础学Python Web开发在线考试系统-Django框架入门项目系列课程(真正带你上路玩转实战项目开发)——目录
《零基础学Python Web开发在线考试系统-Django框架入门项目第1课-请求和响应(真正带你上路玩转实战项目开发)》
《零基础学Python Web开发在线考试系统-Django框架入门项目第2课-模型和管理站点(真正带你上路玩转实战项目开发)》
《零基础学Python Web开发在线考试系统-Django框架入门项目第3课-视图和模板(真正带你上路玩转实战项目开发)》
《零基础学Python Web开发在线考试系统-Django框架入门项目第4课-表单和通用视图(真正带你上路玩转实战项目开发)》
《零基础学Python Web开发在线考试系统-Django框架入门项目第5课-测试(真正带你上路玩转实战项目开发)》
《零基础学Python Web开发在线考试系统-Django框架入门项目第6课-静态文件(真正带你上路玩转实战项目开发)》
《零基础学Python Web开发在线考试系统-Django框架入门项目第7课-自定义管理站点(真正带你上路玩转实战项目开发)》
提示:大家喜欢的请帮忙一键三连,有问题的朋友可以在评论区留言。
本系列文章的目的:
带你零基础学Python Web开发,并通过真实项目-在线考试系统-来学习如何利用Django框架。
因为知识点比较多,工作量比较大,文章章节就7课时,所以最终实现的功能不多,先实现单选题的功能,
但整个项目下来,会让你真正的上手开发,后期你可以自己按照本系列文章继续添加其他功能。
废话咱就不多说了,下面开始吧,如果中途有问题请在评论区留言或私信联系。
楼梯在此:https://huidaoli.blog.csdn.net/article/details/121607251
楼梯在此:https://huidaoli.blog.csdn.net/article/details/121607251
或 https://huidaoli.blog.csdn.net/article/details/121465897
楼梯在此:https://huidaoli.blog.csdn.net/article/details/121465897
若要验证 Django 是否能被 Python 识别,可以在 shell 中输入 python。 然后在 Python 提示符下,尝试导入 Django:
>>> import django >>> print(django.get_version()) 3.2
当然了,你也可能安装的是其它版本的 Django。
from django.contrib import admin from .models import Question class QuestionAdmin(admin.ModelAdmin): fields = ['pub_date', 'question_text'] admin.site.register(Question, QuestionAdmin)你需要遵循以下流程——创建一个模型后台类,接着将其作为第二个参数传给 admin.site.register() ——在你需要修改模型的后台管理选项时这么做。 以上修改使得 "Publication date" 字段显示在 "Question" 字段之前: ![在这里插入图片描述](https://www.www.zyiz.net/i/ll/?i=eaf34448014244e1ab46152c216863f4.png?,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAaHVpZGFvbGk=,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center) 这在只有两个字段时显得没啥卵用,但对于拥有数十个字段的表单来说,为表单选择一个直观的排序方法就显得你的针很细了。 说到拥有数十个字段的表单,你可能更期望将表单分为几个字段集:
from django.contrib import admin from .models import Question class QuestionAdmin(admin.ModelAdmin): fieldsets = [ (None, {'fields': ['question_text']}), ('Date information', {'fields': ['pub_date']}), ] admin.site.register(Question, QuestionAdmin)fieldsets 元组中的第一个元素是字段集的标题。以下是我们的表单现在的样子: ![在这里插入图片描述](https://www.www.zyiz.net/i/ll/?i=079a49b5255446308c8dd2d6428c2e69.png?,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAaHVpZGFvbGk=,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)
好了。
有两个方法可以解决这个问题。第一个就是仿照我们向后台注册 Question 一样注册 Choice :from django.contrib import admin from .models import Choice, Question # ... admin.site.register(Choice)现在 "Choices" 在 Django 后台页中是一个可用的选项了。“添加选项”的表单看起来像这样: ![在这里插入图片描述](https://www.www.zyiz.net/i/ll/?i=5b08056c21484918b4934c1f506a8292.png?,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAaHVpZGFvbGk=,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center) 在这个表单中,"Question" 字段是一个包含数据库中所有考试的选择框。Django 知道要将 ForeignKey 在后台中以选择框 的形式展示。此时,我们只有一个考试。 同时也注意下 "Question" 旁边的“添加”按钮。每个使用 ForeignKey 关联到另一个对象的对象会自动获得这个功能。当你点击“添加”按钮时,你会见到一个包含“添加考试”的表单。如果你在这个弹出框中添加了一个考试,并点击了“保存”,Django 会将其保存至数据库,并动态地在你正在查看的“添加选项”表单中选中它。 不过,这是一种很低效地添加“选项”的方法。更好的办法是在你创建“考试”对象时直接添加好几个选项。让我们实现它。 移除调用 register() 注册 Choice 模型的代码。随后,像这样修改 Question 的注册代码:
from django.contrib import admin from .models import Choice, Question class ChoiceInline(admin.StackedInline): model = Choice extra = 3 class QuestionAdmin(admin.ModelAdmin): fieldsets = [ (None, {'fields': ['question_text']}), ('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}), ] inlines = [ChoiceInline] admin.site.register(Question, QuestionAdmin)
这会告诉 Django:“Choice 对象要在 Question 后台页面编辑。默认提供 3 个足够的选项字段。”
加载“添加考试”页面来看看它长啥样:
class ChoiceInline(admin.TabularInline): #...
通过 TabularInline (替代 StackedInline ),关联对象以一种表格式的方式展示,显得更加紧凑:
注意这里有一个额外的“删除?”列,这允许移除通过“添加新选项”按钮添加的,或是已被保存的行。
现在考试的后台页看起来很不错,让我们对“更改列表”页面进行一些调整——改成一个能展示系统中所有考试的页面。
以下是它此时的外观:
默认情况下,Django 显示每个对象的 str() 返回的值。但有时如果我们能够显示单个字段,它会更有帮助。为此,使用 list_display 后台选项,它是一个包含要显示的字段名的元组,在更改列表页中以列的形式展示这个对象:
class QuestionAdmin(admin.ModelAdmin): # ... list_display = ('question_text', 'pub_date')
另外,让我们把第2节课程中的 was_published_recently() 方法也加上:
class QuestionAdmin(admin.ModelAdmin): # ... list_display = ('question_text', 'pub_date', 'was_published_recently')
现在修改考试的列表页看起来像这样:
你可以点击列标题来对这些行进行排序——除了 was_published_recently 这个列,因为没有实现排序方法。顺便看下这个列的标题 was_published_recently,默认就是方法名(用空格替换下划线),该列的每行都以字符串形式展示出处。
你可以通过在该方法上(在 kaoshi/models.py 中)使用 display() 装饰器来改进,如下图所示:
from django.contrib import admin class Question(models.Model): # ... @admin.display( boolean=True, ordering='pub_date', description='Published recently?', ) def was_published_recently(self): now = timezone.now() return now - datetime.timedelta(days=1) <= self.pub_date <= now
更多关于可通过装饰器设置的属性的信息,请参见 list_display。
再次编辑文件 kaoshi/admin.py,优化 Question 变更页:过滤器,使用 list_filter。将以下代码添加至 QuestionAdmin:
list_filter = ['pub_date']
这样做添加了一个“过滤器”侧边栏,允许人们以 pub_date 字段来过滤列表:
展示的过滤器类型取决你你要过滤的字段的类型。因为 pub_date 是类 DateTimeField,Django 知道要提供哪个过滤器:“任意时间”,“今天”,“过去7天”,“这个月”和“今年”。
这已经弄的很好了。让我们再扩充些功能:
search_fields = ['question_text']
在列表的顶部增加一个搜索框。当输入待搜项时,Django 将搜索 question_text 字段。你可以使用任意多的字段——由于后台使用 LIKE 来查询数据,将待搜索的字段数限制为一个不会出问题大小,会便于数据库进行查询操作。
现在是给你的修改列表页增加分页功能的好时机。默认每页显示 100 项。变更页分页, 搜索框, 过滤器, 日期层次结构, 和 列标题排序 均以你期望的方式合作运行。
在每个后台页顶部显示“Django 管理员”显得很滑稽。这只是一串占位文本。
不过,你可以通过 Django 的模板系统来修改。Django 的后台由自己驱动,且它的交互接口采用 Django 自己的模板系统。
在你的工程目录(指包含 manage.py 的那个文件夹)内创建一个名为 templates 的目录。模板可放在你系统中任何 Django 能找到的位置。(谁启动了 Django,Django 就以他的用户身份运行。)不过,把你的模板放在工程内会带来很大便利,推荐你这样做。
打开你的设置文件(mysite/settings.py,牢记),在 TEMPLATES 设置中添加 DIRS 选项:
TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [BASE_DIR / 'templates'], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ]
DIRS 是一个包含多个系统目录的文件列表,用于在载入 Django 模板时使用,是一个待搜索路径。
就像静态文件一样,我们 可以 把所有的模板文件放在一个大模板目录内,这样它也能工作的很好。但是,属于特定应用的模板文件最好放在应用所属的模板目录(例如 kaoshi/templates),而不是工程的模板目录(templates)。
现在,在 templates 目录内创建名为 admin 的目录,随后,将存放 Django 默认模板的目录(django/contrib/admin/templates)内的模板文件 admin/base_site.html 复制到这个目录内。
如果你不知道 Django 源码在你系统的哪个位置,运行以下命令:
$ python -c "import django; print(django.__path__)"
接着,用你网页站点的名字编辑替换文件内的 {{ site_header|default:_(‘Django administration’) }} (包含大括号)。完成后,你应该看到如下代码:
{% block branding %} <h1 id="site-name"><a href="{% url 'admin:index' %}">kaoshiAdministration</a></h1> {% endblock %}
我们会用这个方法来教你复写模板。在一个实际工程中,你可能更期望使用 django.contrib.admin.AdminSite.site_header 来进行简单的定制。
这个模板文件包含很多类似 {% block branding %} 和 {{ title }} 的文本。 {% 和 {{ 标签是 Django 模板语言的一部分。当 Django 渲染 admin/base_site.html 时,这个模板语言会被求值,生成最终的网页,就像我们在第3节课程所学的一样。
注意,所有的 Django 默认后台模板均可被复写。若要复写模板,像你修改 base_site.html 一样修改其它文件——先将其从默认目录中拷贝到你的自定义目录,再做修改。
机智的同学可能会问: DIRS 默认是空的,Django 是怎么找到默认的后台模板的?因为 APP_DIRS 被置为 True,Django 会自动在每个应用包内递归查找 templates/ 子目录(不要忘了 django.contrib.admin 也是一个应用)。
我们的考试应用不是非常复杂,所以无需自定义后台模板。不过,如果它变的更加复杂,需要修改 Django 的标准后台模板功能时,修改 应用 的模板会比 工程 的更加明智。这样,在其它工程包含这个考试应用时,可以确保它总是能找到需要的自定义模板文件。
更多关于 Django 如何查找模板的文档,参见 加载模板文档。
在类似的说明中,你可能想要自定义 Django 后台索引页的外观。
默认情况下,它展示了所有配置在 INSTALLED_APPS 中,已通过后台应用注册,按拼音排序的应用。你可能想对这个页面的布局做重大的修改。毕竟,索引页是后台的重要页面,它应该便于使用。
需要自定义的模板是 admin/index.html。(像上一节修改 admin/base_site.html 那样修改此文件——从默认目录中拷贝此文件至自定义模板目录)。打开此文件,你将看到它使用了一个叫做 app_list 的模板变量。这个变量包含了每个安装的 Django 应用。你可以用任何你期望的硬编码链接(链接至特定对象的管理页)替代使用这个变量。
接下来要做什么?
初学者学习到这就结束了。随后,你可能想阅读 下一步看什么,看看下一步能做什么。
如果你很熟悉 Python 大屏可视化,且对学习如何把考试应用改成“可复用应用”感兴趣,可以跟着我学习后面的知识和应用实战。