学习Tango with django(5)

模型和数据库

当你想到数据库的时候,你一般会想到结构查询语言(SQL),通过它我们就可以从数据库查询到我们需要的数据。查询一个可以存储所有类型数据的基础数据库,比如你的网页上的用户信息,在django中可以由ORM来处理。本质上,存储在数据库表中的数据可以被封装成一个模型。一个模型就是描述你数据库表数据的一个python对象。你可以只需要操作相应的python模型对象,而不用直接使用sql来操作数据库。
这章将介绍django和ORM的数据管理基础,你会发现在你应用的基础数据库上添加修改删除数据非常的容易,从数据库中获取数据给用户将会多么的直截了当。

rango需求

在开始之前,让我们先重温下我们要开发的rango应用的数据需求,在前面我们已经详细的介绍了应用的需求,但是为了加深一下记忆,让我们再迅速总结一下客户端的需求。

  • rango是一个基本的网页目录-一个包含链接到其它网页的网页
  • 有许多不同的页面分类,每个分类存储着一些链接。在这本书中,我们都假设分类与链接的关系是一对多的关系,看一下如下的实体关系图。
  • 一个分类有一个名称,数个访问者,数个点赞。
  • 一个页面引用一个分类,有一个标题,URL和数个视图。

这里写图片描述

rango应用里的两个主要对象的实体关系图

向django描述你的数据库

在我们创建模型之前,我们需要在django中配置我们的数据库。在django1.9中,当你新建一个项目时,在你的setting.py文件中会自动生成一个叫DATABASES的变量。类似如下面的例子:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

我们可以直接把上面的配置直接用在我们的rango应用上,上面的配置中把轻量级数据库SQLite作为默认数据库。这个数据库的名称项就是数据库文件的路径,默认放在django项目的根目录,名称为db.sqlite3。

Git小提示
如果你使用git的话,你也许会被提示增加和提交数据库文件,这并不是个好主意,因为如果你是同其他人一起开发应用,他们很有可能会改变数据库,那就会产生没完没了的矛盾了。
将db.sqlite3添加到.gitignore文件中,这样在使用gti命令提交和推送时就不会被提示添加了。你也可以将其它文件如.pyc或者主机特定文件放到.gitignore文件中去。

使用其它数据库引擎
django数据库框架现在已经被设计成可以兼容各种数据库引擎了,比如PostgresSQL, MySQL和微软的SQL Server。对于其他数据库,另外的几个配置项如USER, PASSWORD, HOST and PORT都要配置。
经这本书中我们并没有讲如何使用其它数据库引擎,但是官方文档上都有详细的向导教你如何使用。
注意SQLite数据库已经足够展现djangoORM的功能了。但是如果你发现你的应用非常受环境,已经积累了数以千计的用户了,那时你就得考虑更换更加健壮的数据库了。

创建模型

在settings.py文件中配置了数据库信息后,让我们为rango应用添加两个基本的数据模型。django应用的模型文件都存储在应用各自的model.py文件里,也就是说,rango的应用是存储在rango/models.py
在模型里面,我们将创建两个类,每个类表示一个模型。这两个类都必须要继承基类django.db.models.Model。下面的代码定义了Category和Page模型,分别代表了分类和页面。

class Category(models.Model):
    name = models.CharField(max_length=128, unique=True)

    def __str__(self): # For Python 2, use __unicode__ too
        return self.name


class Page(models.Model):
    category = models.ForeignKey(Category)
    title = models.CharField(max_length=128)
    url = models.URLField()
    views = models.IntegerField(default=0)

    def __str__(self): # For Python 2, use __unicode__ too
        return self.title

检查import语句
在models.py文件上面应该有from django.db import models语句,如果没有就添加一下。

__str__() 还是 __unicode__()?
在python中__str__()__unicode__()方法是用来生产代表类的字符串(类似于java中的toString())。在python2.X中,使用__str__()表示使用ASCII格式化字符串,如果想支持unicode,你就需要执行__unicode__()。在python3.X,字符串默认就是unicode,所以你只需要执行__str__()就可以了。
定义模型时,需要指定一系列的数据项和相应的类型,以及一些必须或可选的参数。默认情况下,所有的模型都会自动分配一个名为id的自增整型数据项,并被设置为主键。django提供了一系列综合的数据类型,下面是几个比较常用的:

  • CharField,存储字符数据(如字符串),需要提供max_length参数指定这个数据项可以存储的最大字符长度。
  • URLField,与CharField很相似,但是设计成存储URL的,你也需要指定max_length参数。
  • IntegerField,存储整型数据。
  • DateField,存储python的datetime.date对象。

