保定模板建站哪家好,网站内容优化方案,一级的vi设计公司,宝安网站制作网站建设1. 创建项目
1.1 新建项目
首先新建一个项目#xff0c;名为 mysite#xff0c;命令如下#xff1a;
django-admin startproject mysite # 或用 django-admin.py运行成功#xff0c;生成一些目录#xff1a;
mysite/manage.py # 管理 Django 项目的命令行工具mysit…1. 创建项目
1.1 新建项目
首先新建一个项目名为 mysite命令如下
django-admin startproject mysite # 或用 django-admin.py运行成功生成一些目录
mysite/manage.py # 管理 Django 项目的命令行工具mysite/ # 包包含项目__init__.pysettings.py # 配置文件urls.py # 路由文件wsgi.py # WSGI 接口web 服务器进入点提供底层网络通信功能无需关心1.2 启动服务器
python manage.py runserver # 默认以 8000 端口开启
python manage.py runserver 8080 # 指定端口执行成功看到输出如下信息 在浏览器中访问 http://127.0.0.1:8000/看到以下信息表示开启成功Django2.x 以下版本不一样 1.3 新建应用
现在我们新建一个应用app名为 polls命令如下
cd mysite # 切好到项目里面
python manage.py startapp polls执行成功后可以看到 mysite 中多了一个 polls文件夹打开 polls里面包含以下文件
polls/__init__.pyadmin.py # Django 提供的后台管理程序apps.py migrations/ # 数据库表生成记录__init__.pymodels.py # 模型与数据库相关tests.py # 测试文件views.py # 视图一个视图函数表示一个页面项目与应用的区别
一个项目可以有一个或多个应用一个应用往往是用来实现某个功能如博客、日程管理系统等一个应用可以属于多个项目
1.4 第一个视图
一个视图函数表示一个 Web 页面在 polls/views.py 中编写
from django.shortcuts import render, HttpResponsedef index(request):首页return HttpResponse(Is Ok!)要调用视图我们需要先配置 urlconf让 Django 找到我们的视图函数在此之前我们先把 app 添加到 settings.py 中
INSTALLED_APPS [django.contrib.admin,django.contrib.auth,django.contrib.contenttypes,django.contrib.sessions,django.contrib.messages,django.contrib.staticfiles,polls, # 最好空一行以示区分
]配置 urlconf
编写 mysite/urls.py
from django.contrib import admin
from django.urls import path, include
from polls import views # 导入视图函数urlpatterns [path(admin/, admin.site.urls),path(index/, views.index, nameindex),
]访问 http://127.0.0.1:8000/index/如果不出意外的话会看到 Is Ok! 的字样~
多级路由
上面我们只创建了一个 app因此 url 路径配置在项目 mysite/urls.py中毫无影响但是当有多个应用且有多个相同的名字的视图时为了避免冲突就需要用到多级路由了。
配置 mysite/urls.py
from django.contrib import admin
from django.urls import path, include # 引入 includeurlpatterns [path(admin/, admin.site.urls),path(polls/, include(polls.urls)), # include 就相当于多级路由它会将去掉 url 前面的正则将剩余字符串传递给下一级路由即 polls/urls.py 来判断
]在应用 polls 目录下新建一个 urls.py 文件配置如下
from django.urls import path
from polls import views # 导入视图函数urlpatterns [path(index/, views.index, nameindex),# url(r^index/, views.index, nameindex), # django2.x 以前版本
]那么访问地址将变成 http://127.0.0.1:8000/polls/index/。
2. 模型和后台管理
2.1 数据库配置
在 Django 中模型即指数据库Django 内置 SQLite 数据库可以直接使用它。但是 SQLite 一般仅用来测试使用实际开发中一般很少不会使用。如果要使用其他数据库需要配置 settings并安装相应驱动下面我们以 MySQL 为例。
常用数据库配置
django.db.backends.sqlite3,
django.db.backends.postgresql
django.db.backends.mysql
django.db.backends.oracle,设置 settings.py
DATABASES {default: {ENGINE: django.db.backends.mysql,NAME: test, # 数据库名字需要事先创建USER: root, # 用户名PASSWORD: , # 密码HOST: , # 留空默认为 localhost数据库主机名PORT: 3306,}
}安装 pymysql 模块
pip install pymysql激活 MySQL打开项目mysite/__init__.py 文件配置如下
import pymysql
pymysql.install_as_MySQLdb()时区和语言
Django 默认使用 UTC 时区以及英文我们可以将其修改为东八区和中文
LANGUAGE_CODE zh-hans
TIME_ZONE Asia/Shanghai2.2 创建模型 Model
Django 通过 ORMObject Relation Mapping对象关系映射以面向对象的方式去操作数据库即使不懂 SQL 语句也可以操作数据库。
我们只需在模型中创建相应的 类以及字段即可然后再执行命令Django会自动帮我们生成数据表
类对应数据表名字段对应数据表的列
在此之前我们创建了一个投票应用 polls现在我们将创建两个数据表问题表 Question用来存储问题以及发布事件、以及选择人们的选择表Choice。
下面我们编写 polls/models.py
from django.db import modelsclass Question(models.Model): # 每个类必须继承 models.Model数据表问题表question_text models.CharField(max_length2000) # 问题内容pub_date models.DateTimeField(date published) # 发布日期class Choice(models.Model):数据表选择表choice_text models.CharField(max_length200) # 选择votes models.IntegerField(default0) # 是否已经投票question models.ForeignKey(Question, on_deletemodels.CASCADE) # 外键关联在上面有些字段我们指定了最长宽度 max_length这将限制其输入范围非必须但是最好有所限制 另外我们通过外键数据库内容 ForeignKey将两个表关联起来也就是这两张表是一对多关系。 一个问题可以有多个选择除此之外数据表间关联还有 一对一、以及多对多关系后面讲详细介绍。 模型创建和数据迁徙
接下来就是创建模型执行 python manage.py makemigrations polls会看到以下提示 这表示在 polls\migrations\0001_initial.py 文件中创建相关模型记录当我们对数据表操作时会在上面有相应记录保存在我们的电脑磁盘上面。
接着我们要将数据迁徙到真正的数据库中去执行 python manage.py migrate 在 Pycharm 中打开 SQLite 可以看到创建很多数据表 Tips
创建模型时我们不需要创建 idDjango 会自动帮我们创建外键字段Django会在其名字之上加上一个 _id表示与主表的 ID 进行关联Django 运行随时修改模型只需按照以下三步走即可不丢失数据 修改 models.py执行 python manage.py makemigrations app_name 为改动创建迁徙记录执行 python manage.py migrate 将操作同步至数据库
2.3 操作模型
上面我们通过相应命令创建了模型那么我们该如何操作数据表中内容呢Django为我们提供了一系列的 API可以很方便地就能操作数据。
进入 Django 提供的 shell 交互环境 python manage.py shell from polls.models import Question, Choice # 导入模型类Question.objects.all() # 获取所有 question 对象
QuerySet [] # 因为里面还没数据所有是空的 from django.utils import timezone # 导入 Django 内置的 timezone 模块获取时间来自于依赖库 pytzq Question(question_textWhats new?, pub_datetimezone.now()) # 创建 question 对象q.save() # 保存到数据库q.id # 通过对象属性调用方式访问模型中字段的值
1q.question_text
Whats new?q.pub_date
datetime.datetime(2019, 2, 28, 8, 10, 18, 766500, tzinfoUTC)# 修改字段的值再保存q.question_text Whats up?q.save()# .all() 方式查询数据库中所有对象这里是 question 对象Question.objects.all()
QuerySet [Question: Question object (1)]在上面我们访问 Question 中所有对象时得到是一个 object 对象这样显示很不友好为此我们可以为模型添加一个 __str()__ 方法使其能够更具有可读性
from django.db import models
import datetime
from django.utils import timezoneclass Question(models.Model):...def __str__(self):return self.question_text # 返回的是 question_text而不是 objectclass Choice(models.Model):...def __str__(self):return self.choice_text重新打开一个 shell来看看其他 API from polls.models import Question, ChoiceQuestion.objects.all()
QuerySet [Question: Whats up?]# 关键字查询 filter() 方法过滤 id1Question.objects.filter(id1)
QuerySet [Question: Whats up?]# 查询 question_text 以 What 开头的 questionQuestion.objects.filter(question_text__startswithWhat)
QuerySet [Question: Whats up?]# 导入 timezone
# 查询今年发布的问题from django.utils import timezonecurrent_year timezone.now().year # 获取今年时间2019Question.objects.get(pub_date__yearcurrent_year) # __year2019
Question: Whats up?# 查询不存在的 ID出现异常Question.objects.get(id2)
Traceback (most recent call last):File console, line 1, in moduleFile E:\Python_virtualenvs\for_django\lib\site-packages\django\db\models\manager.py, line 82, in manager_methodreturn getattr(self.get_queryset(), name)(*args, **kwargs)File E:\Python_virtualenvs\for_django\lib\site-packages\django\db\models\query.py, line 399, in getself.model._meta.object_name
polls.models.Question.DoesNotExist: Question matching query does not exist.# pk 即 primary key 缩写与 id 等同Question.objects.get(pk1)
Question: Whats up? q Question.objects.get(pk1) # 创建 Question 对象q.choice_set.all() # 通过 数据表名_set.all() 方式获得与其关联的数据表的所有对象
QuerySet []# 创建三个 choicesq.choice_set.create(choice_textNot much, votes0)
Choice: Not muchq.choice_set.create(choice_textThe sky, votes0)
Choice: The skyc q.choice_set.create(choice_textJust hacking again, votes0)c.question
Question: Whats up? q.choice_set.all()
QuerySet [Choice: Not much, Choice: The sky, Choice: Just hacking again]q.choice_set.count()
3 Choice.objects.filter(question__pub_date__yearcurrent_year)
QuerySet [Choice: Not much, Choice: The sky, Choice: Just hacking again]c q.choice_set.filter(choice_text__startswithJust hacking)c.delete() # delete() 删除对象
(1, {polls.Choice: 1})上面是官方文档提供的一些例子还有更多的有关 API 的操作我们将在后面学习到。
总结
1、创建对象q Question.objects.all() # QuerySet 对象集合
q Question.objects.filter() # QuerySet 对象集合
q Question.objects.get() # QuerySet 对象一个2、插入数据q Question(question_textWhats up?, pub_datetimezone.now()) # 方法一
q.save()访问数据q.idq.pub_dateQuestion.objects.create(question_textWhats up?, pub_datetimezone.now()) # 方法二3、查询数据q Question.objects.get(id1) # 通过 q.数据表名_set.all() 方式获得与其关联的数据表对象
q.choice_set.all() # QuerySet [Choice: Not much, Choice: The sky]4、删除数据
q.delete()2.4 后台管理 Admin
Django 为我们提供了一个后台管理工具 Admin可以对数据进行简单的增删改查等简单易用并支持拓展。
创建管理员用户
python manage.py createsuperuser # 运行命令新建用户名、邮箱和密码
# username: xxx
# email:xxxqq.com
# password:xxx注册应用
将模型中的类注册到 polls/admin.py 中接收站点的管理
from django.contrib import admin
from polls.models import Question, Choiceadmin.site.register(Question)
admin.site.register(Choice)访问 Admin
访问 http://127.0.0.1:8000/admin/输入刚才创建的用户名和密码 样式定制
修改 polls/admin.py
from django.contrib import admin
from polls.models import Question, Choice# 定制样式更多样式见官方文档
class QuestionAdmin(admin.ModelAdmin):list_display (id, question_text, pub_date) # 要显示的字段list_editable (question_text, pub_date) # 可编辑的admin.site.register(Question, QuestionAdmin)
admin.site.register(Choice)3. 模板和视图
3.1 编写视图函数
Django 中每一个网页都是通过视图函数来处理的在 polls 应用中我们将创建以下四个视图
URL视图函数模板说明/index/index()index.html主页显示最新问题/results/results()results.html投票结果/detail/detail()detail.html问题详细描述/vote/vote()vote.html投票动作是否投票
首先我们配置好 mysite/urlconf以便能够找到相应视图函数
from django.contrib import admin
from django.urls import path, include
from polls import viewsurlpatterns [path(admin/, admin.site.urls),path(index/, views.index, nameindex),path(detail/, views.detail, namedetail),path(results/, views.results, nameresults),path(vote/, views.vote, namevote),
]编写视图 polls/views.py
from django.shortcuts import render, HttpResponsedef index(request):首页return HttpResponse(Is Ok!)def detail(request):问题详细描述return HttpResponse(问题详细描述)def results(request):投票结果return HttpResponse(投票结果)def vote(request):是否投票return HttpResponse(是否已经投票)现在视图函数已经创建好了我们可以访问相应视图看看 http://127.0.0.1:8000/detail/ 返回的是什么。
3.2 使用模板
3.2.1 创建模板
在上面的视图函数中我们使用了 HttpResponse 对象返回了一个字符串而实际开发中我们得到的都是一个 HTML页面。这就需要用到我们的模板系统了。
在 polls 目录下创建一个 templates 目录再在 templates 目录下创建一个新的 polls目录。然后在 polls 中创建相应的模板文件其路径polls/templates/polls/如index.html/detail.html 等。 为什么要再多创建一个 polls 目录
当有另一个 app 也有 index.html 时可以避免 Django 匹配错误。
配置 templates
要想 Django 能找到 templates 中的模板文件那么还要配置下 settings
# 当 templates 在 mysite/templates 下不要添加 polls
TEMPLATE_DIRS (os.path.join(BASE_DIR, polls, templates),) TEMPLATES [{BACKEND: django.template.backends.django.DjangoTemplates,DIRS: [os.path.join(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,],},},
]3.2.2 渲染模板
渲染模板Django 为我们提供了一个 render() 函数用于渲染模板文件render()语法格式
render(request, template_name, contextNone) # 三个参数第一个固定为请求对象request第二个是要渲染的模板文件第三个是个可选参数即要传递的数据是个字典格式编辑 polls/views.py
from django.shortcuts import render, HttpResponse
from .models import Questiondef index(request):首页question_list Question.objects.all() # 取出 Question 中所有 question return render(request, polls/index.html, {question_list: question_list})def detail(request, question_id):问题详细描述question Question.objects.get(idquestion_id)return render(request, polls/detail.html, {question: question})当我们访问 http://127.0.0.1:8000/index/ 时index() 函数会处理我们的视图。它从 Question 取出所有的问题对象并渲染到模板中。
创建模板文件 polls/templates/polls/index.html
!--index.html--
!DOCTYPE html
html langen
headmeta charsetUTF-8titleTitle/title
/head
body{% for question in question_list %}!-- 相当于访问 a hrefdetail/1//a--lia href{% url detail question.id %}{{ question.question_text }}/a /li{% endfor %}
/body
/html在模板文件 index.html 中我们使用 for 循环将所有问题循环当我们点击其中的 a 标签的链接时将会被定位到 http://127.0.0.1:8000/detail/1 中。
模板文件 polls/templates/polls/detail.html
!DOCTYPE html
html langen
headmeta charsetUTF-8titleDetail/title
/head
bodyh1{{ question.question_text }}/h1ul{% for choice in question.choice_set.all %}li{{ choice.choice_text }}/li{% endfor %}/ul
/body
/html配置 mysite/urls.py
from django.contrib import admin
from django.urls import path, include
from polls import viewsurlpatterns [path(admin/, admin.site.urls),path(index/, views.index, nameindex),# 我们将 detail/ 修改为 detail/int:question_id以可匹配 http://127.0.0.1:8000/detail/1 这样的路径path(detail/int:question_id, views.detail, namedetail),
] 在这里我们将 detail/ 修改为 detail/int:question_id以可匹配 http://127.0.0.1:8000/detail/1 这样的路径。其中 int: question_id 将匹配到一个正整数另外不要忘了在视图函数中也要接收相应 question_id
def detail(request, question_id):问题详细描述question Question.objects.get(idquestion_id)return render(request, polls/detail.html, {question: question})这里我们用的是 Django 提供的模板语言将数据库中的数据显示在页面上后面将详细介绍。 3.3 返回 404 错误
当我们访问不存在的路径时会返回一个 Http404我们可以定制下让其返回我们想要的内容编辑 polls/views.py
from django.http import Http404
from django.shortcuts import render
from .models import Questiondef detail(request, question_id):try:question Question.objects.get(pkquestion_id)except Question.DoesNotExist:raise Http404(Question 不存在)return render(request, polls/detail.html, {question: question})另外 Django 也为我们提供了一个快捷函数 get_object_or_404()只需一行即可替代上面多行
from django.shortcuts import get_object_or_404, render
from .models import Questiondef detail(request, question_id):question get_object_or_404(Question, pkquestion_id) # 第一个参数模型第二个任意关键字return render(request, polls/detail.html, {question: question})get_object_or_404()替代的是 get() 方法get_list_or_404()替代的是 filter() 方法
3.4 URL 命名空间
什么是 URL 的命名空间呢就是给每一个 URL 路径添加一个 别名它有如下几点好处
当有多个 app 时可以更好地区分是哪个 app 的路径避免硬编码在上面 index.html 中我们使用的就是 URL 命名空间而不是 a href/detail/{{question.id}} 这样的硬编码。这样在我们修改匹配方法时不需要做大量的修改。
添加命名空间
from django.contrib import admin
from django.urls import path, include
from polls import viewsurlpatterns [path(admin/, admin.site.urls),path(index/, views.index, nameindex), # 其中 nameindex 即为 URL的 命名空间path(detail/int:question_id, views.detail, namedetail),
]当有多个应用时
当有多个应用时我们只需在 urls.py 中添加一个 app_name 并在使用时带上它即可
...
app_name polls # 添加这行
urlpatterns [path(admin/, admin.site.urls),path(index/, views.index, nameindex), # 其中 nameindex 即为 URL的 命名空间path(detail/int:question_id, views.detail, namedetail),
]使用时一定要记得带上 app_name
lia href{% url polls:detail question.id %}{{ question.question_text }}/a/li4. 表单和通用视图
在创建表单之前我们先来分析下程序的整体运行流程
访问首页 index将所有问题都显示出来点击问题跳转到 detail显示详细问题并显示投票选项当用户投票后跳转到 results 结果页面并询问是否还要继续投票。
从流程中可以看出我们要在问题详细页面提供单选框以供用户选择下面我们来创建第一个表单
4.1 Form 表单
编写 polls/detail.html
!DOCTYPE html
html langen
headmeta charsetUTF-8titleDetail/title
/head
body
!--问题--
h1{{ question.question_text }}/h1!-- 错误信息 --
{% if error_message %}p{{ error_message }}/p
{% endif %}form action{% url vote question.id %} methodpost{% csrf_token %} !--csrf 攻击表单提交必须带上这个--!-- 通过 question.choice_set.all 获得所有 Choice 选项 --{% for choice in question.choice_set.all %} !--choice1、choice2--input typeradio namechoice idchoice{{ forloop.counter }} value{{ choice.id }}label forchoice{{ forloop.counter }}{{ choice.choice_text }}/label{% endfor %}!-- 提交 --input typesubmit valuevote
/form
/body
/html在上面 detail.html 模板文件中我们创建了一个表单当用户点击提交时会被提交到 action 对应的 URL 中去。在表单中我们通过 question.choice_set.all 获得所有 Choice 选项并循环它。再定义了一个单选框 radio提交到服务器的键为 choice值为选项的 id。另外要注意的是 form 表单发送 post 请求时务必带上 {% csrf_token %}否则将被禁止提交。
配置 mysite/urls.py
# /index/
path(index/, views.index, nameindex),
# /detail/1/
path(detail/int:question_id, views.detail, namedetail),
# /results/1/
path(results/int:question_id, views.results, nameresults),
# /vote/1/
path(vote/int:question_id, views.vote, namevote),编写 polls/views.py
from django.shortcuts import render, HttpResponse, get_object_or_404, redirect
from .models import Question, Choice
from django.http import HttpResponseRedirect
from django.urls import reversedef vote(request, question_id):处理投票print(question_id)question get_object_or_404(Question, idquestion_id)try:choice_id request.POST.get(choice, None)print(choice_id)selected_choice question.choice_set.get(idchoice_id)except (KeyError, Choice.DoesNotExist):# choice 没找到重新返回表单页面并给出提示信息return render(request, polls/detail.html, {question: question, error_message: 你没用选择选项})else:selected_choice.votes 1selected_choice.save()ret reverse(results, args(question.id,)) # /results/1return HttpResponseRedirect(ret)question_id 为问题所对应的 id在 detail.html 模板中我们将选项的 id 提交到了后台通过 request.POST.get(choice) 我们可以获得用户选择的选项 id当没有对应的 choice_id 时重新返回表单页面并给出错误信息当有相应 choice_id 时对应 vote 则加 1最后重定向到投票结果页面 results。
编写 polls/results.html
!DOCTYPE html
html langen
headmeta charsetUTF-8title结果/title
/head
bodyh1{{ question.question_text }}/h1ul{% for choice in question.choice_set.all %}li{{ choice.choice_text }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}/li{% endfor %}/ula href{% url detail question.id %}Vote again?/a
/body
/html至此一个简单的公共投票系统已大致编写完成以下为演示 4.2 通用视图
在视图 polls/views中我们写了大量的类似于 index() 的重复代码存在冗余问题。
Django 为我们提供了一种 通用视图系统将常见的模式抽象画可以删去很多冗余代码。为此我们需要以下三个步骤
转换 urlconf删除一些旧的、不需要的视图基于通用视图引入新的视图
转换 URLconf
编辑 mysite/urls.py
urlpatterns [path(admin/, admin.site.urls),path(index/, views.IndexView.as_view(), nameindex),path(detail/int:pk, views.DetailView.as_view(), namedetail),path(results/int:pk, views.ResultsView.as_view(), nameresults),path(vote/int:question_id, views.vote, namevote),
]在这里我们将 question_id 修改为 pk这是因为通用视图从 url 中匹配的将是主键 pk。
修改视图
from django.views import genericclass IndexView(generic.ListView):template_name polls/index.html # 模板名称context_object_name question_list # 返回给模板的变量def get_queryset(self):return Question.objects.all()class DetailView(generic.DetailView):model Question # 模型template_name polls/detail.htmlclass ResultsView(generic.DetailView):model Questiontemplate_name polls/results.htmldef vote(request, question_id):passListView显示对象的列表DetaiView显示特定类型对象详细页面context_object_name返回给模板的变量{question_list:question_list} 中的 question_listDetaiView匹配的是 URL 中的 pk 主键template_name返回的模板文件格式为 app_name/model name_list.html
更多有关通用视图https://docs.djangoproject.com/zh-hans/2.1/topics/class-based-views/
5. 测试
测试是实际开发中不可或缺的一部分它可以
检验程序是否符合预期及时发现问题节省开发时间更有利团队合作等
测试分为手动测试和自动测试手动测试往往费时费力效率低下。我们可以借助一些测试模块如TestCase自动帮我们完成测试工作Django也有自动测试程序它也是基于 TestCase 模块来实现的。
在模型 models.py 中我们给 Question 定义了一个 was_published_recently() 方法用于返回问题是否是最近发布的当 Question 在最近一天发布时返回 True。
class Question(models.Model):数据表问题表question_text models.CharField(max_length2000) # 问题内容pub_date models.DateTimeField(date published) # 发布日期def __str__(self):return self.question_textdef was_published_recently(self):# 当前时间减去前一天与问题发布时间比较return self.pub_date timezone.now() - datetime.timedelta(days1)5.1 验证 bug
进入 Django shell 环境 import datetimefrom django.utils import timezonefrom polls.models import Question# 创建一个在发布日期 30 天后的问题对象future_question Question(pub_datetimezone.now() datetime.timedelta(days30))# 测试返回值发现也是 Truefuture_question.was_published_recently()
True我们创建了一个在发布日期 30 天后的问题测试发现还是返回 True也就是说这里被允许在未来时间发布问题这就是个 bug。
5.2 测试 bug
编写 polls/tests.py
from django.test import TestCase
import datetime
from django.utils import timezone
from .models import Questionclass QuestionModelTests(TestCase):def test_was_published_recently_with_future_question(self):# 创建一个 pub_date 是未来30天后的 Question 示例然后检查 was_published_recently() 的返回值它应该是 Falsetime timezone.now() datetime.timedelta(days30)future_question Question(pub_datetime)self.assertIs(future_question.was_published_recently(), False)执行 python manage.py test polls会看到结果
Creating test database for alias default...
System check identified no issues (0 silenced).
FFAIL: test_was_published_recently_with_future_question (polls.tests.QuestionModelTests)
----------------------------------------------------------------------
Traceback (most recent call last):File E:\Python_virtualenvs\for_django\Projects\mysite\polls\tests.py, line 11, in test_was_published_recently_with_future_qu
estionself.assertIs(future_question.was_published_recently(), False)
AssertionError: True is not False----------------------------------------------------------------------
Ran 1 test in 0.016sFAILED (failures1)
Destroying test database for alias default...我们创建了一个 pub_dae 值为 30 天后的 Question 实例用 assertls() 方法判断是否返回 False结果发现返回 True。
5.3 修改 bug
我们要让 pub_date 是未来某天时 Question.was_published_recently() 返回 False修改 polls/models.py
def was_published_recently(self):now timezone.now()return now - datetime.timedelta(days1) self.pub_date now再进行测试发现测试通过。测试在项目开发中很重要也很常用在这里我们只是做个大概的了解到后面再详细的探讨。
6. 静态文件
静态文件即 Web 应用程序所要用到的一些必要文件如图片、JS 脚本、CSS 样式等。一个完整的 Web 应用应该有自己独立静态文件、模板文件也就是说需要和项目本身区分开。
在应用 polls 下新建一个 static 的目录再新建一个以应用名字为名的文件夹最后再分类存储各种静态文件其目录结构是这样的 配置静态文件
与模板 templates 一样再使用前需要先配置好静态文件这样 Django 才能找到编辑 settings.py
STATIC_URL /static/
STATICFILES_DIRS (os.path.join(BASE_DIR, polls, static),
) # 一定不要忘记最后的逗号使用静态文件
在 polls/static/polls/ 下创建一个 images 目录用来存储图片再创建一个 css 目录用来存储 CSS 文件。然后在新建一个 style.css 的文件。
下面我们来给首页 index.html 添加背景图片编写以下代码
li a{color: red;
}body {background: white url(images/2.png) no-repeat;
}然后在 index.html 中来加载 style.css 文件
{% load static %} !--引入 static--
!DOCTYPE html
html langen
headmeta charsetUTF-8titleTitle/title!--再把 style.css 加载进来 --link relstylesheet href{% static polls/css/style.css %}
/head
body{% for question in question_list %}lia href{% url detail question.id %}{{ question.question_text }}/a /li{% endfor %}
/body
/html我们再刷新下发现已经给首页添加好了背景图片。除此之外我们还可以在模板文件中直接使用静态文件如在模板中使用 jQuery
# 同样地也要先引入 static
{% load static %}
script src{% static polls/js/jquery-3.1.1.js %}/script