复习第一步,把之前做好的内容,包括代码、模板之类,都放在一起的文件夹,给删了,重新开始!
建立项目
重新开始第一件事,以规范的方式对项目进行描述,再建立虚拟环境,以便在其中创建项目。
创建项目
那么,要制定的规范是这样的,完全按照教程上的规范来,不是我自己想的,但要按照这上面的执行,它如是说:
我们要编写一个名为“学习笔记”的Web应用程序,让用户能够记录感兴趣的主题,并在学习每个主题的过程中添加日志条目。“学习笔记”的主页对这个网站进行描述,并邀请用户注册或登录。用户登录后,就可创建新主题、添加新条目以及阅读既有的条目。
怎么样?记住了吗?这里我们发现,单靠这一章的内容似乎还不足以实现这上面的全部内容啊?那是因为还要结合下一章的内容才足够,这一章就学习了这一章的内容就行了。
建立虚拟环境
新建一个目录,命名learning_log,使用命令行窗口在该目录(文件夹)使用如下命令创建虚拟环境:python -m venv ll_env
使用命令后出现了一个新的文件夹ll_env,文件夹还有个Scripts文件夹在之后会用到
激活虚拟环境
在命令行窗口使用这一命令激活虚拟环境:
ll_env\Scripts\activate
安装Django
激活虚拟环境后就可以安装Django,需要注意的是,似乎是因为虚拟环境具有独立性,因此新建一个项目后是把Django安装到项目中,并不像pip一样是安装到python之中,以后还可以用的,而是只能在这个项目中用。
安装Django时,我使用了官网上给的命令。
py -m pip install Django==5.0.6
为了安装Django,这里花费了很多时间,总是下载失败,也许是现在的网络环境下载Django等软件并不方便,建议下载之后不要轻易删除,并且注意这些软件总是不断更新换代,在安装上要注意版本和安装手段的更新。
在Django中创建项目
执行如下命令来新建一个项目,注意有个句点不要忽略
django-admin startproject learning_log .
dir
dir learning_log
第一个命令新建了一个名为learning_log的项目,包含了5个文件,还创建了一个文件manage.py,这个文件有大用,它接受命令并将其交给Django的相关部分去运行。我们将使用这些命令来管理诸如使用数据库的运行服务器等任务。dir是用来检查文件夹里有些什么文件的,并不操作什么。
创建数据库
我们需要创建一个数据库,依然是在虚拟环境,命令行窗口中,执行下面的命令:
python manage.py migrate
这个命令叫做迁移数据库,在这里它创建了一个文件db.sqlite3,这就是我们新建的数据库
查看项目
执行命令runserver,来查看一下创建好的项目
python manage.py runserver
可以看到,这个命令里使用了manage.py,这说明了什么,说明我们用这个文件启动了服务器,这就是这个文件第一次发挥作用。
输入URL:http://localhost:8000/,Congratulations!尽管网页上没啥实质性内容,但是会显示你已经成功创建了项目。由此创建项目这一步取得了成功,一张白纸已经准备好,准备开始涂画。
创建应用程序
再打开一个命令行窗口,激活虚拟环境,下面要开始在项目里加入应用程序了。执行如下命令:
python manage.py startapp learning_logs
这一命令让Django建立创建应用程序所需的基础设施。我们可以直接看到的是,项目中新建了一个文件夹learning_logs,比较重要,之后会用到的是models.py,admin.py,views.py。
定义模型
模型方面,要用到的是models.py,所谓模型就是一个类,这个文件中把我们要用来的类规定了出来。
我们来创建一个新的类,它名为Topic,被用于创建主题,将用这个类来创建主题的数据,它的特性我们将写在代码中:
class Topic(models.Model):
'''用户学习的主题'''
text = models.CharField(max_length=200)
date_added = models.DateTimeField(auto_now_add=True)
def __str__(self):
'''返回模型的字符串表示'''
return self.text
在对models.py进行更新,添加新的类时犯了一个错误:将文章里写好的代码复制黏贴到文件中后,制表符被四个空格所替代,使得缩进错误程序无法运行。因此应当注意代码复制黏贴后会出现的这种情况。
激活模型
要使用模型,必须让Django将应用程序包含到项目中。为此,打开setting.py,将前面的应用程序添加到INSTALLED_APPS的列表当中:
--snip--
INSTALLED_APPS = [
--snip--
'django.contrib.staticfiles',
# My apps
'learning_logs',
]
--snip--
添加完成后,使用命令makemigrations来修改数据库,使用该命令后将创建一个名为0001——initial.py的迁移文件,这个文件将在数据库中为模型Topic创建一个表。
python manage.py makemigrations learning_logs
接下来依然是使用“创建数据库”中使用过的命令,进行迁移数据库,此时不再是创造数据库,而是更新数据库。
python manage.py migrate
每当需要修改“学习笔记”管理的数据时,都采取如下三个步骤:修改models.py;对learning_logs调用makemigrations;让Django迁移项目。
Django管理网站
现在开始建立一个管理网站,这个网站被用来处理模型。管理网站将仅限管理员使用。
超级用户(superuser)是具备有全部权限的用户,也是网络题材中非常火热的概念。管理员同时也是超级用户。为创建超级用户,需执行以下命令:
python manage.py createsuperuser
这个命令后会要求我们输入用户名、邮箱(可为空)、两次输入密码,以创建用户。我这里输入密码时密码是隐形的,看不到自己输入了什么。若两次输入密码相同系统会对密码进行判定,判定其太短/简单/经典,进行选择审核通过创建用户即可。
前面我们创建的模型Topic还未导入到管理网站,在admin.py中进行模型的注册:
from django.contrib import admin
from learning_logs.models import Topic
admin.site.register(Topic)
注册完成后,我们可以使用超级用户账户访问管理网站了,对网站http://localhost:8000/admin/进行访问即可。网站上可以添加和修改用户和用户组,还可以管理与刚刚的模型Topic相关的数据。
这里就创建两个新主题,Chess和Climbing吧。
定义模型Entry
定义一个新的模型Entry,这个模型用于让用户在学习笔记中添加条目。要注意的是,每条条目都关联一个主题,条目与主题有多对一关系。下面给出模型Entry的代码:
class Entry(models.Model):
'''学到的有关某个主题的具体知识'''
topic = models.ForeignKey(Topic,on_delete=models.CASCADE)
text = models.TextField()
date_added = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name_plural = 'entries'
def __str__(self):
'''返回模型的字符串表示'''
return self.text[:50] + "…"
迁移模型Entry
在添加新模型后,再次迁移数据库。继续这个流程:修改models.py,执行命令python manage.py makemigrations app_name,再执行命令python manage.py migrate
向管理网站注册Entry
我们还需要注册模型Entry。因此修改admin.py成如下
from django.contrib import admin
# Register your models here.
from learning_logs.models import Topic,Entry
admin.site.register(Topic)
admin.site.register(Entry)
此时在管理网站中出现Entries,可以添加条目,并且创建的条目需要关联到一个主题
创建网页:学习笔记主页
虽然已经建立了管理网页,但事实上我们还没有主页。本节来学习创建网页,通常分三个阶段:定义URL、编写视图、编写模板。
细节分析一下,第一步定义URL模式,URL模式描述了URL是如何设计的,让Django知道如何将浏览器请求与网站URL匹配,以确定返回哪个网页。接着第二步,每个URL都被映射到特定的视图——视图函数获取并处理网页所需的数据。接着第三步,视图函数调用一个模板,由模板生成浏览器能够理解的网页。
URL
我们已经有了基础URL(http://localhost:8000/),这个返回默认的Django网站,现在我们修改一下把它映射到主页去。
打开项目主文件夹learning_log,里面有个urls.py文件,这个文件管理着URL。我们在其中添加一行代码,修改完后如下所示:
from django.contrib import admin
from django.urls import path
urlpatterns = [
path('admin/', admin.site.urls),
path('',include(('learning_logs.urls','learning_logs'),namespace='learning_logs')),
]
在代码中有一个实参namespace,这让我们能够将learning_logs的URL同项目中其它的URL区分开来,这在我们需要扩展项目时会非常的有帮助。
下一步,我们在文件夹learning_logs中创建另一个urls.py文件,我们此时应当还记得learning_logs文件夹是一个应用程序。创建的urls.py代码如下所示,为了与主文件夹中的文件区分添加一个注释
"""定义learning_logs的URL模式"""
from django.urls import path
# 从当前的urls.py所在文件夹导入views
from . import views
app_name = 'learning_logs'
# 包含可在应用程序learning_ logs中请求的网页
urlpatterns = [
# 主页
path('', views.index, name='index'),
]
我们导入了模块views,这是用来导入视图的,这个文件在之后会用到。变量urlpatterns是一个列表,包含可在应用程序learning_logs中请求的网页,在这里似乎用来放入了主页。
编写视图
视图函数接受请求中的信息,准备好生成网页所需的数据,再将这些数据发送给浏览器——这通常是使用定义了网页是什么样的模板实现的。
视图函数的文件views.py放在了应用程序的目录中,这是在执行python manage.py startapp时自动生成的
在文件中添加视图函数,作用是令urls.py文件调用,URL会映射到视图,而视图函数调用模板,生成网页所需的数据,修改后的视图文件如下:
from django.shortcuts import render
#在这里创建视图
def index(request):
'''学习笔记的主页'''
return render(request, 'learning_logs/index.html')
编写模板
模板定义了网页是什么样子的,而数据则由数据库提供。在文件夹learning_logs中再建立一个文件夹templates,然后在里面再建立一个文件夹learning_logs,在里面放模板。先创建一个模板文件index.html,代码如下:
<p>Learning Log</p>
<p>Learning Log helps you keep track of your learning, for any topic you're
learning about.</p>
三个步骤完成后,我们成功完成了项目的主页,请求基础URL即可看到
创建其他网页
现在运用上一节的方法扩充项目,这里将再创建两个显示数据的网页,一个负责列出主题,一个显示特定主题的所有条目。
模板继承
创建一个父模板base.html
<p>
<a href="{% url 'learning_logs:index' %}">Learning Log</a>
</p>
{% block content %}{% endblock content %}
现在重新编写index.html,使其继承base.html
显示所有主题的页面
现在开始制作显示所有主题的页面,使用前文的三个流程进行制作。
首先是URL模式,修改learning_logs/urls.py:
urlpatterns = [
# 主页
path('', views.index, name='index'),
# 显示所有的主题
path('topics/', views.topics, name='topics'),
]
然后视图文件中,编写一个新的视图函数,利用函数topics从数据库中获取数据,再通过模板使其显示(别忘了从库里引入Topic类):
from .models import Topic
def topics(request):
'''显示所有的主题'''
topics = Topic.objects.order_by('date_added')
context = {'topics': topics}
return render(request, 'learning_logs/topics.html', context)
新的页面需要新的模板,命名为topics.html,它接受字典context以便能够使用topics()提供的数据:
{% extends "learning_logs/base.html" %}
{% block content %}
<p>Topics</p>
<ul>
{% for topic in topics %}
<li>{{ topic }}</li>
{% empty %}
<li>No topics have been added yet.</li>
{% endfor %}
</ul>
{% endblock content %}
现在修改父模板吧,使主页能够链接到显示所有主题的页面:
<p>
<a href="{% url 'learning_logs:index' %}">Learning Log</a> -
<a href="{% url 'learning_logs:topics' %}">Topics</a>
</p>
{% block content %}{% endblock content %}
完成,我们完成了显示所有主题的页面。
显示特定主题的页面
这个网页稍微复杂点:
URL上药利用主题的id属性:
# 特定主题的详细页面
re_path(r'^topics/(?P<topic_id>\d+)/', views.topic, name='topic'),
视图函数更加复杂一点:
def topic(request, topic_id):
'''显示单个主题及其所有的条目'''
topic = Topic.objects.get(id=topic_id)
entries = topic.entry_set.order_by('-date_added')
context = {'topic': topic, 'entries': entries}
return render(request, 'learning_logs/topic.html', context)
模板需要显示主题的名称和条目的内容:
{% extends "learning_logs/base.html" %}
{% block content %}
<p>Topic:{{ topic }}</p>
<ul>
{% for entry in entries %}
<li>
<p>{{ entry.date_added|date:'M d, Y H:i'}}</p>
<p>{{ entry.text|linebreaks }}</p>
</li>
{% empty %}
<li>
There are no entries for this topic yet.
</li>
{% endfor %}
</ul>
{% endblock content %}
最后修改一下topics.html ,让每个主题都链接到相应的网页,这样可以从主题链接来看条目:
{% extends "learning_logs/base.html" %}
{% block content %}
<p>Topics</p>
<ul>
{% for topic in topics %}
<li>
<a href="{% url 'learning_logs:topic' topic.id %}">{{ topic }}</a>
</li>
{% empty %}
<li>No topics have been added yet.</li>
{% endfor %}
</ul>
{% endblock content %}
这一章的内容到此完成。