其它数据类型
django官方文档提供了全面的django数据类型,以及每个数据项必须或者可选的参数。

对于每一项,你可以指定unique属性。如果设置为真,这个数据项映射到基础数据库的表中的值必须是唯一的。举个例子,上面定义的Category模型,name项设置了unique为真,也就是说,每个分类的名称必须是唯一的。这样你就可以把这一项作为主键来使用了。
你也可以为数据项中指定其它属性,比如使用default='value'来指定一个默认值,数据项的值可以设置为空的(或者NULL)(NULL=True)或者非空(null=False)。
django还提供了以下三种数据类型,来定义数据库中模型之间的关系。

  • ForeignKey,用来创建一对多数据类型
  • OneToOneField,用来创建一对一数据类型
  • ManyToManyField,用来创建多对多数据类型

在上面的模型例子中,模型pages中的category项就是一个ForeignKey类型,我们在这一项中指定Category类作为参数,就能创建一个一对多的关系了。
最后,最好在类定义中添加__str__() 或者 __unicode__()方法。没有定义这个方法的话,在打印这些类的对象时,会显示<Category: Category object>,在访问或者调试对象时,这个信息没什么用。如果定义了上面的方法后,在打印类对象时,如category类就会显示<Category: Python>。在使用管理界面时,这样做也非常有用,因为django会展现这些对象的字符串表现形式。

创建并迁移数据库

我们在models.py中定义好模型后,就可以让django开始工作在数据库中创建表了。django提供了一个迁移工具,在模型定义有修改的时候,通过工具更新数据库表。比如说,你在模型中增加了一个字段后,你就可以使用迁移工具更新数据库表结构了。

配置

首先,数据库必须要先被初始化,也就是说数据库和相应表必须要先创建后才能存储数据。因此你需要先打开终端或者命令提示行,将目录切换到项目所在根目录,也就是manage.py文件所在的目录。运行下面的命令,注意输出的内容会和你自己运行的输出内容不太一样。

$ python manage.py migrate

Operations to perform:
    Apply all migrations: admin, contenttypes, auth, sessions
Running migrations:
    Rendering model states... DONE
    Applying contenttypes.0001_initial... OK
    Applying auth.0001_initial... OK
    Applying admin.0001_initial... OK
    Applying admin.0002_logentry_remove_auto_add... OK
    Applying contenttypes.0002_remove_content_type_name... OK
    Applying auth.0002_alter_permission_name_max_length... OK
    Applying auth.0003_alter_user_email_max_length... OK
    Applying auth.0004_alter_user_username_opts... OK
    Applying auth.0005_alter_user_last_login_null... OK
    Applying auth.0006_require_contenttypes_0002... OK
    Applying auth.0007_alter_validators_add_error_messages... OK
    Applying sessions.0001_initial... OK

使用这个命令会让django项目中安装的所有app(在settings.py的INSTALLED_APPS中定义的)更新到数据库中。命令运行完后,你应该能看到在项目根目录下生成了一个db.sqlite3的文件。
下一步,创建超级用户来管理数据库。运行如下命令:

$ python manage.py createsuperuser

超级用户是用来访问django项目的管理界面,在后面章节会用到。根据提示输入帐号,email,密码。输入完后,脚本会提示创建成功。超级用户的用户名和密码你必须要记住。

创建并更新模型或表

无论你什么时候对模型作出修改,你都需要通过manage.py提供的makemigrations命令注册这些修改。我们在根目录中运行如下命令,并指定rango应用作为目标参数。

$ python manage.py makemigrations rango

Migrations for 'rango':
    0001_initial.py:
        - Create model Category
        - Create model Page

上面的命令运行完后,检查一下在rango/migrations目录下是否创建了新的python脚本,0001_initial.py。这个脚本包含了为这次的迁移创建数据库模式所需要的详细信息。

检查数据库SQL
如果你想查看一下djangoORM对模型作出的修改运行了哪些sql,你可以运行以下命令:

$ python manage.py sqlmigrate rango 0001

这个例子中,rango是app名称,0001是你希望查看sql代码的迁移文件。运行完后,你就能比较直观的看到在数据库层做了什么操作,比如什么表被创建等。你也能看到比较复杂的数据库模式的创建,比如多对多关系模型还需要创建额外的表。
在为你的app创建好迁移文件后,你还需要提交到数据库中运行。再次运行migrate命令。

