Personal study notes, refer to the official django documentation: https://docs.djangoproject.com/zh-hans/3.2/This
article is published on my personal blog: https://sunguoqi.com/2021/12/10/Django_02 /
Article directory
1. Automated testing
To test your code is to check that your code works (nonsense)
To be honest, so far, I have written programs to run --> report errors --> then look at the error messages --> print
input and output to test. But the project is a whole project after all, so the test is too unprofessional.
Automated testing has the following advantages:
- Testing will save you time
- Testing not only finds bugs, but prevents them
- Tests make your code more attractive
- Testing facilitates teamwork
Sounds good, then try it!
1. First, there must be a bug
Following this application logic we wrote earlier, when we visit index
this page, we should get the five most recently posted votes, if there are five.
But now there is a small bug that if our vote is scheduled to be released tomorrow, our idea is that users can only see this vote tomorrow, the index
page should not display this data, but according to the current logic, index
it will be displayed immediately. Article data.
注意
: The above description is indeed a bug, but there is another important bug, that is, when we wrote the data model before, we did not define any method to display the data within one day. Forgive me for not seeing this requirement: Question was posted within a day.
Below is the current state of the model layer.
# django框架的接口模块,默认已经引入
from django.db import models
import datetime
from django.utils import timezone
# Create your models here.
# 创建了一个“问题”类(表),表里有两个字段。
class Question(models.Model):
# 问题描述字段
question_text = models.CharField(max_length=200)
# 创建日期字段
pub_date = models.DateTimeField('date published')
def was_published_recently(self):
return self.pub_date >= timezone.now() - datetime.timedelta(days=1)
# python魔法方法,显示调用该对象的时候的返回内容
def __str__(self):
return self.question_text
# 创建了一个选项类(表),表中包含三个字段。
class Choice(models.Model):
# 这个表里定义了一个外键字段,因为一个问题可以有多个选项,每个问题对应每个问题的选项。
question = models.ForeignKey(Question, on_delete=models.CASCADE)
# 选项描述字段
choice_text = models.CharField(max_length=200)
# 是否选取字段
votes = models.IntegerField(default=0)
# python魔法方法,显示调用该对象的时候的返回内容
def __str__(self):
return self.choice_text
2. Expose this bug
The text description of this BUG is indeed a bit pale. Let's use the python
manage.pyshell
command to expose this BUG.
Open the terminal in the project root directory and enter python manage.py shell
into the interactive compilation environment.
>>> import datetime
>>> from django.utils import timezone
>>> from polls.models import Question
>>> # 创建了一个实例对象,他的时间是未来的。
>>> future_question = Question(pub_date=timezone.now() + datetime.timedelta(days=30))
>>> # 会公开近期投票吗?
>>> future_question.was_published_recently()
True
Obviously now the application will open future votes, so we have to fix this bug, oh right, this is not an automated test, we are just testing it in an interactive environment, we should write it into a file, when the project runs, Execute automated tests.
3. Automated testing
By convention, tests for Django applications should be written in the application's tests.py
files . The test system will automatically find and execute test code in all files tests
starting with .
polls/tests.py
# Django自带的测试接口,默认已经引入
from django.test import TestCase
# Create your tests here.
# 引入datatime模块
import datetime
from django.utils import timezone
# 引入我们的数据表
from .models import Question
class QuestionModelTests(TestCase):
def test_was_published_recently_with_future_question(self):
"""
未来的一个时间他的返回值应该是False
"""
time = timezone.now() + datetime.timedelta(days=30)
future_question = Question(pub_date=time)
self.assertIs(future_question.was_published_recently(), False)
4. Run the test
Execute test command in terminalpython manage.py test polls
PS J:\study_django\mysite> python manage.py test polls
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
E
======================================================================
ERROR: test_was_published_recently_with_future_question (polls.tests.QuestionModelTests)
未来的一个时间他的返回值应该是False
----------------------------------------------------------------------
Traceback (most recent call last):
File "J:\study_django\mysite\polls\tests.py", line 19, in test_was_published_recently_with_future_question
self.assertIs(future_question.was_published_recently(), False)
AttributeError: 'Question' object has no attribute 'was_published_recently'
----------------------------------------------------------------------
Ran 1 test in 0.003s
FAILED (errors=1)
Destroying test database for alias 'default'...
PS J:\study_django\mysite>
Here's how the automated test runs:
-
python manage.py test polls
will look for test code in thepolls
app -
It found a subclass of django.test.TestCase
-
It creates a special database for testing to use
-
It looks for test methods in the class - methods
test
starting with . -
In the
test_was_published_recently_with_future_question
method , it creates an instancepub_date
with a value of 30 days later .Question
-
Then use the
assertls()
method and find that itwas_published_recently()
returnsTrue
, and we expect it to returnFalse
.
5. Fix this bug
Should be returned when pub_date
is a future date . Modify the method in to only return if the date is in the past tense :Question.was_published_recently()
False
models.py
True
polls/models.py
...
def was_published_recently(self):
now = timezone.now()
return now - datetime.timedelta(days=1) <= self.pub_date <= now
...
6. More comprehensive testing
It's best to test the past, the recent, and the future. So modify the test code as follows.
# Django自带的测试接口,默认已经引入
from django.test import TestCase
# Create your tests here.
# 引入datatime模块
import datetime
from django.utils import timezone
# 引入我们的数据表
from .models import Question
class QuestionModelTests(TestCase):
def test_was_published_recently_with_future_question(self):
"""
未来的一个时间他的返回值应该是False
"""
time = timezone.now() + datetime.timedelta(days=30)
future_question = Question(pub_date=time)
self.assertIs(future_question.was_published_recently(), False)
def test_was_published_recently_with_old_question(self):
"""
最近一天的
"""
time = timezone.now() - datetime.timedelta(days=1, seconds=1)
old_question = Question(pub_date=time)
self.assertIs(old_question.was_published_recently(), False)
def test_was_published_recently_with_recent_question(self):
"""
过去的
"""
time = timezone.now() - datetime.timedelta(hours=23, minutes=59, seconds=59)
recent_question = Question(pub_date=time)
self.assertIs(recent_question.was_published_recently(), True)
7. Other solutions
Another solution is that we should not display future votes, then we should filter them out when the view is displayed 过去
and 未来
I have not continued to study this.
Second, the introduction of static files
First polls
, create a directory named under static
the directory. Django will look in this directory for static files, in a similar way to how Diango looks for templates in the polls/templates/
directory .
1. Create a new css style
Create a new style in the static file directory.
static/style.css
li a {
color: green;
}
2. Introduce static files
Introduce static files in templates.
index.html
{% load static %}
<link rel="stylesheet" type="text/css" href="{% static 'style.css' %}" />