在这一节,我们将学习如何用自动脚本来添加内容,然后给我们的应用添加首页和一个内容页。

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”,可看到如下页面:

实战Django:Rango Part2_用户

写这样一个脚本虽然要花上一点时间,但你若是在一个团队中做这个项目,你可以把这个脚本分发给团队中的其他人,那样,他们就可以很快创建好数据库。此外,这个脚本在测试中亦会派上用场。

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/,你会看到这样的页面:

实战Django:Rango Part2_用户_02

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官方实例的页面。

 

实战Django:Rango Part2_用户_03

 

13.练习


1)创建一个”about”视图,关联的模板文件为about.html;

2)模板的标题叫“关于Rango”,可自由添加一些文字,但需要插入一个叫rango.jpg的图片(图片下载地址请看part1),图片存放在static文件夹下。

 

【未完待续】

本文版权归舍得学苑所有,欢迎转载,转载请注明作者和出处。谢谢!
作者:舍得
首发:舍得学苑@博客园