$ python manage.py migrate

Operations to perform:
    Apply all migrations: admin, rango, contenttypes, auth, sessions
Running migrations:
    Rendering model states... DONE
    Applying rango.0001_initial... OK

这个输出表示数据库表已经成功创建了,配置没问题。
但是根据rango应用的需求,Category模型目前还缺一些字段,别着急,稍后我们再运行迁移命令,把这些字段都添加上。

django模型和shell

在我们将关注转移到演示django管理界面之前,通过django自带的shell直接同django模型交互的知识有必要学习一下。django自带的shell是非常有用的调试工具。我们将演示在shell中如何创建一个Category实例。
要访问shell,我们需要再次运行django项目根目录下的manage.py。运行如下命令:

$ python manage.py shell

这个命令会创建一个python解释器实例并加载django项目的配置。接下来就可以通过终端与模型交互演示功能了。查看一下代码里注释了解一下每条命令用来实现什么功能的。注意django1.9和django1.10的返回结果会稍有不同,注释中都标记出来了。

# Import the Category model from the Rango application
>>> from rango.models import Category

# Show all the current categories
>>> print(Category.objects.all())
# The output examples below are for both Django 1.9 and Django 1.10.
# Both denote the same thing, that no categories have been defined.
[] # Django 1.9 output -- an empty list.
<QuerySet []> # Django 1.10 output -- an empty QuerySet object.

# Create a new category object, and save it to the database.
>>> c = Category(name="Test")
>>> c.save()

# Now list all the category objects stored once more.
>>> print(Category.objects.all())
# The output examples below are for both Django 1.9 and Django 1.10.
# You'll now see a 'test' category in both output examples.
[<Category: test>] # Django 1.9
<QuerySet [<Category: test>] # Django 1.10

# Quit the Django shell.
>>> quit()

在上面的例子中,我们首先导入了我们想要操作的模型,然后打印出了所有已存在的分类。因为我们数据库里category表是空的,所以返回的结果也是空的。接下来我们创建并保存了一个category实例,再次打印了所有分类。第二次打印就显示了新增加的category实例。注意,第二次打印出现的Test就是__str__()__unicode__()方法的输出结果。

完成官方手册教程
上面的例子仅仅是djano的shell中涉及数据库操作的简单尝试。如果你还没做完,现在就比较适合完成django官方手册上其它两部分,以便学习到更多的模型操作的知识。也可以在django官方文档上查阅到跟模型操作有关的可用命令。

配置管理界面

django有一个出色的功能就是内置的基于web的管理界面,能够让你浏览、编辑、删除相关的模型实例(从对应的数据库表中)。在这一节,我们将配置管理界面,让你之前创建的Rango模型在管理界面上显示。
django的设置相对都比较直观。在settings.py文件中,你会注意到预安装的app中有一个叫django.contrib.admin。同时在项目的urls.py文件里有一行匹配admin/的urlpattern。
默认情况下,配置都准备好了,使用下面命令运行django开发服务器。

$ python manage.py runserver

在浏览器中打开http://127.0.0.1:8000/admin/,然后会显示一个登录界面。使用之前用$ python manage.py
createsuperuser
命令创建的用户信息登录,你就会看到类似于如下的界面。

这里写图片描述

没有rango模型的django管理界面

界面看起来很不错,但是没有在rango应用中定义的Category和Page模型。为了让页面包括这两个模型,我们需要django提供帮助。
打开文件rango/admin.py,在已有的include语句上,添加你想要注册到管理页面上的类。下面的例子将Category和Page类都注册到管理页面上了。

from django.contrib import admin
from rango.models import Category, Page

admin.site.register(Category)
admin.site.register(Page)

以后想添加新类到管理页面上,只需要调用admin.site.register()方法就可以了。
保存修改,重启开发服务器,重新访问http://127.0.0.1:8000/admin/,现在就能看到Category和Page类了,如下所示:
这里写图片描述

包括rango模型的django管理界面

尝试点击一下Categorys链接,你应该能看到之前在shell下创建的test实例。

尝试使用管理界面
现在在你开发rango应用的时候,你可以用管理界面验证数据是否正确存储。尝试操作一下这个管理界面,了解一下如何运行的。管理界面设计的通俗易懂,简单直观。
删除Category的test实例,之后我们会导入更多的实例数据到数据库中。

用户管理
django的管理界面是用户管理的入口,通过django提供的认证与授权模块进行管理。你可以创建、修改和删除用户帐号,并设置权限等级。

