到目前为止我们已经完成了一个django应用的所有基础部分。 包括url配置、视图、模型和模板。接下来开始继续完善我们的博客系统了。

首先我们需要一个显示每篇文章的详细页面,对不?

文章详情

对于首页每一篇文章,我们希望点击标题后可以进入该文章的阅读页面。修改post_list.html中的标题href如下:

  1. 1
  1. <h1><a href="{% url 'blog.views.post_detail' pk=post.pk %}">{{ post.title }}</a></h1>

我来详细解释下这个{% url ‘blog.views.post_detail’ pk=post.pk %},{% %} 表示使用django模板标签而不是普通的HTML文字,这里我们使用了url标签来生成真正的url链接。 blog.views.post_detail是视图的全路径。

url配置

我们希望文章详细页面的链接类似这样:http://127.0.0.1:8000/post/1/

修改blog/urls.py为下面的这样:

  1. 1
    2
    3
    4
    5
    6
    7
  1. from django.conf.urls import patterns, include, url
    from . import views
  2.  
  3. urlpatterns = patterns('',
    url(r'^$', views.post_list),
    url(r'^post/(?P<pk>[0-9]+)/$', views.post_detail),
    )

这个看起来有点复杂,我们来解释下:

  1. ^ 代表的是开始
  2. post/表示URL开始必须是post/
  3. (?P[0-9]+) – 这部分比较复杂。它表示一个命名参数pk, 它会捕获url中的这部分然后将它赋值给pk参数传递给视图。 [0-9]表示这部分必须是数字,+表示至少1个数字,也可以多个数字。
  4. / – 然后后面接/
  5. $ – URL的结尾

post_detail视图

现在去访问还会报错,因为我们还没有post_detail这个视图。现在我们开始定义它。

修改文件blog/views.py如下:

  1. 1
    2
    3
    4
    5
  1. from django.shortcuts import render, get_object_or_404
  2.  
  3. def post_detail(request, pk):
    post = get_object_or_404(Post, pk=pk)
    return render(request, 'blog/post_detail.html', {'post': post})

post_detail模板

然后再增加模板blog/templates/blog/post_detail.html:

  1. 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
  1. {% extends 'blog/base.html' %}
  2.  
  3. {% block content %}
    <div class="date">
    {% if post.published_date %}
    {{ post.published_date }}
    {% endif %}
    </div>
    <h1>{{ post.title }}</h1>
    <p>{{ post.text|linebreaks }}</p>
    {% endblock %}

这次我们还是采用模板继承方式,这里我们还用到了模板标签if,这是一个条件判断的标签。

OK,一切都已准备就绪,现在打开首页,然后点击任意一篇文章标题看下结果:

搞定!!

创建文章

最后一件事就是要实现文章创建和更新操作,这是博客系统最核心的功能。django自带的admin很酷,但是确很难定制和美化。 forms非常强大和自由,我们可以好好的利用它来实现我们需要的功能。

forms一个很好的特性就是它既能从头定义一个表单,也能创建一个ModelForm来将表单结果保存为一个模型。 而这正是我们想要的功能,我们可以创建一个ModelForm来将表单转换为一个Post模型。

表单对象的定义放在forms.py文件中。我们需要在blog文件夹中创建forms.py文件,结构如下:

  1. blog
  2. └── forms.py

在里面写入如下内容:

  1. 1
    2
    3
    4
    5
    6
    7
    8
  1. from django import forms
    from .models import Post
  2.  
  3. class PostForm(forms.ModelForm):
  4.  
  5. class Meta:
    model = Post
    fields = ('title', 'text',)

PostForm需要继承自forms.ModelForm,这样django就能实现某些神奇的效果。 在里面我们定义了元类Meta,然后指定model为Post,还有字段为title和text。 因为我们只需要对外暴露标题和内容,至于作者就是登陆用户了,而发布日期和创建日期就是提交时间。

下面我们要做的就是在view中使用我们的form,并在template中显示它。

我们继续走四个步骤:页面上添加链接, 外加“三部曲”。基本上每个新功能的增加时只需要增加这四个东东就行了。

增加链接

打开blog/templates/blog/base.html,在名字为page-header的div中添加一个新增文章的链接:

  1. 1
  1. <a href="{% url 'blog.views.post_new' %}" class="top-menu"><span class="glyphicon glyphicon-plus"></span></a>

这时候你的base.html应该是这样的:

  1. 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
  1. {% load staticfiles %}
    <html>
    <head>
    <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
    <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">
    <script src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
    <link href="http://fonts.googleapis.com/css?family=Lobster&subset=latin,latin-ext" rel="stylesheet" type="text/css">
    <link rel="stylesheet" href="{% static 'css/blog.css' %}">
    <title>Django Girls Blog</title>
    </head>
    <body>
    <div class="page-header">
    <a href="{% url 'blog.views.post_new' %}" class="top-menu"><span class="glyphicon glyphicon-plus"></span></a>
    <h1><a href="/">Django Girls Blog</a></h1>
    </div>
    <div class="content">
    <div class="row">
    <div class="col-md-8">
    {% block content %}
    {% endblock %}
    </div>
    </div>
    </div>
    </body>
    </html>

