首页 > 代码库 > 实战Django:Rango Part2

实战Django:Rango Part2

 

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

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 slugifyclass 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 adminfrom rango.models import Category, Pageclass 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 pythonimport osimport djangodef 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 pdef 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”,可看到如下页面:

1

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

11.在首页上显示分类


我们来回顾一下,要完成某页面显示,需要做哪些操作?

  • 编写视图
  • 创建模板
  • 设计URL

下面我们来一一完成。先编辑rango/views.py 文件,让它变成下面这样:

rango/views.py

from django.shortcuts import renderfrom rango.models import Categorydef 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, urlfrom rango import viewsurlpatterns = patterns(‘‘,        url(r^$, views.index, name=index))

编辑rangoproject/urls.py 文件,让它变成下面这样:

rangoproject/urls.py

from django.conf.urls import patterns, include, urlfrom django.contrib import adminurlpatterns = patterns(‘‘,    url(r^admin/, include(admin.site.urls)),    url(r^rango/, include(rango.urls)),)

好了,让我们在浏览器中访问一下http://127.0.0.1:8000/rango/,你会看到这样的页面:

2

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, urlfrom rango import viewsurlpatterns = 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文件夹下。

 

【未完待续】

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

 

实战Django:Rango Part2