单数和复数拼写
注意在管理界面有一个错单词(Categorys, 不是 Categories),在你的模型中添加一个内嵌的Meta类并定义verbose_name_plural属性就可修复。例子如下,查看一下修改后的Category模型版本。django官方文档里有更多的关于在meta类中可以存储的数据的信息。

class Category(models.Model):
    name = models.CharField(max_length=128, unique=True)

    class Meta:
        verbose_name_plural = 'Categories'

    def __str__(self):
        return self.name

扩展admin.py
应该注意到rango应用给出的admin.py示例是相当简单的,仅有基本的功能。但是你其实可以有很多方法自定义管理界面。如果你感兴趣,你可以查阅一下官方文档获取更多关于管理界面的信息。

创建一个填充脚本

将测试数据输入到数据库中通常很麻烦。很多开发者通过随机生成无规则数据作为测试数据,比如wTFzmN00bz7。这里我们不这么做,写一个脚本自动的将真实可信的数据填充到数据库中更好。因为当你准备示范或者测试你的应用时,你能从数据库中返回比较直观的实例。当然,如果你还要部署应用或者将应用分享给同事,你或者他们也不用再重复填充相同的数据了。因此,创建一个填充脚本是很不错的主意。
要为rango应用创建一个填充脚本,我们首先需要在django项目根目录下创建一个新的python文件,命名为populate_rango.py,并添加如下代码:

1 import os
2 os.environ.setdefault('DJANGO_SETTINGS_MODULE',
3                   'tango_with_django_project.settings')
4
5 import django
6 django.setup()
7 from rango.models import Category, Page
8
9 def populate():
10  # First, we will create lists of dictionaries containing the pages
11  # we want to add into each category.
12  # Then we will create a dictionary of dictionaries for our categories.
13  # This might seem a little bit confusing, but it allows us to iterate
14  # through each data structure, and add the data to our models.
15
16  python_pages = [
17      {"title": "Official Python Tutorial",
18      "url":"http://docs.python.org/2/tutorial/"},
19      {"title":"How to Think like a Computer Scientist",
20      "url":"http://www.greenteapress.com/thinkpython/"},
21      {"title":"Learn Python in 10 Minutes",
22      "url":"http://www.korokithakis.net/tutorials/python/"} ]
23
24  django_pages = [
25      {"title":"Official Django Tutorial",
26      "url":"https://docs.djangoproject.com/en/1.9/intro/tutorial01/"},
27      {"title":"Django Rocks",
28      "url":"http://www.djangorocks.com/"},
29      {"title":"How to Tango with Django",
30      "url":"http://www.tangowithdjango.com/"} ]
31
32  other_pages = [
33      {"title":"Bottle",
34      "url":"http://bottlepy.org/docs/dev/"},
35      {"title":"Flask",
36      "url":"http://flask.pocoo.org"} ]
37
38  cats = {"Python": {"pages": python_pages},
39      "Django": {"pages": django_pages},
40      "Other Frameworks": {"pages": other_pages} }
41
42  # If you want to add more catergories or pages,
43  # add them to the dictionaries above.
44
45  # The code below goes through the cats dictionary, then adds each category,
46  # and then adds all the associated pages for that category.
47  # if you are using Python 2.x then use cats.iteritems() see
48  # http://docs.quantifiedcode.com/python-anti-patterns/readability/
49  # for more information about how to iterate over a dictionary properly.
50
51  for cat, cat_data in cats.items():
52      c = add_cat(cat)
53      for p in cat_data["pages"]:
54          add_page(c, p["title"], p["url"])
55
56  # Print out the categories we have added.
57  for c in Category.objects.all():
58      for p in Page.objects.filter(category=c):
59          print("- {0} - {1}".format(str(c), str(p)))
60
61def add_page(cat, title, url, views=0):
62  p = Page.objects.get_or_create(category=cat, title=title)[0]
63  p.url=url
64  p.views=views
65  p.save()
66  return p
67
68def add_cat(name):
69  c = Category.objects.get_or_create(name=name)[0]
70  c.save()
71  return c
72
73# Start execution here!
74if __name__ == '__main__':
75  print("Starting Rango population script...")
76  populate()

理解代码!
我们再强调一次,千万不要简单的复制粘贴,然后没了。将代码添加到你的模块中,然后一行一行的理解每行的意思,这样会帮助你理解整个代码的意思。
我们在下面也给出了解释,希望你能学到新一点的东西。
你应该注意到每行代码前有一个行数,这表示我们列出了整个文件,而不是代码片段。这样也让你复制粘贴麻烦点。

