Django 简介
Django 是一个 Web 框架,一套用于帮助开发交互式网站的工具,Django能够响应网页请求,还能让你更轻松地读写数据库、管理用户等。
1. 建立项目
建立项目时,首先需要以规范的方式对项目进行描述,再建立虚拟环境,以便在其中创建项目。
规范制定
规范制定将 阐述项目目标、功能,并讨论项目的外观和用户界面。
我们将编写一个名为“学习笔记”的Web应用程序,让用户能够记录感兴趣的主题,并在学习每个主题的过程中添加日志条目。“学习笔记”的主页对这个网站进行描述,并邀请用户注册或登录。用户登录后,可创建新的主题、添加新的条目以及阐述既有的条目。
建立虚拟环境
要使用 Django,首先需要建立一个虚拟工作环境。虚拟环境是系统的一个位置,你可以在其中安装包,并将其与其他Python包隔离。将项目的库与其他项目分离是有益的。
创建项目目录
为项目创建一个目录,并将其命名为 learning_log。
目录创建好之后,在终端进行打开。
终端打开后,录入命令创建虚拟环境
python -m venv ll_env
创建成功之后,目录下会有新的内容生成:
激活虚拟环境
这说明虚拟环境已经创建成功,但你还需要一个命令将他进行激活:
# 基于windoews系统的激活命令:
ll_env\Scripts\activate
#环境停止命令
deactivate
命令执行后:
安装 Django
虚拟环境创建激活后,安装Django.
Django 安装在虚拟环境当中,当命令行窗口处于上一步的截图状态时,我们继续录入下述命令:
pip isntall Django==1.11
由于我们在虚拟环境中进行工作,因此在所有的系统中,安装Django的命令都不相同;不需要指定标志 --user ,也无需使用 python -m pip install package_name 这样较长的命令。
哦!对! 不要忘记 Django 仅在虚拟环境处于活动状态时才可使用。
在 Django 中创建项目
在虚拟环境处于激活状态下,执行下述命令进行项目创建。
#创建项目
django-admin.py startproject learning_log .
#上行命令当中 末尾的句点是一定要写的,他会保证你创建的项目会按照合适的目录结构构建
#dir 查看
dir
dir lerning_log
进行到这里的时候出了一个Bug,之前没有显示,但是 dir查看文件内容的时候并没有出现该有的文件。
报错信息给大家看一下:
查了一下原因,应该是版本导致的,3.10以后停掉了这个库,所以掉不到,会报错,我又装了一个3.9版本的python。
在这里我重走一下流程…
换成 3.9 版本之后构建没有报错:
还可以通过命令查看创建的项目结构都涵盖哪些信息:
#基于windoews系统
dir learning_log
运行如下:
如图,它包含了四个文件。
其中重要的是:settings.py、urls.py、wsgi.py。settings.py:指定Django如何与你的系统交互以及如何管理项目。
urls.py:告诉Django应创建哪些网页来响应浏览器请求。
wsgi.py:帮助Django提供它创建的文件。文件名称为: web server gateway interface
创建数据库
Django 将大部分与项目相关的信息都存储在数据库中,因此我们需要创建一个供Django使用的数据库。
为给项目“学习笔记” 创建数据库,在处于激活状态下的虚拟环境中执行命令:
python manage.py migrate
…又报错了
traceback Generator expression must be parenthesized
traceback Generator expression must be parenthesized
查了一下,又是版本问题。这次是 Django 版本导致的。
解决如下:
找到对应报错的这个文件。打开之后,找到 151行
保存更改内容关闭文件,
回到命令窗口,
回滚一下刚才的创建数据库命令,并执行。
我这里没有报错。
如果你们还不行,可以尝试一下更新 Django的版本。
更新命令:
pip install -U Django
这里其实涉及到了 SQLite 的新知识点。
我自己也没有接触过,不涉及太多声明了,文章主旨在Django的使用,所以这一点就不花费太多精力了。
查看项目
核验查实项目是否正确创建,可以通过命令进行:
python manage.py runserver
Django 启动一个服务器,让我们能够查看系统中的项目,了解它们的工作情况。当我们在浏览器中录入URL以请求网页时,该Django服务器将进行响应:生成合适的网页,并将其发送给浏览器。
打开浏览器,录入:
http://localhost:8000/
如视此图,表明一切进行顺利。且,当前界面是Django创建的。
现在暂时不要关闭当前这个服务器。
如需关闭:Ctrl + C 进行关闭。
2. 创建应用程序
Django项目由一系列应用程序组成,它们协同工作,让项目成为一个整体。我们暂时只创建了一个应用程序,当然后续还会根据需要创建新的应用程序。
当前,在页面打开的终端窗口中应该还运行着 runserver。
在打开一个终端窗口,并且切换到 manage.py 所在的目录。激活该虚拟环境,再执行命令startapp。
程序启动指令
# 先对虚拟环境进行激活
ll_env\Scripts\activate
#创建
python manage.py startapp learning_logs
#查看其内容
dir learning_logs
定义模型
现在需要考虑涉及的数据。每位用户都需要在学习笔记中创建很多主题,
用户输入的每个条目都与特定主题相关联,这些条目将以文本的方式显示。我们还需要存储每个条目的时间戳,以便用户能够知道每个条目大概在什么时间段创建。
打开 models.py,查看其包含内容。
from django.db import models
# Create your models here.
这里我们看到,这个类在创建时候就导入了 models模块。
该模块可以让我们创建自己的模型。
模型告诉 Django 如何处理应用程序当中的数据,在代码层面,模型就是一个类,包含属性和方法。
class Topic(models.Model):
#用户学习的主题
text = models.CharField(max_length=200)
date_added = models.DateTimeField(auto_now_add=True)
def __str__(self):
#返回模型的字符串表示
return self.text
两个报错
这里遇到了两个报错,因为没有即时记录,没办法更详细记录报错内容了。
使用命令创建数据库出现错误信息:ImportError
命令:
python manage.py migrate
报错信息:
from django.conf.urls import re_path as url
ImportError: cannot import name ‘re_path’ from ‘django.conf.urls’
解决方案:
根据报错信息,找到提示出现错误的urls.py文件,打开后手动更改其代码内容:
#源代码:
from django.conf.urls import url
#更改后:
from django.urls import re_path as url
更改保存之后,重新执行,可正常执行。
报错原因:
版本问题,原内容被废弃,不在生效。手动更改可执行内容,可正常使用。
模型定义完成之后运行报错:django.core.exceptions.ImproperlyConfigured: Requested setting INSTALLED_APPS, but settings…
很多之前的内容我们在本地就能直接进行测试,随着内容的逐渐深入,我们转换到 pygame中进行代码编写。
出现这个错误其实也是没有配置好其对应内容,配置步骤如下:
先设置好这里:
这是pygame本身的设置
然后在设置代码运行时候需要配置的内容。
设置步骤我尽量将图片截的清楚了,
至于环境变量的话,添加时点击旁边的小按钮,然后出现框框
在加号添加就可以了
DJANGO_SETTINGS_MODULE=learning_log.settings
设置好之后,只要本地服务是开好的,执行刚才定义好的模型,应该是可以成功测试的。
定义模型的测试效果
现在模型已经定义好了,两个报错解决了,我们在 pygame中运行模型看一下效果
有个成功起飞的小火箭
激活模型
要使用模型,必须让Django将应用程序包含到项目中。
打开 settings.py
位于目录:learning_log/learning_log中
其中,代码段负责 告诉 Django哪些应用程序安装在项目中:
#元组 INSTALLED_APPS 负责告诉 Django项目由哪些应用程序组成
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
现在我们要对其进行更改:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
#添入自己的项目
'learning_logs',
]
接下来,需要让Django修改数据库,使其能够存储与模型Topic相关的信息,
在终端录入命令:
#让Django确定如何修改数据库,使其能够存储与我们定义的新模型相关联的数据。
python manage.py makemigrations learning_logs
执行效果如下:
上述浮出的图腾部分是报错信息。
此报错是因为版本问题,Django 1.1 版本不支持该命令,需要我们升级。
如果你想升级到指定版本:
pip install --upgrade django==2.0
亦或者直接升级版本:
pip install --upgrade django
更新完成后,重新运行命令。
然后可以看到输出表名Django创建了一个名为 0001_initial.py 的迁移文件,这个文件将在数据库中为模型Topic创建一个表
我们继续利用这种迁移,让Django替我们修改数据库:
python manage.py migrate
命令执行完成后,我们需要检查的点:
Django 管理网站
为应用程序定义模型时,Django提供的管理网站(admin site)让我们能够轻松地处理模型。网站的管理员可使用管理网站,但普通用户不能使用。
创建超级用户
python manage.py createsuperuser
向管理网站注册模型
手工注册我们开发过程中用到的模型
创建learning_logs时,Django在models.py所在的目录中创建了一个名为:admin.py的文件。
打开并查看器文件 code:
from django.contrib import admin
# Register your models here.
# 在这里注册我们的模型
from learning_logs.models import Topic
admin.site.register(Topic)
这些代码导如我们要注册的模型Topic。
admin.site.register() 让 Django通过网站管理我们的模型
现在,我们使用超级用户访问管理网站
在浏览器中录入访问路径:
http://127.0.0.1:8000/admin/
访问之后出现下图界面:
然后接着录入我们刚才创建好的超级用户:
登录成功后如图:
添加主题
向管理网站注册Topic后,,我们来添加第一个主题。
点击 Topic 进入主题网页
我们添加主题:Chess 和 Rock Climbing
。。新惊喜来了
解决:no such table: main.auth_user__old
出现这个问题是因为Django在创建项目时已经创建了数据库表:
我们只需同步一下就可以正常继续上述添加操作了。
python manage.py migrate
重新创建超级用户
python manage.py createsuperuser
添加成功了!!
定义模型 Entry
在上步中,我们添加好了主题,如果要在对应的主题中添加对应的主题内容就需要为其定义模型。
然,每个条目都与特定主题相关联,这种关系叫多对一,即多个条目可关联到同一个主题。
#在模块 models.py中添加下述 code
class Entry(models.Model):
#将每个条目关联到特定主题
topic = models.ForeignKey(Topic,on_delete=models.CASCADE)
text = models.TextField()
date_added = models.DateTimeField(auto_now_add=True)
#嵌套 Meta 类
#用于管理模型的额外信息
class Meta:
verbose_name_plural = 'entries'
def __init__(self):
# 返货模型的字符串表示
return self.text[:50] + '...'
迁移模型 Entry
由于我们添加了一个新的模型,需要再次迁移数据库
python manage.py makemigrations app_name
python manage.py migrate
向管理网站注册 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)
注册完成后,运行查看:
测试:添加一个条目
save
点击 save后,返回到主条目管理页面。在管理页面中,只显示了条目的开头部分而不是所有文本。这就是使用 text[:50]作为条目的字符串表示的好处。
Django shell
输入一些数据后,就可以通过交互式终端会话以编程方式查看这些数据了。
这种交互式环境成为 Django shell
python manage.py shell
from learning_logs.models import Topic
Topic.objects.all()
Topic.object.all() 获取模型 Topic的所有实例;它返回一个列表,称为查询集。
我们可以像遍历列表一样遍历查询集。下面分配给每个主题对象ID
topics = Topic.objects.all()
for topic in topics:
print(topic.id,topic)
现在通过输出可知每个主题的id值了。
然后开始通过 id值来获取该对象并查看其任何属性
t = Topic.objects.get(id=1)
t.text
t.date_added
利用主题和键的关联关系,可以查看和主题有关的所有条目
t.entry_set.all()
3. 创建学习网页
Django创建网页的过程分为三个阶段:定义URL,编写视图和编写模板。
首先,需要定义好URL模式,URL模式描述了URL是如何设计的,让Django知道如何将浏览器请求与网站URL匹配,以确定返回哪个网页。
每个URL都被映射到特定的视图----视图函数获取并处理网页所需的数据。
映射URL
打开 learning_log中的urls.py文件:
#前两行导入了为项目和管理网站管理URL的函数和模块
from django.urls import re_path as url,include
from django.contrib import admin
#变量 urlpatterns 包含实参namespace
#让我们能够将 learning_logs的URL同项目中的其他URL区分开来
urlpatterns = [
#admin.site.urls 该模块定义了可在管理网站中请求的所有URL
url(r'^admin/', admin.site.urls),
]
我们需要包含 learning_logs 的URL
from django.urls import re_path as url,include
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'',include(('learning_logs.urls','learning_logs'),namespace='learning_logs')),
]
默认的URLurls.py包含在 learning_log 中,
现在我们需要在文件夹 learning_logs 中创建另一个urls.py 文件:
# learning_logs 中创建的urls.py文件
#添加该文档注释是为了清楚打开的urls.py所处位置
"""定义learning_logs的URL模式"""
# 函数 url用其将URL映射到视图
from django.urls import re_path as url
# 句点让python从当前的urls.py模块所在的文件中导入视图
from . import views
#列表 urlpatterns 包含可在应用程序learning_logs中请求的网页
urlpatterns = [
#主页
url(r'^$',views.index,name = 'index'),
]
编写视图
learning_logs 中的文件 views.py 是你执行命令python manage.py startapp 时
自动生成的
当前其内容如下:
from django.shortcuts import render
# Create your views here.
当前只包含了一个 render 函数(),它根据视图提供的数据渲染响应。
#该代码段演示如何在主页编写视图
def index(request):
#学习笔记的主页
return render(request,'learning_logs/index.html')
编写模板
模板定义了网页的结构。指定了网页是什么样的,而每当网页被请求时,Django将填入相关的数据。模板让你能够访问视图提供的任何数据。我们的主页视图没有提供任何数据。
在文件夹 learning_logs 中创建一个文件夹,命名为:templates
然后在 templates 中在创建一个名为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>
当项目阶段进行到这里,应该是可以正常运行的。因为上述流程中走过的每个步骤出现的Bug,都写在文中了。即便是 创建学习网页这块内容出现了 bug ,却没写在文中,也是解决了 bug 才将内容写进文中的。
进行到这里,我们可以运行查看效果了:
4. 创建其他网页
制定创建网页的流程后,就可以开始扩充"学习笔记"项目了。我们创建两个显示数据的网页,其中一个列出所有的主题,另一个则显示特定主题的所有条目。对于每个网页,我们都将指定URL模式,编写一个视图函数,并编写一个模板。但在此之前,我们还要编写一个父模板,项目中的其他模板继承该父模板。
模板继承
父模板
创建一个名为 base.html 的父模板,将其存储在 index.html 同级目录下。
<p>
<a href="{% url 'learning_logs:index' %}">Learning Log</a>
</p>
{% block content %}{% endblock content %}
子模板
编写 index.html,使其继承 base.html
{% extends "Learning_logs/base.html" %}
{% block content %}
<p>Learning Log helps you keep track of your learning, for any topic you're learning about.</p>
{% endblock content %}
显示所有主题的界面
URL 模式
我们首先需要定义所有主题页面的URL
# urls.py 文件
# 显示所有的主题
url(r'^topics/$', views.topics, name='topics'),
视图
函数 topics() 需要从数据库中获取一些数据,并将其发送给模板。我们需要在 views.py
中添加代码如下:
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)
模板
显示所有主题的页面模板都接受字典 context,以便能够使用 topics()提供的数据。
创建一个文件:topics.html,存储在 index.html 同级目录下。
{% extends "learning_logs/base.html" %}
{% block content %}
<p>Topic</p>
<ul>
{% for topic in topics %}
<li> {{ topic }}</li>
{% empty %}
<li>No Topic 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 模式
#learning_logs/urls.py:
# 特定主题的详细页面
url(r'^topics/(?P<topic_id>\d+)/$', views.topic, name='topic'),
视图
函数 topic() 需要从数据库中获取指定的主题以及与之相关联的所有条目
# views.py
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/topics.html',context)
模板
这个模板需要显示主题的名称和条目的内容,如果当前主题不包含任何条目,
还需要向用户指出这一点:
{% extends 'learning_logs/base.html' %}
{% block content %}
<p>Topic: {{ topic }}</p>
<p>Entries:</p>
<ul>
{% for entry in entrys %}
<li>
<p>{{ entry.date_added|date:'M d, Y H:i' }}</p>
<p>{{ entry.text|linebreaks }}</p>
</li>
{% empty %}
<li>
Three are no entries for this topic yet.
</li>
{% endfor %}
</ul>
{% endblock content %}
将显示所有主题页面中的每个主题都设置为链接
topics.html
{% extends "learning_logs/base.html" %}
{% block content %}
<p>Topic</p>
<ul>
{% for topic in topics %}
<li>
<a href="{% url 'learning_logs:topic' topic.id %}">{{ topic }}</a>
</li>
{% empty %}
<li>No Topic have been added yet.</li>
{% endfor %}
</ul>
{% endblock content %}