在这一节,我们将学习如何用自动脚本来添加内容,然后给我们的应用添加首页和一个内容页。
9.Part1练习答案
除了加入views和likes两个字段,这里我们需要思考一个问题,用户将如何来访问我们的页面?用/rango/category/1/ 或 /rango/category/2/?他们怎么知道1代表哪个分类,2又代表哪个分类?有没有更直接一点的方法呢?
我想还是直接用分类名称来作为链接的一部分会比较好一些,比如用/rango/category/Python/来访问Python分类这样子。但碰到带空格的分类名称时,链接中的空格会被自动转义,因此,用一个别名来作为链接更为理想。
Django中有一个slugify的方法,它可以把帮助我们自动处理别名,比如我们的分类名是”how do i create a slug in django“,slugify会把它变成”how-do-i-create-a-slug-in-django“。
编辑rango/models.py文件,修改Category类:
rango/models.py:
from django.template.defaultfilters import slugify class Category(models.Model): name = models.CharField(max_length=128, unique=True) views = models.IntegerField(default=0) likes = models.IntegerField(default=0) slug = models.SlugField(unique=True) def save(self, *args, **kwargs): self.slug = slugify(self.name) super(Category, self).save(*args, **kwargs) def __str__(self): return self.name
然后依次在dos命令提示符下运行如下命令:
$ python manage.py makemigrations rango
$ python manage.py migrate
注意:在model.py中对模型中的字段进行修改后,必须执行上述命令才能把数据库跟着改动。
加入slug字段后,我们希望在管理界面中输入分类名称时,自动生成slug字段,这个可以通过修改admin.py来实现。
编辑rango/admin.py 文件,让它变成下面这个样子:
rango/admin.py:
from django.contrib import admin from rango.models import Category, Page class PageAdmin(admin.ModelAdmin): list_display = ('title', 'category', 'url') class CategoryAdmin(admin.ModelAdmin): prepopulated_fields = {'slug':('name',)} admin.site.register(Category, CategoryAdmin) admin.site.register(Page, PageAdmin)
10.创建自动化脚本
这一次我们不再手动输入内容,而是采用自动化脚本的形式:用一个脚本来自动添加内容。
在项目根文件夹下创建populate_rango.py,加入如下内容:
rangoproject/populate_rango.py:
#!/usr/bin/env python import os import django def populate(): python_cat = add_cat('Python') add_page(cat=python_cat, title="Official Python Tutorial", url="http://docs.python.org/3/tutorial/") add_page(cat=python_cat, title="How to Think like a Computer Scientist", url="http://www.greenteapress.com/thinkpython/") add_page(cat=python_cat, title="Learn Python in 10 Minutes", url="http://www.korokithakis.net/tutorials/python/") django_cat = add_cat("Django") add_page(cat=django_cat, title="Official Django Tutorial", url="https://docs.djangoproject.com/en/1.7/intro/tutorial01/") add_page(cat=django_cat, title="Django Rocks", url="http://www.djangorocks.com/") add_page(cat=django_cat, title="How to Tango with Django", url="http://www.tangowithdjango.com/") frame_cat = add_cat("Other Frameworks") add_page(cat=frame_cat, title="Bottle", url="http://bottlepy.org/docs/dev/") add_page(cat=frame_cat, title="Flask", url="http://flask.pocoo.org") # 输出我们添加的内容. for c in Category.objects.all(): for p in Page.objects.filter(category=c): print ("- {0} - {1}".format(str(c), str(p))) def add_page(cat, title, url, views=0): p = Page.objects.get_or_create(category=cat, title=title, url=url, views=views)[0] return p def add_cat(name): c = Category.objects.get_or_create(name=name, defaults=None)[0] return c # 开始执行! if __name__ == '__main__': print ("开始执行Rango自动化脚本...") os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'rangoproject.settings') django.setup() from rango.models import Category, Page populate()
我们来运行这个脚本,在dos命令提示符下输入命令:
python populate_rango.py
你会看到象这样的提示:
开始执行Rango自动化脚本... - 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/
按回车进入登录页面,输入账号和密码,登录成功后,点击链接“Pages”,可看到如下页面:
写这样一个脚本虽然要花上一点时间,但你若是在一个团队中做这个项目,你可以把这个脚本分发给团队中的其他人,那样,他们就可以很快创建好数据库。此外,这个脚本在测试中亦会派上用场。
11.在首页上显示分类
我们来回顾一下,要完成某页面显示,需要做哪些操作?
- 编写视图
- 创建模板
- 设计URL
下面我们来一一完成。先编辑rango/views.py 文件,让它变成下面这样:
rango/views.py:
from django.shortcuts import render from rango.models import Category def index(request): # 查询数据库中的所有分类; # 用likes字段排序; # 只显示前5个字段; # 把列表存入context_dict字典,再把这个字典传给模板引擎; category_list = Category.objects.order_by('-likes')[:5] context_dict = {'categories': category_list} # 把context_dict字典传给模板引擎; return render(request, 'rango/index.html', context_dict)
接下来我们来编辑首页模板,在templates文件夹(位于项目根文件夹下)中创建一个rango文件夹,然后在该文件夹下新建一个index.html文件,加入如下内容:
rangoproject/templates/rango/index.html:
<!DOCTYPE html> <html> <head> <title>Rango</title> </head> <body> <h1>欢迎来到Rango!</h1> {% if categories %} <ul> {% for category in categories %} <li>` category`.`name `</li> {% endfor %} </ul> {% else %} <strong>目前还没有可用分类。</strong> {% endif %} </body> </html>
Tips:建议把所有的模板文件储存为UTF-8编码。
在{% if categories %} 这个语句中的categories ,就是我们视图里context_dict字典的数据,“if”是用来判断它是否存在。若存在,则用“for”语句把它逐条取出来——因为categories 是一个列表。
最后我们来设计URL,在rango文件夹下创建一个叫url.py的文件,然后添加如下内容:
rango/urls.py :
from django.conf.urls import patterns, url from rango import views urlpatterns = patterns('', url(r'^$', views.index, name='index'))
编辑rangoproject/urls.py 文件,让它变成下面这样:
rangoproject/urls.py :
from django.conf.urls import patterns, include, url from django.contrib import admin urlpatterns = patterns('', url(r'^admin/', include(admin.site.urls)), url(r'^rango/', include('rango.urls')), )
好了,让我们在浏览器中访问一下http://127.0.0.1:8000/rango/,你会看到这样的页面:
12.创建内容页
现在,分类是显示出来了,我们还希望用户进入分类后,能看到每个分类里的内容。
先编写视图,编辑rango/views.py 文件,先在头部加入一行:
rango/views.py:
from rango.models import Page
然后加入如下内容:
rango/views.py:
def category(request, category_name_slug): # 定义要传递给模板引擎的context_dict字典。 context_dict = {} try: # 是否能匹配到给定的分类别名? # 如果匹配不到,.get() 方法会提交一个DoesNotExist的异常; # 匹配到的话,我们就用它来在Page表中检索出该分类的数据; category = Category.objects.get(slug=category_name_slug) context_dict['category_name'] = category.name # 获取该分类下的所有页面; pages = Page.objects.filter(category=category) # 把获取到的数据存入context_dict; context_dict['pages'] = pages # 我们把分类名称也加入到context_dict中,这个值可用来在模板中校验分类是否存在。 context_dict['category'] = category except Category.DoesNotExist: # 如果找不到分类,那么啥都不做; # 模板会显示“没有分类”的信息; pass return render(request, 'rango/category.html', context_dict)
现在我们来创建模板,在templates/rango文件夹下新建一个category.html文件,加入如入内容:
rangoproject/templates/rango/category.html:
<!DOCTYPE html> <html> <head> <title>Rango</title> </head> <body> <h1>` category_name `</h1> {% if category %} {% if pages %} <ul> {% for page in pages %} <li><a href="` page`.`url `">` page`.`title `</a></li> {% endfor %} </ul> {% else %} <strong>当前分类下尚无可用页面.</strong> {% endif %} {% else %} 指定的分类名称 ` category_name ` 不存在! {% endif %} </body> </html>
接下来我们重新设计URL,编辑rango/url.py的文件,把它变成下面这样:
rango/urls.py :
from django.conf.urls import patterns, url from rango import views urlpatterns = patterns('', url(r'^$', views.index, name='index'), url(r'^category/(?P<category_name_slug>[\w\-]+)/$', views.category, name='category'), )
除了这些,我们还需要修改一下首页的模板,让分类名称加上链接。编辑index.html,把它改成这样:
rangoproject/templates/rango/index.html:
<!DOCTYPE html> <html> <head> <title>Rango</title> </head> <body> <h1>欢迎来到Rango!</h1> {% if categories %} <ul> {% for category in categories %} <!-- 下面这行给分类加入了超链接 --> <li><a href="/rango/category/` category`.`slug `">` category`.`name `</a></li> {% endfor %} </ul> {% else %} <strong>目前还没有可用分类。</strong> {% endif %} </body> </html>
我们来检查一下工作成果
我们先访问首页,你会看到首页中列出了当前所有的分类,这些分类都是超链接。我们点击“Django”分类,这样,Django分类中的所有页面都显示出来了,点击“Official Django Tutorial”链接,它将会把我们带到Django官方实例的页面。
13.练习
1)创建一个”about”视图,关联的模板文件为about.html;
2)模板的标题叫“关于Rango”,可自由添加一些文字,但需要插入一个叫rango.jpg的图片(图片下载地址请看part1),图片存放在static文件夹下。
【未完待续】
本文版权归舍得学苑所有,欢迎转载,转载请注明作者和出处。谢谢!
作者:舍得
首发:舍得学苑@博客园