上面的代码看起来有好多,实际上就是定义在文件最下方的两个小函数add_page() 和 add_cat()的一系列调用。通读代码,我们找到程序从最低部的两行开始执行,75行和76行。因为上面的内容都是函数的定义,函数只用在被调用时才会被执行。当python解释器运行到if __name__ == '__main__'时,就会调用populate()函数。

__name__ == '__main__'表示什么意思
语句__name__ == '__main__'在判断python模块是作为被导入执行还是单独执行时是非常有用的。假设我们现在有一个可重用模块将会被导入到其它模块中(使用import语句)。在终端中输入python module.py,一个单独python脚本会被执行。
代码里的条件判断语句if __name__ == '__main__'只有在这个模块是单独运行的时候才会被执行。导入模块时就不会运行这块代码,但是模块里的函数或者类都是可以访问的。

导入模块
当要导入django模型时,一定要保证你已经导入了项目的配置信息。你需要导入django模块,并设置环境变量DJANGO_SETTINGS_MODULE为你项目的settings.py,正如上面代码第1到6行演示的那样。然后再调用django.setup()导入django的项目信息。
如果这个关键步骤你没有执行,当当如模型时就会报错,因为django所需要的基础环境还没有被初始化。这就是我们为什么在settings被加载后才导入Category和Page模型的原因,如第7行所示。
51到54行的for循环负责重复的调用add_cat()和add_page()函数。这些函数负责依次创建新的category和page。populate()函数一直不断创建分类。如上面的例子,在第52行,一个新的分类存储在局部变量c中,存储它的原因是因为查找page实例需要引用分类。在populate()函数里调用完add_cat()和add_page()函数之后,函数通过循环得到所有的分类和相关的页面对象,将它们的名称打印到终端上。

创建模型实例
在上面的填充脚本中我们使用l非常方便的get_or_create()方法。因为我们不想再创建重复的项,所以我们使用get_or_create()方法先判断实例在数据库中是否存在,如果不存在则创建它,如果存在就返回一个实例引用。
这个函数可以帮助我们删除了很多重复性的代码。我们用django提供的方法来准确度完成检查重复的工作,而不是自己费力的写代码完成。
get_or_create()函数返回一个元组对象,包括(object,created)。如果数据库中不存在给出条件的实例,那么返回元组的第一个对象就是get_or_create()函数创建的实例。这个实例通过你传递给方法的参数,如上面代码所示的category、url、title和views,所创建而成。如果实例在数据库中已存在,这个函数就只返回相应的实例对象。created是一个布尔值,当get_or_create()函数创建了一个新实例就返回True。
因此在调用get_or_create()函数返回结果后面加个[0]表示仅返回实例对象。像其它大多数编程语言的数据结构一样,python元组使用从0计数原则。
你可以在django官方文档上查询更多的关于get_or_create()函数的信息。

脚本保存好后,现在你可以在终端里切换到django项目的根目录里运行新的填充脚本了。只是简单的执行命令$ python populate_rango.py。你应该能看到如下的输出结果,新增分类的顺序根据你电脑的配置不同而不同。

$ python populate_rango.py

Starting Rango population script...
- Python - Official Python Tutorial
- Python - How to Think like a Computer Scientist
- Python - Learn Python in 10 Minutes
- Django - Official Django Tutorial
- Django - Django Rocks
- Django - How to Tango with Django
- Other Frameworks - Bottle
- Other Frameworks - Flask

