第 5章 开发“公司简介”模块 本章将开发的“公司简介”模块承接第4章的内容,对应hengDaProject项目中的aboutApp应用。该模块一共包含两个子页面: “企业概况”和“荣誉资质”,主要用于介绍企业的基本情况和展示企业获得的荣誉。图51和图52分别显示了两个子页面最终的效果图。“企业概况”页面与第4章制作的“科研基地”页面基本相同,页面全部由静态资源构成,包括说明文字和图片等,所有数据不需要从后台数据库读取。开发“企业概况”页面主要学习如何通过Bootstrap制作侧边导航栏。相对于“企业概况”页面,“荣誉资质”页面则采用动态数据嵌入的方式生成页面,其页面文字和图像均需要从后台读取, 视频讲解 其好处在于可以让网站管理员方便地对企业荣誉进行添加、修改和删除。在“荣誉资质”页面开发的过程中,会详 细阐述Django数据模型概念和基本使用方法。另外,Django提供了现成的后台管理系统,本章会阐述如何使用该后台管理系统以及如何对后台管理系统进行优化,方便管理员管理网站数据。 5.1继承模板 本节先来制作“公司简介”模块的基础页面。根据如图51所示页面效果,其与第4章制作的“科研基地”页面基本相同,仅在页面主体部分左侧多出一个侧边导航栏。下面进入具体的制作步骤。 按照第4章渲染页面的方法,首先打开aboutApp应用,在该应用下创建一个templates文件夹,然后在该文件夹下创建一个名为survey.html的网页文件。根据第4章创建的页面模板,以继承方式继承页面内容,包括: 页面头部、导航栏、页脚。具体代码如下。 {% extends "base.html" %} {% load staticfiles %} {% block title %} 图51“企业概况”页面效果 图52“荣誉资质”页面效果 企业概况 {% endblock %} {% block content %} <!-- 广告横幅 --> <div class="container-fluid"> <div class="row"> <img class="img-responsive model-img" src="{% static 'img/about.jpg' %}"> </div> </div> <!-- 主体内容 --> {% endblock %} 上述代码通过{% extends "base.html" %}来继承模板base.html文件。对于广告横幅,修改相应的静态图片文件路径即可。主体部分暂时不填入内容,详细的主体内容设计将在下一小节进行阐述。 为了能够有效渲染survey.html文件,打开aboutApp应用下的views.py文件,修改视图处理函数survey如下。 def survey(request): return render(request, 'survey.html',{'active_menu': 'about',}) 此处render()函数第一个参数直接返回请求,第二个参数传入欲渲染的HTML文件名,第三个参数是为了在页面切换到“公司简介”时能够同步地切换导航栏激活状态,因此需要向模板添加active_menu参数。按Ctrl+S组合键保存所有修改的文件然后运行项目,单击“公司简介”下的“企业概况”链接,页面效果图如图53所示。 图53“企业概况”初始页面效果 按照上述开发方式,在aboutApp应用的templates文件夹下开发荣誉资质模块对应的页面honor.html,并修改其视图处理函数honor: def honor(request): return render(request, 'honor.html',{'active_menu': 'about',}) 至此,“公司简介”模块下的两个页面框架均已制作完成。可以看到,通过模板的复用,仅需使用几行继承代码,就可以将之前制作的子页面完整地导入进来,可以大幅提高项目开发效率。 最后还遗留一个小问题,如果当前已经在“企业概况”页面内,此时光标移到“荣誉资质”导航链接上会发现两个链接颜色是一样的。为了能够有效进行区分,在style.css文件中添加如下代码。 /* 二级菜单鼠标移过时属性 */ .navbar-default .navbar-nav li ul a:hover{ color:#fff; background-color:#005197; } /* 一级菜单激活时,二级菜单鼠标移过时属性 */ .navbar-default .navbar-nav li.active ul a:hover{ color:#fff; background-color:#022a4d; } 通过上述设置,两个子模块链接在鼠标移过时就会呈现不同的颜色。5.2节将开始制作页面主体部分。 5.2制作侧边导航栏 5.1节完成了“公司简介”模块下两个页面的基本框架设计,并修改了对应的视图处理函数,本节将制作主体部分中的侧边导航栏以方便用户切换子页面。 根据如图51所示效果,页面主体可以分为左右两部分,左边是侧边导航栏,右边是固定位置的图片和介绍性文字。根据页面结构,设计HTML基本结构如下。 <div class="container"> <div class="row row-3"> <!-- 侧边导航栏 --> <div class="col-md-3"> </div> <!-- 说明文字和图片 --> <div class="col-md-9"> </div> </div> </div> 上述代码对页面采用39栅格布局,侧边导航栏占3个栅格,右边内容占9个栅格。采用container将整个页面主体内容限制在指定宽度内,并包含在class=row的div中,占满一行。其中,为行div添加额外的样式“.row3”,编辑style.css文件添加样式设置: .row-3{ margin-top:30px;/* 设置顶部边距 */ } 侧边导航栏部分采用Bootstrap提供的列表组件listgroup实现,其中每一个链接列表项用样式listgroupitem表示,具体代码如下。 <!-- 侧边导航栏 --> <div class="col-md-3"> <div class="model-title"> 公司简介 </div> <div class="model-list"> <ul class="list-group"> <li class="list-group-item" id="survey"> <a href="{% url 'aboutApp:survey' %}">企业概况</a> </li> <li class="list-group-item" id="honor"> <a href="{% url 'aboutApp:honor' %}">荣誉资质</a> </li> </ul> </div> </div> 上述代码中"{% url 'aboutApp:survey' %}"和"{% url 'aboutApp:honor' %}"用于逆向寻找路由,方便后期部署。modeltitle和modellist样式类分别用于定制导航栏标题和列表样式,编辑style.css文件,添加对应的样式。 /*侧边导航栏标题样式*/ .model-title { text-align: center; color: #fff; font-size: 22px; padding: 15px 0px; background: #005197; margin-top: 25px; } /*侧边导航栏列表项样式*/ .model-list li{ text-align:center; background-color:#f6f6f6; font-size:16px; } /*侧边导航栏列表项链接样式*/ .model-list li a{ color:#545353; } /*侧边导航栏列表项链接激活样式*/ .model-list li a:hover{ text-decoration:none; color:#005197; } 通过上述样式设置,可以完成侧边导航栏的基本设计。接下来针对侧边导航栏的页面切换链接进行样式设计。大致思路与设计一级导航栏链接一致,在侧边导航栏链接切换时处于激活状态的链接文字呈现蓝色,其他链接文字呈现灰色,这样用户切换侧边导航栏之后就可以明显地看到当前处于哪个子页面。实现方法可以参照一级导航栏的设计流程,只需要由后台向模板传递二级菜单变量,然后前端通过JavaScript脚本的addClass()函数动态地对<li>标签添加active类即可实现。首先,编辑style.css文件,添加代码如下。 /*侧边导航栏激活样式*/ .model-list li.active{ text-align:center; background-color:#f6f6f6; font-size:16px; border-color: #ddd; } /*侧边导航栏激活状态下鼠标移过时样式*/ .model-list li.active:hover{ text-align:center; background-color:#f6f6f6; font-size:16px; border-color: #ddd; } /*侧边导航栏激活状态时链接样式*/ .model-list li.active a{ color:#005197; } 上述CSS代码可以使得当侧边导航栏中的某一链接处于激活状态时其链接文字显示蓝色,方便用户浏览和辨识。接下来在base.html文件的<body>标签最后添加JavaScript代码: <script type="text/JavaScript"> $('#{{sub_menu}}').addClass("active"); </script> 最后修改aboutApp应用中的views.py文件,重新编辑survey()和honor()函数,在最后render()函数返回时添加额外的submenu变量。 def survey(request): return render(request, 'survey.html', { 'active_menu': 'about', 'sub_menu': 'survey', }) def honor(request): return render(request, 'honor.html', { 'active_menu': 'about', 'sub_menu': 'honor', }) 通过上述修改,即可实现侧边导航栏二级菜单切换。至此,已完成侧边导航栏的开发任务。接下来继续完善“企业概况”页面。主体右边部分是位置固定的介绍性文字和图片,其设计与“科研基地”页面基本一致,包括标题、下画线、段落文字和图片,这里不再过多阐述,详细设计代码可以参照4.1节。可以直接将4.1节中的代码复制到此处,然后替换文字和图片路径即可。“企业概况”最终效果如图51所示。 从最终效果来看,“企业概况”页面主体部分的文字和图片均为静态资源文件,即不需要与后台数据库进行交互,直接在HTML文件中调用,这种页面称为静态页面,其开发相对较为简单。在5.3节,将学习如何通过Django数据库模型来构建动态页面。 5.3Django数据库模型 本节将会通过Django数据库模型来渲染“荣誉资质”页面,其基本实现流程如下。 (1) 用户通过浏览器请求页面。 (2) 服务器收到浏览器请求,根据URL路由找到匹配的视图处理函数。 (3) 视图处理函数首先找到需要返回的HTML模板文件,然后从数据库中取出数据(图片数据对应的是图片的存储路径),然后将数据过滤后以模板变量形式插入到模板文件中,最后通过render()函数返回生成的页面。 (4) 浏览器收到请求页面并显示。 在2.8节中已经阐述了如何通过Python操作数据库,一般步骤为创建数据库、设计表结构和字段、使用SQLite(MySQL、PostgreSQL等)引擎来连接数据库、编写数据访问层代码、业务逻辑层调用数据访问层执行数据库操作。这里注意到上述数据库操作流程较为烦琐,需要开发人员直接面向数据库进行数据的增删查改,开发效率较低。是否可以让开发人员直接面向代码中的对象来操作数据库呢?答案是可以的。这种面向对象的数据库编程方式即为对象关系映射(Object Relational Mapping, ORM)。具体地,在ORM中类名对应数据库中的表名,类属性对应数据库里的字段,类实例对应数据库表里的某一行数据。Django中内嵌了ORM框架,不需要直接面向数据库编程,而是通过模型类和对象完成数据表的增删改查操作。 使用Django进行数据库开发的步骤如下。 (1) 配置数据库连接信息。 (2) 在模型文件models.py中定义模型类。 (3) 数据库模型迁移。 (4) 通过类和对象完成数据增删改查操作。 具体地,Django已经在项目创建时自动地提供了一个SQLite数据库用于为项目提供数据库操作,同时已为该数据库的使用配置好了参数。打开配置文件夹hengDaProject下的settings.py文件,找到其中的DATABASES字段,默认配置如下。 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), } } 可以看到,该项目默认数据库引擎ENGINE为django.db.backends.sqlite3,数据库路径为当前项目根目录下的db.sqlite3数据库文件(SQLite数据库本质上是一个文件)。如果需要采用其他数据库,那么数据库的配置就在该字段进行设置。在实际Web站点部署时,一般不会采用SQLite数据库,因为该数据库的并发量、响应速度等具有较大的限制,但是在开发阶段可以采用该数据库进行开发测试。在第11章项目部署环节将会详细阐述如何在Django中配置和使用MySQL数据库。 在了解Django数据库的基本概念和配置后,5.3.1节将会通过Django数据库模型来进行具体的开发。 5.3.1创建荣誉模型 参照如图52所示效果,可以看到企业获得的每一项荣誉均采用“1张图片+1段简要文字描述”这种形式进行展示。为了能够在后期方便管理人员对荣誉信息进行管理,需要抽象出当前的荣誉数据,并在数据库中生成相应的数据模型。 Django数据模型是与数据库相关的,与数据库相关的代码通常写在models.py文件中。首先打开aboutApp中的models.py文件,在该文件中添加“荣誉”(Award)模型。 from django.db import models class Award(models.Model):#荣誉模型 description = models.TextField(max_length=500, blank=True, null=True)#文字描述 photo = models.ImageField(upload_to='Award/', blank=True) #图片 首先导入django.db中的models模块来方便创建数据库字段。接下来定义了一个Award类,对应“荣誉”模型,该类继承自models.Model。在Award类中定义了两个字段: description和photo,分别对应“荣誉”模型的文字描述和图片。文字描述采用models.TextField来进行字段声明,并且使用max_length参数来设置该字段允许的最大长度。另外,通过设置参数blank=True, null=True表示该字段允许为空。图片信息采用models.ImageField来声明,通过设置upload_to参数来定义图片的上传目录,上传的图像信息会存储在服务器媒体资源路径的Award文件夹下面。 在本节实例中仅使用了Django数据库模型中的文本和图像字段,除此以外,Django还提供了很多其他有用的字段,包括整型数据、字符型数据、浮点型数据等,具体调用形式和参数如表51所示。 表51Django数据库模型常用字段 CharField字符串字段,用于较短的字符串。CharField要求必须有一个参数maxlength,用于从数据库层和Django校验层限制该字段所允许的最大字符数 IntegerField用于保存一个整数 DecimalField用于保存一个浮点数。使用时必须提供以下两个参数。 max_digits: 总位数(不包括小数点和符号)。 decimal_places: 小数位数 AutoField用于保存一个整型数据,添加记录时它会自动增长。通常不需要直接使用这个字段 BooleanField用于保存真、假逻辑数据 TextField用于保存一个容量很大的文本字段 EmailField一个带有检查邮件合法性的字符字段,不接受maxlength参数 DateField用于保存一个日期字段。可选参数主要有以下两个。 auto_now: 当对象被保存时,自动将该字段的值设置为当前时间。 auto_now_add: 当对象首次被创建时,自动将该字段的值设置为当前时间 DateTimeField用于保存一个日期时间字段,功能类似DateField,支持同样的附加选项 FileField用于上传文件,在声明时必须指定参数upload_to,该参数表明用于保存文件的本地路径 ImageField功能类似FileField,不过要校验上传对象是否是一个合法图片。除了upload_to以外它还有两个可选参数: height_field和width_field,如果提供这两个参数,则图片将按提供的高度和宽度规格进行保存 URLField用于保存URL。若verify_exists 参数为True (默认),给定的URL会预先检查是否存在,即检查URL是否被有效装入且没有返回404响应 NullBooleanField类似BooleanField,不过允许NULL作为其中一个选项 注意,在使用表51中的Django模型字段时,其中关于文件上传的两个字段ImageField和FileField需要额外进行路径设置,即需要在项目中指定媒体资源文件存储目录。由于本节实例也采用了图像ImageField字段,因此需要进行配置。具体地,打开配置文件夹hengDaProject下的settings.py文件,在文件末尾添加代码: MEDIA_URL = '/media/' MEDIA_ROOT = os.path.join(BASE_DIR, 'media/') 上述配置可以告诉解释器当前项目的媒体资源文件(此处指图像)的存储根路径为/media/,即将所有上传的图片存储在项目根目录下的media文件夹中,结合数据库ImageField字段中参数upload_to的设置,最终上传的图片存储路径为/media/Award。 模型创建完成后需要将创建的模型同步到数据库系统中。在终端中首先输入命令: python manage.py makemigrations 此时,会在终端中输出结果: Migrations for 'aboutApp': aboutApp\migrations\0001_initial.py - Create model Award 此时,已经做好将模型数据存入数据库的准备。打开aboutApp应用中的migrations文件夹可以查看当前文件夹下已经创建了0001_initial.py文件,此文件即为在本地创建好的需要同步的数据模型文件。但是注意,此时并没有真正进行数据库同步,仅仅完成了同步的准备工作。接下来输入命令: python manage.py migrate 控制台输出结果为: Operations to perform: Apply all migrations: aboutApp, admin, auth, contenttypes, sessions Running migrations: Applying aboutApp.0001_initial... OK Applying contenttypes.0001_initial... OK Applying auth.0001_initial... OK Applying admin.0001_initial... OK Applying admin.0002_logentry_remove_auto_add... OK Applying contenttypes.0002_remove_content_type_name... OK Applying auth.0002_alter_permission_name_max_length... OK Applying auth.0003_alter_user_email_max_length... OK Applying auth.0004_alter_user_username_opts... OK Applying auth.0005_alter_user_last_login_null... OK Applying auth.0006_require_contenttypes_0002... OK Applying auth.0007_alter_validators_add_error_messages... OK Applying auth.0008_alter_user_username_max_length... OK Applying sessions.0001_initial... OK 此时才真正完成了数据库模型的同步操作,即在数据库中已经为Award模型创建好了对应的数据表。接下来可以对该数据库模型进行数据增删查改操作。可以直接在Python Shell中通过代码编辑数据库中的数据,但是这种通过代码对数据库进行增删查改的方式并不方便也不直观,而Django自带强大的后台管理系统,通过该后台管理系统可以方便地对创建的数据库模型进行管理和操作。 5.3.2Django后台管理系统 一个企业门户网站分为前台和后台两部分。前台主要为普通用户提供常规页面的访问,可以浏览基本信息。后台由网站的管理员负责网站数据的查看、添加、修改和删除。开发一套完整的后台管理系统是一件异常烦琐的工作,为此,Django提供了现成高效的后台管理系统,在我们创建项目的过程中已经自动生成了这样一个便捷的后台。 具体地,Django能够根据定义的模型自动地生成管理模块,使用Django的管理功能只需要以下两步操作。 (1) 创建超级管理员。 (2) 注册模型类。 要使用Django的后台管理系统首先需要创建一个超级管理员账户来登录后台系统。具体地,在终端中输入命令: python manage.py createsuperuser 此时会弹出提示需要输入超级管理员用户名: Username (leave blank to use 'administrator'): 输入完成后按Enter键,会出现提示需要输入邮箱: Email address: 输入完成后按Enter键,会出现提示需要输入超级管理员账户密码: Password: 在输入过程中由于是密码因此输入时不会显示当前输入的字符。输入完成后直接按Enter键,会要求再次输入密码以完成密码的前后一致性检查。 Password (again): 输入完成并且两次密码输入正确后会出现: Superuser created successfully. 此时表明超级管理员已经成功创建。接下来启动项目并访问http://127.0.0.1:8000/admin,访问效果如图54所示。 图54Django后台管理系统登录页面 如图54所示页面即为后台管理系统的登录页面,输入创建的超级管理员用户名和密码即可登录后台管理系统。登录后的页面如图55所示。 图55Django后台管理系统主页面 图56Django后台管理系统Users列表 进入后台管理系统后可以看到当前已经注册在系统中的模型,包括Groups和Users,这是系统默认提供的账户管理模型。单击Users可以看到如图56所示页面,在该页面中列出了当前的所有用户数据,此处由于我们并没有创建其他用户数据,因此仅可看到超级管理员账户。 在后台管理系统中,可以通过可视化按钮以及系统提供的默认表单方便地对数据库模型进行操作。 下面继续完成本章开发任务。从图55中可以看到,当前管理系统主页面并没有Award模型的操作设置,这是因为我们在数据库中创建了Award模型,但是并没有将该模型注册到后台管理系统中,因此后台管理系统也就无法操作该模型。如果需要将模型注册到后台管理系统,只需要在admin.py文件中添加模型对应的注册信息即可。具体地,打开aboutApp中的admin.py文件,编辑代码如下。 from django.contrib import admin from .models import Award class AwardAdmin(admin.ModelAdmin): list_display = ['description','photo'] admin.site.register(Award, AwardAdmin) 首先引入Django中提供的管理员模块admin,然后从models.py文件中导入前面创建的Award类。接下来定义了一个名为AwardAdmin的荣誉管理类,该类继承自admin模块中的ModelAdmin类。在AwardAdmin中设置了展示列表list_display参数,在该参数中将需要编辑的模型字段添加进来,此处包括文字描述字段description和图像字段photo。最后通过admin.site.register()函数将AwardAdmin类与Award类进行绑定并实现注册。保存所有修改,刷新浏览页面可以看到在后台管理系统中新增加了ABOUTAPP组(对应AboutApp应用),在该组中可以操作Award类,如图57所示。 图57Django后台管理系统添加注册模型 接下来,通过后台管理系统向Awards模型中添加几条数据用于后期使用。单击Award所在行对应的Add按钮,进入数据添加界面,如图58所示。 图58Django后台管理系统向模型中添加数据 在定义Award模型时共有两个字段: description和photo,与后台数据添加界面中的两个字段一一对应。由于description采用了长文本字段TextField来声明,因此后台管理系统自动地为该字段形成多行输入框便于用户输入数据,而photo声明时使用了ImageField字段,因此后台管理系统自动形成文件上传按钮来执行数据添加操作。按照输入格式,在description中添加文字描述,然后单击“浏览”按钮选中一张图片(注意上传的照片名中不要含中文),最后单击右侧的SAVE按钮保存数据。 按照上述方式继续添加几条类似的Award数据,最终Award列表如图59所示。 图59Django后台管理系统Award模型数据列表 此时,Award模型中所有数据均已存入数据库文件中。值得注意的是,对于图像photo字段,在数据库中并不是直接存储了该图像数据,而是存储了对应的图像路径。图像的真实存储路径根据settings文件的MEDIA_URL和MEDIA_ROOT来设置。具体地针对本实例项目,可以查看当前项目根目录下的media文件夹中是否存在对应的图片(media/Award路径下)。 除了向模型添加数据以外,同样可以通过后台管理系统实现模型数据的删、改、查操作,具体的内容此处就不再一一展开演示。在数据库中有了上述的Award模型数据以后,就可以在用户请求页面的过程中动态地向页面嵌入数据实现动态页面的访问。5.3.3节将会阐述如何通过Django从数据库中取出模型数据并插入到模板中进行动态页面渲染。 5.3.3动态页面渲染 Django提供了方便的ORM操作来对数据库模型进行管理。当用户在访问荣誉资质页面时,请求通过路由URL分发至views.py文件中的honor()函数进行处理,该函数收到请求后首先从数据库中取出Award模型的所有数据,然后将数据嵌入到honor.html模板文件中。 重新编辑views.py文件中的honor()函数如下。 from .models import Award def honor(request): awards = Award.objects.all() return render(request, 'honor.html', { 'active_menu': 'about', 'sub_menu': 'honor', 'awards': awards, }) 首先从当前应用下的model.py文件中导入Award模型,然后在honor()函数中通过模型的objects.all()函数得到一个查询集并存放于变量awards中。在页面渲染时通过render()函数将awards变量以参数形式添加到页面中。本实例通过Django模型管理器的objects.all()函数来获取模型数据信息。除此以外,Django还提供了很多其他的查询功能,具体见表52。此处,并不需要一次性地掌握所有查询语句,只需要在后续章节中通过项目实例逐步学会常见的调用方式即可。 表52Django数据库常用查询方法 管理器方法返 回 类 型说明 模型类.objects.all()QuerySet返回表中所有数据 模型类.objects.filter()QuerySet返回符合条件的数据 模型类.objects.exclude()QuerySet返回不符合条件的数据 模型类.objects.order_by()QuerySet对查询结果集进行排序 模型类.objects.values()QuerySet返回一个列表,每个元素为一个字典 模型类.objects.reverse()QuerySet对排序的结果反转 模型类.objects.get()模型对象返回一个满足条件的对象; 如果没有找到符合条件的对象,会引发模型类.DoesNotExist异常; 如果找到多个,会引发模型类.MultiObjectsReturned 异常 模型类.objects.count()int返回查询集中对象的数目 模型类.objects.first()模型对象返回第一条数据 模型类.objects.last()模型对象返回最后一条数据 模型类.objects.exists()bool判断查询的数据是否存在 下面开始编辑honor.html页面。根据如图52所示效果,“荣誉资质”页面的整体设计和“企业概况”页面一致,不同之处在于主体部分采用图片列表的形式展示企业所获荣誉。在布局时可以采用Bootstrap现成的缩略图组件(样式类thumbnail)略加修改即可实现。初始设计方案如下。 <div class="col-md-9"> <div class="model-details-title"> 荣誉资质 </div> <div class="row"> <div class="col-sm-6 col-md-4"> <div class="thumbnail"> <img src="{% static 'img/honor1.jpg' %}"> <div class="caption"> <p>2011年加入互联网协会</p> </div> </div> </div> <div class="col-sm-6 col-md-4"> <div class="thumbnail"> <img src="{% static 'img/honor2.jpg' %}"> <div class="caption"> <p>2012年加入互联网协会</p> </div> </div> </div> </div> </div> 上述代码共包含两个缩略图,每个缩略图包括一个<img>标签用于显示图像以及一个class="caption"的<div>标签用于显示图片对应的描述信息。每个缩略图在大屏浏览器下占4个栅格,在小屏浏览器上占6个栅格。上述代码采用了静态页面方式将图像路径和文字描述信息显式地写在HTML中,无法根据数据库信息动态地修改图片和文字数据。接下来需要实现根据后台honor()函数传入的awards参数将数据动态地写入HTML中,主要通过模板标签{% for %}{% endfor %}来实现。该模板标签可以动态地遍历传入的变量,实现页面数据循环写入。具体代码如下。 <div class="col-md-9"> <div class="model-details-title"> 荣誉资质 </div> <div class="row"> {% for award in awards %} <div class="col-sm-6 col-md-4"> <div class="thumbnail"> <img src="{{award.photo.url}}"> <div class="caption"> <p>{{award.description}}</p> </div> </div> </div> {% endfor %} </div> </div> 上述代码通过{% for award in awards %}语句逐个地取出awards中的每一条数据并赋值到新的临时变量award中,每个award都包含一项photo和description数据。在缩略图中分别使用模板变量{{award.photo.url}}和{{award.description}}对<img>的src属性以及段落<p>赋予动态内容。这种方式可以根据awards中的实际的条目数来生成缩略图。对该页面数据的增删查改不再需要开发人员变更代码实现,只需要通过后台管理系统操作数据即可完成数据更新。刷新页面后浏览效果如图510所示。 图510动态页面效果 可以看到每个缩略图的文字信息均已正确显示,但是图片信息没有显示出来。主要原因在于当前debug模式下没有将动态资源路径MEDIA_URL添加到静态路由static下。编辑配置文件夹hengDaProject下的urls.py文件,添加代码如下。 from django.conf import settings from django.conf.urls.static import static if settings.DEBUG: urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) 保存修改后,重新刷新网页即可看到正确的效果图。至此,本节完成了数据库模型的导出和渲染。通过本节“荣誉资质”子模块的开发,相信读者已经掌握动态页面的制作流程和基本的数据库操作方法。后续章节的其他页面均采用这种动态页面的制作方式来实现。因此,希望读者能够牢牢掌握本节内容的知识点,多动手多实践,对于其中不清楚的地方可以结合本书配套资源代码来分析。 5.4优化后台管理系统 在5.3节中介绍了Django的后台管理系统的使用方法,对于开发人员来说,掌握该后台管理系统的使用是必需的,但是该系统对于非开发人员来说其交互方式并不友好,包括语言(Django后台管理系统默认语言为英文)和界面设计等。本节重点阐述如何对后台管理系统进行优化以方便今后将网站交付给实际客户使用。 5.4.1登录界面优化 1. 界面汉化 Django在创建项目时默认将英文作为项目主要语言,因此,在后台管理系统中大部分字段都是英文。下面首先对登录界面进行汉化处理。 打开项目配置文件settings.py,找到其中的LANGUAGE_CODE字段,该字段用于设置整个项目的语言,这里需要改为中文支持。另外,需要修改时区字段TIME_ZONE为中国时区,对其进行修改如下。 LANGUAGE_CODE = 'zh-Hans'#设置语言为中文 TIME_ZONE = 'Asia/Shanghai' #设置中国时区 修改后保存并启动项目。访问后台管理系统,可以发现关键字段英文都已转换为中文,效果如图511所示。 2. 修改管理系统名称 Django提供的后台管理系统默认的系统名称为“Django管理”,而在实际交付给客户使用时需要按照网站主题定义后台系统名字,因此接下来需要完成后台管理系统名称的修改。 打开aboutApp应用下的admin.py文件,在文件末尾添加代码: admin.site.site_header = '企业门户网站后台管理系统' admin.site.site_title = '企业门户网站后台管理系统' 上述代码分别对管理系统头部和页面标题进行了修改,保存修改后刷新页面如图512所示。这里注意,由于我们创建的项目hengDaProject是一个多应用项目,上述代码修改只需要放置在任一应用下的admin.py文件中即可生效。 图511Django后台管理系统登录界面汉化 图512修改Django后台管理系统名称 5.4.2主界面优化 1. 模型名称修改 主界面部分首先来修改数据模型的显示。由于创建了Award模型,因此在ABOUTAPP下可以看到英文显示的“Awards”字样(默认会以模型名的复数形式表示)。尽管开发人员知道该模型含义,但是对于非开发人员来说英文字样较为突兀,这里希望能够改成“获奖荣誉”。一种有效的解决思路就是在模型的创建过程中为模型创建一个中文别名,这样在后台管理系统中就可以用别名替代模型的真实名来显示。Django为这种思路提供了简单的实现方法,只需要修改模型的Meta元信息即可。打开aboutApp应用下的models.py文件,为定义的Award模型添加Meta元信息说明,代码如下。 class Award(models.Model): #荣誉模型 description = models.TextField(max_length=500, blank=True, null=True) #文字描述 photo = models.ImageField(upload_to='Award/', blank=True) #图片 class Meta: verbose_name = '获奖和荣誉' verbose_name_plural = '获奖和荣誉' 其中,verbose_name字段即为模型定义的别名,verbose_name_plural为别名对应的复数形式。保存后刷新页面即可看到如图513所示效果。 图513修改数据模型名称 2. 应用名称修改 接下来需要对应用名ABOUTAPP的显示进行修改。针对本章任务来说,需要将ABOUTAPP修改为“公司简介”。Django在后台默认显示的应用的名称为创建App时的名称,需要修改这个App的名称达到定制的要求。从Django 1.7版本以后不再使用app_label,修改App需要使用AppConfig。这里只需要在应用的init.py里面进行修改即可,打开aboutApp下的init.py文件,添加代码如下。 from os import path from django.apps import AppConfig VERBOSE_APP_NAME = '公司简介' def get_current_app_name(file): return path.dirname(file).replace('\\', '/').split('/')[-1] class AppVerboseNameConfig(AppConfig): name = get_current_app_name(file) verbose_name = VERBOSE_APP_NAME default_app_config = get_current_app_name( file) + '.init.AppVerboseNameConfig' 这里主要参考Django官方参考文档来实现,通过继承AppConfig类来设置App别名,该部分代码如果难以理解可以暂时不做深究,主要注意VERBOSE_APP_NAME字段,通过修改该字段可以为应用添加别名。保存修改后刷新页面,效果图如图514所示。 图514修改应用名称 后续章节每个应用在后台管理界面中均按照上述方法进行名称修改,本书对此不再重复阐述。 5.4.3列表界面优化 单击模型会进入模型列表页面,该页面中显示了模型的所有数据,注意到模型的每个字段依然是英文。接下来将对模型字段进行修改使得description和photo分别显示为“荣誉描述”和“荣誉照片”。解决方法与模型名称的修改基本一致,通过对模型每个字段取别名来进行显示。重新编辑Award模型中的description和photo字段,为每个字段添加verbose_name属性,具体修改如下。 description = models.TextField(max_length=500, blank=True, null=True, verbose_name='荣誉描述') photo = models.ImageField(upload_to='Award/', blank=True, verbose_name='荣誉照片') 保存修改后刷新页面,效果如图515所示。 图515修改模型字段名称 小结 本章实现“公司简介”模块的开发,该模块共包含两个页面: 一个静态页面(“企业概况”页面)和一个动态页面(“荣誉资质”页面)。静态页面主要学习模板的继承以及侧边导航栏的制作。动态页面则通过Django实现了“荣誉”模型的后台管理和页面显示,重点需要掌握Django数据模型创建方式、后台管理系统的使用技巧以及前端页面渲染动态数据方法。本章最后一节阐述如何对后台管理系统进行优化以方便非开发用户使用。本章内容侧重阐述后端Python Web编程知识,通过一个动态页面的制作来学习Django数据库的使用,后续章节的页面大部分均采用这种动态页面制作的方式实现。因此,读者需要牢牢掌握本章知识内容。