URL

打开blog/urls.py文件,添加一条配置:

  1. 1
  1. url(r'^post/new/$', views.post_new, name='post_new'),

现在它的内容应该是这样的:

  1. 1
    2
    3
    4
    5
    6
    7
    8
  1. from django.conf.urls import patterns, include, url
    from . import views
  2.  
  3. urlpatterns = patterns('',
    url(r'^$', views.post_list),
    url(r'^post/(?P<pk>[0-9]+)/$', views.post_detail),
    url(r'^post/new/$', views.post_new, name='post_new'),
    )

post_new视图

打开文件blog/views.py,先引入PostForm

  1. 1
  1. from .forms import PostForm

然后增加视图:

  1. 1
    2
    3
  1. def post_new(request):
    form = PostForm()
    return render(request, 'blog/post_edit.html', {'form': form})

post_edit.html模板

在blog/templates/blog目录新建一个post_edit.html页面,然后写入下列内容:

  1. 1
    2
    3
    4
    5
    6
    7
    8
    9
  1. {% extends 'blog/base.html' %}
  2.  
  3. {% block content %}
    <h1>New post</h1>
    <form method="POST" class="post-form">{% csrf_token %}
    {{ form.as_p }}
    <button type="submit" class="save btn btn-default">Save</button>
    </form>
    {% endblock %}

保存后,刷新首页,点击加号那个链接可以看到如下页面:

但是当你写了文字后点击保存后会发现又跑到这个新建页面来了。 因为这个是POST提交,但是URL还是一样的,又会跑到post_new那个视图中去, 这个视图只做了页面跳转来到了这个新建页面。

那么我们需要修改下post_new视图逻辑了:

在头部先引入下面的依赖:

  1. 1
    2
  1. from django.core.urlresolvers import reverse
    from django.shortcuts import redirect

然后修改post_new视图如下:

  1. 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
  1. def post_new(request):
    if request.method == "POST":
    form = PostForm(request.POST)
    if form.is_valid():
    post = form.save(commit=False)
    post.author = request.user
    post.save()
    return redirect('blog.views.post_detail', pk=post.pk)
    else:
    form = PostForm()
    return render(request, 'blog/post_edit.html', {'form': form})

上面表示我添加完一篇文章后自动跳转到文章详情页面去,保存后效果:

表单验证

由于我们在Post模型中已经定义了title和text是必需的,django会自动帮我们做验证。 看下如果我们不输入title和text直接提交会怎样:

django已经自动帮我们做了验证,是不是很酷呢?

编辑文章

我们刚刚已经实现了新建文章的功能,那么如果是编辑修改文章呢。接下来我会快速的讲解这个流程,现在你应该是可以看得懂的了。

首先打开blog/templates/blog/post_detail.html,添加一行:

  1. 1
    2
  1. <a class="btn btn-default" href="{% url 'post_edit' pk=post.pk %}">
    <span class="glyphicon glyphicon-pencil"></span></a>

现在它的内容是这样的:

  1. 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
  1. {% extends 'blog/base.html' %}
  2.  
  3. {% block content %}
    <div class="date">
    {% if post.published_date %}
    {{ post.published_date }}
    {% endif %}
    <a class="btn btn-default" href="{% url 'post_edit' pk=post.pk %}"><span class="glyphicon glyphicon-pencil"></span></a>
    </div>
    <h1>{{ post.title }}</h1>
    <p>{{ post.text|linebreaks }}</p>
    {% endblock %}

然后修改blog/urls.py文件,添加一条:

  1. 1
  1. url(r'^post/(?P<pk>[0-9]+)/edit/$', views.post_edit, name='post_edit'),

我们会重用模板blog/templates/blog/post_edit.html, 因此只需要修改下view就可以了,打开文件blog/views.py,将下面的内容添加到最后:

  1. 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
  1. def post_edit(request, pk):
    post = get_object_or_404(Post, pk=pk)
    if request.method == "POST":
    form = PostForm(request.POST, instance=post)
    if form.is_valid():
    post = form.save(commit=False)
    post.author = request.user
    post.save()
    return redirect('blog.views.post_detail', pk=post.pk)
    else:
    form = PostForm(instance=post)
    return render(request, 'blog/post_edit.html', {'form': form})

这个跟post_new几乎一模一样,先通过主键查到文章:post = get_object_or_404(Post, pk=pk), 然后我们在提交和进入编辑页面的时候都将post作为instance参数传递给PostForm。