下一步,验证一下填充脚本是否真的将数据填充到数据库中了。重启django开发服务器,访问管理界面(http://127.0.0.1:8000/admin/)检查是否新增了一些新分类和页面。当你点击page链接时你能看到所有的page吗?就像下面显示的截图一样。
这里写图片描述

django管理界面,显示了通过填充脚本填充的页面,成功!

尽管一开始编写一个填充脚本会花一些时间,但是在以后会节约你很多时间。如果要将应用部署到其它地方,在django配置好后,运行一下填充脚本,你就可以马上演示你的应用了。你也会发现当使用单元测试的时候这样做会多么的方便。

工作流:创建模型

既然我们已经讲解了django的ORM处理的核心原则,现在我们就来对所有的配置过程进行一个总结。我们已经为你把关键的任务分割成好几个部分了。当你需要迅速的重温一下这些步骤的时候就来翻阅一下这些知识。

配置数据库

在一个新的django项目,首先你需要告诉django你要用什么数据库(在settings.py的DATABASES里配置)。你可以在应用的admin.py文件里注册模型让它们可以通过管理界面访问。

添加模型

添加一个新的模型可以分为以下五步:

  • 首先,在应用的models.py里创建新的模型。
  • 在admin.py里导入并注册模型。
  • 执行迁移命令$ python manage.py makemigrations <app_name>
  • 运行命令$ python manage.py migrate应用修改。这将会为你的模型在数据库中创建必要的数据结构。
  • 为你的新模型创建或编辑填充脚本。

有时你不得不删掉数据库,这也很容易重新开始。如果你想这样做,按照下面的流程做。注意在这本书里,我们使用的是SQLite数据库,django支持各种各样数据库引擎。

  • 如果django开发服务器正在运行的话,先停止。
  • 对于SQLite数据库,删除django项目目录下的db.sqlite3文件,这个目录和manage.py所在目录一致。
  • 如果你修改过应用模型,你还要运行命令$ python manage.py makemigrations <app_name>,这里将<app_name>替换成你的应用名称,如rango。如果模型没有修改,跳过此步。
  • 运行命令$ python manage.py migrate,创建新的数据库文件(如果你运行的是SQLite数据库)。
  • 使用命令$ python manage.py createsuperuser创建新的管理员帐号。
  • 最后,再次运行你的填充脚本插入靠谱的测试数据到你的数据库中。

练习
既然你已经完成了这个章节,尝试做一下练习来巩固你所学习的知识。再强调一次,接下来的章节都是假设你完成了这些练习。如果你搞不定,下面有一些提示帮助你完成练习。

  • 更新Category模型,在模型中添加views和likes属性,并设置默认值为0。
  • 为你的应用运行makemigration命令,将修改迁移到你的数据库中。
  • 更新填充脚本,设置python分类的views值为128,likes为64,设置django分类的views值为64,likes为32,设置the other frameworks分类的views值为32,likes为16。
  • 删除并重建数据库,运行更新过的填充脚本,将新数据填充到数据库中。
  • 完成django官方手册第二部分和第七部分,这几节会加强你所学到的关于在django中操作数据库的知识,并介绍了一些自定义django管理界面的其它技术。
  • 自定义管理界面。修改admin.py文件,当你查看Page模型时,页面会显示分类,页面名称和url,如下截图所示。你需要完成之前的练习或者完成django的官方手册才能完成这个练习。
    这里写图片描述
    更新后的Page管理界面,包含Category和URL列

练习提示
下面给出了一些提示来帮助你完成上面的联系。

  • 修改Category模型通过增加两个IntegerFields:views和likes。
  • 在你的填充脚本里,修改add_cat()函数,控制Category模型里的views和likes的值。
    • 你需要在add_cat()函数里增加两个参数,这样views和likes的值才能传递给函数,当然还有category的名称。
    • 接下来你就可以在这个通过add_cat()函数创建的Category模型实例中使用这些参数来设置views和likes值了。模型的实例赋值给之前在填充脚本中定义的变量c。举个例子,你可以用语句c.likes来访问likes项。别忘了save()实例。
    • 接下来你需要更新填充脚本中populate()函数的cats字典。观察这个字典,每个键值对表示为分类名称为键,另外一个包含分类相关信息的字典作为值。你需要为每个分类的字典添加views和likes项。
    • 最后一步需要你修改一下调用add_cat()函数的方式,现在你已经有三个参数需要传递了(name,views,likes),你的代码目前只有name。你需要在函数调用中增加另外两项。如果你还不清楚for循环是如何处理字典的,你需要查阅一下python在线手册。通过手册你能了解到如何通过字典访问views和likes。
  • 更新好填充脚本后,你需要自定义管理界面。你应该编辑rango/admin.py,创建PageAdmin并继承admin.ModelAdmin。
    • 在PageAdmin里,增加list_display = ('title','category', 'url')
    • 将PageAdmin注册到django的管理界面。你应该修改admin.site.register(Page)这一行,修改为admin.site.register(Page, PageAdmin)

测试
我们已经编写了几个测试来验证你是否完成了练习。为了检查目前为止你的工作成果,从我们的github库中下载test.py脚本,并保存到你的rango应用目录里。
在终端或命令提示行里运行如下命令。

$ python manage.py test rango

如果你对学习自动测试感兴趣,现在你就可以学习测试章节。这个章节讲解了关于如何写测试去自动检查你的代码完整性的一些基础。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值