Django初学者笔记系列(二)
1.创建应用程序
Django项目 由一系列应用程序组成,它们协同工作,让项目成为一个整体。我们暂时只创建一个应用程序,它将完成项目的大部分工作
当前,在前面打开的终端窗口中应该还运行着runserver 。请再打开一个终端窗口(或标签页),并切换到manage.py所在的目录。激活该虚拟环境,再执行命令startapp
learning_log$ source ll_env/bin/activate
(ll_env)learning_log$ python manage.py startapp learning_logs
(ll_env)learning_log$ ls
db.sqlite3 learning_log learning_logs ll_env manage.py (ll_env)learning_log$ ls learning_logs/
admin.py init.py migrations models.py tests.py views.py
我们将使用models.py来定义我们要在应用程序中管理的数据
。admin.py和views.py将在稍后介绍。目录下还有一个apps.py文件,作用之后了解
2.定义模型
打开models.py并创建模型:
from django.db import models
class Topic(models.Model):
"""用户学习的主题"""
text = models.CharField(max_length=200)
date_added = models.DateTimeField(auto_now_add=True)
def __str__(self):
"""返回模型的字符串表示"""
return self.text
我们创建了一个名为Topic 的类,它继承了Model ——Django中一个定义了模型基本功能的类
。Topic 类只有两个属性:text 和date_added。属性text是一个CharField——由字符或文本组成的数据
。需要存储少量的文本,如名称、标题或城市时,可使用CharField 。定义CharField 属性时,必须告诉Django该在数据库中预留多少空间。属性date_added 是一个DateTimeField ——记录日期和时间的数据
。我们传递了实参auto_add_now=True ,每当用户创建新主题时,这都让Django将这个属性自动设置成当前日期和时间。
要获悉可在模型中使用的各种字段,戳下方链接:
模型字段的官方文档
我们需要告诉Django,默认应使用哪个属性来显示有关主题的信息。Django调用方法__str__() 来显示模型的简单表示。在这里,我们编写了方法__str__() ,它返回存储在 属性text中的字符串
3.激活模型
打开settings.py,将应用添加进去。
--snip--
INSTALLED_APPS = (
--snip--
'django.contrib.staticfiles',
# 我的应用程序
'learning_logs', )
--snip--
接下来,需要让Django修改数据库,使其能够存储与模型Topic 相关的信息。为此,在终端窗口中执行下面的命令:
python3 manage.py makemigrations learning_logs
输出如下:
learning_logs/migrations/0001_initial.py
- Create model Topic
(ll_env) nanimatoMacBook-Air:learning_log heguanlin$
命令makemigrations让Django确定该如何修改数据库,使其能够存储与我们定义的新模型相关联的数据
。输出表明Django创建了一个名为0001_initial.py的迁移文件,这个文件将在数据库中为模型Topic创建一个表。
下面来应用这种迁移,让Django替我们修改数据库:
输入:
python3 manage.py migrate
而输出中包含一行:
Applying learning_logs.0001_initial... OK
在这里,Django确认为learning_logs 应用迁移时一切正常(OK )。每当需要修改“学习笔记”管理的数据时,都采取如下三个步骤:修改models.py;对learning_logs 调用makemigrations;让Django迁移项目。
Django管理网站
为应用程序定义模型时,Django提供的管理网站(admin site)让你能够轻松地处理模型。网站的管理员可使用管理网站,但普通用户不能使用。在本节中,我们将建立管理网站,并通过它使用模型Topic 来添加一些主题。
1.创建超级用户
python3 manage.py createsuperuser
注意:
可能会对网站管理员隐藏有些敏感信息。例如,Django并不存储你输入的密码,而存储从该密码派生出来的一个字符串——散列值。每当你输入密码 时,Django都计算其散列值,并将结果与存储的散列值进行比较。如果这两个散列值相同,就通过了身份验证。通过存储散列值,即便黑客获得了网站数据库的访问 权,也只能获取其中存储的散列值,而无法获得密码。在网站配置正确的情况下,几乎无法根据散列值推导出原始密码。
2.向管理网站注册模型
Django自动在管理网站中添加了一些模型,如User 和Group ,但对于我们创建的模型,必须手工进行注册。 我们创建应用程序learning_logs 时,Django在models.py所在的目录中创建了一个名为admin.py
的文件。为向管理网站注册Topic ,请输入下面的代码:
from django.contrib import admin
from learning_logs.models import Topic #导入要注册的模型Topic
admin.site.register(Topic) #让Django通过管理网站管理我们的模型
现在,使用超级用户账户访问管理网站:访问http://localhost:8000/admin/
,并输入你刚创建的超级用户的用户名和密码。这个网页让你能够添加和修改用户和用户组,还可以管理与刚才定义的模型Topic 相关的数据。
注意 :
如果你在浏览器中看到一条消息,指出访问的网页不可用,请确认你在终端窗口中运行着Django服务器。如果没有,请激活虚拟环境,并执行命令python3 manage.py runserver
3.添加主题
向管理网站注册Topic 后,我们来添加第一个主题。为此,单击Topics进入主题网页,它几乎是空的,这是因为我们还没有添加任何主题。单击Add,你将看到一个用于添加新主题的表单。在第一个方框中输入Chess ,再单击Save,这将返回到主题管理页面,其中包含刚创建的主题。 下面再创建一个主题,以便有更多的数据可供使用。再次单击Add,并创建另一个主题Rock Climbing。当你单击Save时,将重新回到主题管理页面,其中包含主题Chess和Rock Climbing。
定义模型Entry
下面是模型Entry的代码:models.py
from django.db import models
# Create your models here.
class Topic(models.Model):
'''用户学习的主题'''
text = models.CharField(max_length=200)
date_added = models.DateTimeField(auto_now_add=True)
def __str__(self):
'''返回模型的字符串表示'''
return self.text
class Entry(models.Model):
'''学到的有关某个主题的具体知识'''
topic = models.ForeignKey(Topic)
text = models.TextField()
date_added = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name_plural = 'entries'
def __str__(self):
'''返回模型的字符串表示'''
return self.text[:50] + "..."
像Topic 一样,Entry 也继承了Django基类Model 。第一个属性topic 是一个ForeignKey 实例。
外键是一个数据库术语,它引用了数据库中的另一条记录;这些代码将每个条目关联到特定的主题。每个主题创建时,都给它分配了一个键(或ID)。需要在两项数据之间建立联系时,Django使用与每项信息相关联的键。稍后我们将根据这些联系获取与特定主题相关联的所有条目。
接下来是属性text ,它是一个TextField 实例。这种字段不需要长度限制,因为我们不想限制条目的长度
我们在Entry 类中嵌套了Meta 类。Meta 存储用于管理模型的额外信息,在这里,它让我们能够设置一个特殊属性,让Django在需要时使用Entries 来表示多个条目。如果没有这个类,Django将使用Entrys来表示多个条目。最后,方法__str__() 告诉Django,呈现条目时应显示哪些信息。由于条目包含的文本可能很长,我们让Django只 显示text 的前50个字符(见❺)。我们还添加了一个省略号,指出显示的并非整个条目。关于该类的作用和子类的用法之后重点掌握
迁移模型Entry
由于我们添加了一个新模型,因此需要再次迁移数据库:
修改models.py---->执行命令python3 manage.py makemigrations app_name---->python3 manage.py migrate
在执行第二个命令时报错:TypeError: init() missing 1 required positional argument: ‘on_delete’,参考了这篇文章得到解决点击这里
生成了一个新的迁移文件——0002_entry.py,它告诉Django如何修改数据库,使其能够存储与模型Entry 相关的信息,执行命令migrate ,我们发现Django应用了这种 迁移且一切顺利
向管理网站注册Entry
我们还需要注册模型Entry 。为此,需要将admin.py修改成类似于下面这样:
from django.contrib import admin
from learning_logs.models import Topic,Entry
admin.site.register(Topic)
admin.site.register(Entry)
在此遇到这样一个报错:AttributeError: ‘AdminSite’ object has no attribute ‘reg’。不知道为什么,重新开启服务就好了
返回到http://localhost/admin/,你将看到learning_logs下列出了Entries。单击Entries的Add链接,或者单击Entries再选择Add entry。你将看到一个下拉列表,让你能够选择要为哪个主题创 建条目,还有一个用于输入条目的文本框。从下拉列表中选择Chess,并添加一个条目。
Django shell
输入一些数据后,就可通过交互式终端会话以编程方式查看这些数据了。这种交互式环境称为Django shell,是测试项目和排除其故障的理想之地。下面是一个交互式shell会话示例:
(ll_env)learning_log$ python3 manage.py shell
>>> from learning_logs.models import Topic
>>> Topic.objects.all()
<QuerySet [<Topic: Chess>, <Topic: Rock Climbing>]>
命令python3 manage.py shell
启动一个python解释器,可使用它来探索存储在项目数据库中的数据。
下面演示了如何查看分配给每个主题对象的ID:
>>> topics = Topic.objects.all()
>>>> for topic in topics:
... print(topic.id, topic)
...
1 Chess
2 Rock Climbing
知道对象的ID后,就可获取该对象并查看其任何属性。下面来看看主题Chess的属性text 和date_added 的值:
>>> t = Topic.objects.get(id=1)
>>> t.text
'Chess'
>>> t.date_added
datetime.datetime(2015, 5, 28, 4, 39, 11, 989446, tzinfo=<UTC>)
我们还可以查看与主题相关联的条目。前面我们给模型Entry 定义了属性topic ,这是一个ForeignKey ,将条目与主题关联起来。利用这种关联,Django能够获取与特定主 题相关联的所有条目,如下所示:
>>> t.entry_set.all()
[<Entry: The opening is the first part of the game, roughly...>, <Entry: In the opening phase of the game, it's important t...>]
为通过外键关系获取数据,可使用相关模型的小写名称、下划线和单词set。例如,假设你有模型Pizza 和Topping ,而Topping通过一个外键关联到Pizza ;如果你有 一个名为my_pizza 的对象,表示一张比萨,就可使用代码my_pizza.topping_set.all() 来获取这张比萨的所有配料。
编写用户可请求的网页时,我们将使用这种语法。确认代码能获取所需的数据时,shell很有帮助。如果代码在shell中的行为符合预期,那么它们在项目文件中也能正确地工作。如 果代码引发了错误或获取的数据不符合预期,那么在简单的shell环境中排除故障要比在生成网页的文件中排除故障容易得多。我们不会太多地使用shell,但应继续使用它来熟悉对 存储在项目中的数据进行访问的Django语法。
注意:
每次修改模型后,你都需要重启shell,这样才能看到修改的效果。要退出shell会话,可按Ctr + D;如果你使用的是Windows系统,应按Ctr + Z,再按回车键。