OK,现在让我们来测试下效果:

完美,恭喜你!你的应用已经变得越来越酷了。

Django1.9开发博客(7)- 实现功能的更多相关文章

  1. Django1.7开发博客

    转自: http://www.pycoding.com/articles/category/django 基于最新的django1.7写的,通俗易懂,非常适合新手入门. 感谢博主! 参考教程: htt ...

  2. Django1.9开发博客(8)- 继续完善

    到现在为止我们已经完成的差不多了,并且基本的东西都已经学到了,是时候用起来了. 我们的博客还有很多功能需要完善,下面抛砖引玉新增几个功能,还有其他功能等你自己去发现和实现. 草稿箱 之前我们新建文章的 ...

  3. Django1.9开发博客(14)- 集成Xadmin

    xadmin是一个django的管理后台实现,使用了更加灵活的架构设计及Bootstrap UI框架, 目的是替换现有的admin,国人开发,有许多新的特性: 兼容 Django Admin 使用 B ...

  4. Django1.9开发博客(11)- 富文本与代码高亮

    TinyMCE是一个轻量级的基于浏览器的所见即所得编辑器,支持目前流行的各种浏览器,由JavaScript写成. 功能配置灵活简单(两行代码就可以将编辑器嵌入网页中),支持AJAX.另一特点是加载速度 ...

  5. Django1.9开发博客(12)- i18n国际化

    国际化与本地化的目的为了能为各个不同的用户以他们最熟悉的语言和格式来显示网页. Django能完美支持文本翻译.日期时间和数字的格式化.时区. 另外,Django还有两点优势: 允许开发者和模板作者指 ...

  6. Django1.9开发博客(13)- redis缓存

    Redis 是一个高性能的key-value数据库.redis的出现, 很大程度补偿了memcached这类keyvalue存储的不足,在部分场合可以对关系数据库起到很好的补充作用. 它提供了Pyth ...

  7. Django1.9开发博客(10)- 全文搜索

    Django本身不提供全文检索的功能,但django-haystack为其提供了全文检索的框架. django-haystack能为Django提供whoosh,solr,Xapian和Elastic ...

  8. Django1.9开发博客(9)- 用户认证

    你应该注意到了一点,当你去新建.修改和删除文章的时候并不需要登录,这样的话任何浏览网站的用户都能随时修改和删除我的文章.这个可不是我想要的! 编辑和删除的认证 我们需要保护post_new, post ...

  9. Django1.9开发博客(6)- 模板继承

    模板继承就是网站的多个页面可以共享同一个页面布局或者是页面的某几个部分的内容.通过这种方式你就需要在每个页面复制粘贴同样的代码了. 如果你想改变页面某个公共部分,你不需要每个页面的去修改,只需要修改一 ...

随机推荐

  1. FIO是测试IOPS

    FIO是测试IOPS的非常好的工具,用来对硬件进行压力测试和验证,支持13种不同的I/O引擎,包括:sync,mmap, libaio, posixaio, SG v3, splice, null, ...

  2. vertical-align属性

    准备阶段 vertical-align取值及含义: 值 含义 baseline 默认.元素放置在父元素的基线上. top 把元素的顶端与行中最高元素的顶端对齐 text-top 把元素的顶端与父元素字 ...

  3. 导入charts开源库到工程里面

    http://blog.csdn.net/zww1984774346/article/details/50608338 http://blog.csdn.net/zww1984774346/artic ...

  4. js插入拼接链接 --包含可变字段

    // newsId: 传参过来的Id, pathIdlet newsDetailId = parseInt(this.props.newsId); goTo() { window.location.h ...

  5. Java基础之扩展GUI——高亮元素、上下文菜单、移动旋转元素、自定义颜色(Sketcher 10)

    窗口应用程序. 本例在上一版的基础上实现了高亮元素.移动元素.上下文菜单.旋转元素.设置自定义颜色. 1.自定义常量包: // Defines application wide constants p ...

  6. jQuery的扩展与noConflict

    jQuery的扩展 noConflict

  7. install sublime for linux

    Download Your Free eBooks NOW - 10 Free Linux eBooks for Administrators Python API, that available f ...

  8. Excel应该这么玩——2、命名列:消除地址引用

    命名列:通过名称引用列,让公式更容易理解. 下面继续举上次的栗子. 1.历史遗留问题 之前虽然把数字编成了命名单元格,但其中还是有单元格地址B2.C2之类,要理解公式需要找到对应的列标题. 特别是像下 ...

  9. Scala入门学习笔记四--List使用

    前言 本篇将介绍一个和Array很相似的集合List,更多内容请参考:Scala教程 本篇知识点概括 List的构造 List与Array的区别 List的常用方法 List伴生对象的方法 ::和:: ...

  10. char类型的字节数

    java为:两个字节,C语言中为:1个字节