django 简易博客开发 3 静态文件、from 应用与自定义

来源:互联网 发布:怎样使用ps软件 编辑:程序博客网 时间:2024/04/28 07:16

首先还是贴一下源代码地址  https://github.com/goodspeedcheng/sblog   

上一篇博客我们介绍了 django 如何在views中使用templates以及一些常用的数据操作,这篇博客将介绍静态文件的使用、from 应用与自定义

1、静态文件的使用

鉴于我们上次所看到的界面惨不忍睹,为了不影响心情,先介绍一下如何使用静态文件美化界面

首先新建static目录,目录下新建css/js/img三个目录

修改seeting.py文件

STATICFILES_DIRS = (    '/home/gs/blog/static',   #替换成自己的static 目录)

修改blog目录下 urls.py 添加以下内容

urlpatterns += patterns((''),    (r'^static/(?P<path>.*)$', 'django.views.static.serve',            {'document_root': '/home/gs/blog/static'}    ),)

当然这只是本机测试环境下的使用方法,生产环境这样部署是不可以的。

2、使用bootstrap美化界面

为了方便,我们使用bootstrap进行界面优化,如果你想自己写界面,这一步完全可以跳过去

bootstrap 下载地址 http://twitter.github.com/bootstrap/

中文文档:http://wrongwaycn.github.com/bootstrap/docs/index.html

 

bootstrap使用非常方便下载解压后 将其中的css/js/img 目录中文件分别放入static目录下相应文件夹就好了,然后修改base.html,在head标签添加

<link rel="stylesheet" href="/static/css/bootstrap.css"><link rel="stylesheet" href="/static/css/reset.css"><link rel="stylesheet" href="/static/css/style.css"><link rel="stylesheet" href="/static/css/code.css"><script src="/static/js/modernizr.js"></script><script src="/static/js/jquery.js"></script>

因为bootstrap需要jquery支持,所以必须要引入jquery ,因为我们使用的html5,使用modernizr会自动检测不兼容的浏览器利用js添加相应的功能。

在body添加

<script src="/static/js/bootstrap.min.js"></script>

现在base.html是这个样子的

复制代码
<!DOCTYPE html><html><head>    <meta charset="UTF-8" />    <title>        {% block title %}{% endblock %}            </title>    <link rel="stylesheet" href="/static/css/bootstrap.css">    <script src="/static/js/modernizr.js"></script>    <script src="/static/js/jquery.js"></script>    {% block extra_head %}    {% endblock %}</head><body>    {% block body %}        {% block header %}            {# 任何每个页面都可能修改的文本区域的页面 #}            {% block menu %}            {# 你的菜单 (导航栏) 应该包含在这个区块中. 它是针对站点级的导航, 不是 每个页面专属的导航菜单. #}            {% endblock %}        {% endblock %}        <div class="container">        {% block content %}            {# 这个区块用来放置页面正文内容. 任何页面正文内容都可能不一样. 它不 包含任何站点导航, 信息头, 页脚, 或其它任何属于 base 模板的东东. #}            <div class="container-fluid">                <div class="row-fluid">                    <div class="span9">                                                    {% block article %}                            {% block article_title %}                                {% comment %}                                用来指定 content 区块的 "title". 比如 blog 的标题.                                 也可以用来 包含 content 内的导航 (译注: 比如提纲), 或其它类似的东东.                                 大致都是些 页面中并非主要内容的东东.                                 我不知道这个区块是否应该放到 content tag 内, 并且对应于前面建议的 content tag,                                 是不是还需要一个 main_content 区块.                                {% block [section]_menu %} {% block page_menu %}                                这是对应于之前建议的 menu 区块. 用来导航一个章节或页面.                                {% endcomment %}                            {% endblock %}                            {% block article_content %}{% endblock %}                        {% endblock %}                                                {% block article_menu %} {% endblock %}                        {% block comments %} {% endblock %}                        </div>                        <div class="span3">                            {% block aside %}                                {% block tags %}{% endblock %}                            {% endblock %}                        </div>                    </div>                </div>            {% endblock %}            {% block footer %}                {# 任何每个页面都可能修改的文本区域的页脚 #}                <p>Thanks for visiting my site! </p>            {% endblock %}        {% endblock %}    </div>    <script src="/static/js/bootstrap.min.js"></script></body> </html>
复制代码

因为base.html中block越多以后越方便,所以我添加了一些标签,可以暂时忽略

其中用到了bootstrap的布局,阅读文档吧: http://twitter.github.com/bootstrap/scaffolding.html

然后新建一个blog_base.html文件,添加blog中会用到的内容,比如导航栏、搜索框等

复制代码
{% extends "base.html" %}{% block extra_head %}    <style>        body {            padding-top: 60px; /* 60px to make the container go all the way to the bottom of the topbar */      }    </style> {% endblock %}   {% block header %}    {% block menu %}    <div class="navbar navbar-inverse navbar-fixed-top">        <div class="navbar-inner">            <div class="container">                  <a class="brand" href="#">BLOG</a>                <ul class="nav">                    <li class="active divider-vertical">                        <a href="{% url bloglist %}">home</a>                    </li>                    <li>                        <a href="#">about</a>                    </li>                    <li>                        <a href="#">contact</a>                    </li>                </ul>                                 </div>                        </div>    </div>        {% endblock %}{% endblock %}
复制代码

修改blog_list.html 文件和blog_show.html文件以适应bootstrap 

blog_list.html

 

复制代码
{% extends "blog_base.html" %}{% load comments %}{% block title %} blog list {% endblock %}{% block article %}<article class='content-main'>    {% for blog in blogs %}        <h4><a href="{% url detailblog blog.id %}">{{ blog.caption }}</a></h4>        <p class="muted">            {% for tag in blog.tags.all %}                <i class="icon-tag"></i> <small>{{ tag }}</small>            {% endfor %}        </p>        {% load markup %}        <div>{{ blog.content|markdown:'codehilite' }} </div>        <div class="row-fluid">            <div class="span3">                <p class="muted"><i class="icon-time"></i><small> {{ blog.publish_time }}</small></p>            </div>            <div class="span2 offset7">                <a href="{% url delblog blog.id %}" title="delete"><i class="icon-trash"></i></a>                <a href="{% url updateblog blog.id %}" title="edit"><i class="icon-edit"></i></a>                {% get_comment_count for blog as comment_count %}                <a href="{% url detailblog blog.id %}#cmt" title="comment"><i class=" icon-comment"></i>{{ comment_count }}</a>            </div>        </div>    <hr>    {% endfor %}</article>{% endblock %}{% block aside %}       <a class="btn" href="{# {% url addblog %} #}"><i class="icon-plus"></i> add new blog</a>    {% block tags %}        <div class="well">            {% for tag in tags %}            <span class="label"><a href="{% url filtrblog tag.id %}">{{ tag }}</a></span>            {% endfor %}        </div>    {% endblock %}{% endblock %}
复制代码

 

 

 

其中

<a class="btn" href="{# {% url addblog %} #}"><i class="icon-plus"></i> add new blog</a>

是接下来要说的添加文章的操作

{% for tag in tags %}    <span class="label"><a href="{% url filtrblog tag.id %}">{{ tag }}</a></span>{% endfor %}

需要在urls.py文件添加

url(r'^blog/tag/(?P<id>\d+)/$', 'blog_filter', name='filtrblog'),

然后添加view

复制代码
from sblog.models import Tagdef blog_filter(request, id=''):    tags = Tag.objects.all()    tag = Tag.objects.get(id=id)    blogs = tag.blog_set.all()    return render_to_response("blog_filter.html",        {"blogs": blogs, "tag": tag, "tags": tags})
复制代码

blog_show.html

复制代码
{% extends "blog_base.html" %}{% block title %} {{ blog.caption }} {% endblock %}{% block article %} <div class="content">    <article class="content-main">    {% block article_title %}        <h2>{{ blog.caption }}</h2>    {% endblock %}    <p class="muted">        <i class="icon-user"></i><small> {{ blog.author }}</small>          <i class="icon-time"></i><small> {{ blog.publish_time }}</small>    </p>        <section>        <div class="blog-content">            {% block article_content %}                {{ blog.content }}            {% endblock %}         </div>    </section>    <section>        <div class="row-fluid post-info">            <div class="span3">                <p>                      <i class="icon-tag"></i>                    {% for tag in blog.tags.all %}                         <small class="muted"> {{ tag }} </small>                    {% endfor %}                </p>              </div>            <div class="span2 offset7">                <a href="{% url delblog blog.id %}" title="delete"><i class="icon-trash"></i></a>                <a href="{% url updateblog blog.id %}" title="edit"><i class="icon-edit"></i></a>                <a href="#cmt" title="comment"><i class=" icon-comment"></i></a>            </div>        </div>    <hr>    </section>        </article>    <hr></div>    {% endblock %}
复制代码

这其中

复制代码
<section>        <div class="row-fluid post-info">            <div class="span3">                <p>                      <i class="icon-tag"></i>                    {% for tag in blog.tags.all %}                         <small class="muted"> {{ tag }} </small>                    {% endfor %}                </p>              </div>            <div class="span2 offset7">                <a href="{% url delblog blog.id %}" title="delete"><i class="icon-trash"></i></a>                <a href="{% url updateblog blog.id %}" title="edit"><i class="icon-edit"></i></a>                <a href="#cmt" title="comment"><i class=" icon-comment"></i></a>            </div>        </div>    <hr>    </section>  
复制代码

是我们接下来要说的对blog的修改、删除等操作

 

3、表单的使用及自定义

通过钱两部,我们美化了一下界面,现在让我们来添加功能吧。

要实现添加博客的功能,我们必须要用到表单。

Django带有一个form库,称为django.forms,这个库可以处理我们本章所提到的包括HTML表单显示以及验证。当然我们现在有两个选择

  • 自己写,完成表单显示以及验证
  • 使用django提供的From

这里我们选择后者,既然我们选择了django,为什么还要重复的造轮子呢?

Form文档在此 https://docs.djangoproject.com/en/dev/topics/forms/ 我就不再介绍了,直接说怎么用吧。

首先修改urls.py 文件添加 

url(r'^blog/add/$', 'blog_add', name='addblog'),

然后在sblog目录下新建forms.py文件

from django import formsclass BlogForm(forms.Form):    caption = forms.CharField(label='title', max_length=100)    content = forms.CharField(widget=forms.Textarea)

这里我们只博客的标题和内容

CharField 表示字符类型    当你在本地显示这个表单的时,
content字段被显示成`` input type=”text”`` ,而它应该被显示成<`` textarea`` >。我们可以通过设置* widget* 来修改它

然后新建blog_add.html

复制代码
 1 {% extends "blog_base.html" %} 2  3 {% block title %} 发布文字 {% endblock %}    4  5  6 {% block article %}  7  8 <form action="" method="post"> 9     {% csrf_token %} 10     <div class="field">11         <label for="id_caption">Title: </label>12         {% if form.caption.errors %}13         <div class="alert alert-error">14             {{ form.caption.errors }}          15         </div>16         {% endif %}17         {{ form.caption }}18     </div>19     <div class="field">        20         <label for="id_content">Content: </label>21         {% if form.content.errors %}22         <div class="alert alert-error">23             {{ form.content.errors }}24         </div>25         {% endif %}26         {{ form.content }}27     </div>28     <div class="form-actions">29         <input class="btn btn-primary" type="submit" value="save and add">30     </div>31 </form>32 {% endblock %}
复制代码

添加views

复制代码
from django.http import HttpResponseRedirectfrom django.template import RequestContextfrom sblog.models import Authorfrom sblog.forms import BlogFormdef blog_add(request):    if request.method == 'POST':        form = BlogForm(request.POST)        if form.is_valid():            cd = form.cleaned_data            title = cd['caption']            author = Author.objects.get(id=1)            content = cd['content']            blog = Blog(caption=title, author=author, content=content)            blog.save()            id = Blog.objects.order_by('-publish_time')[0].id            return HttpResponseRedirect('/sblog/blog/%s' % id)    else:        form = BlogForm()    return render_to_response('blog_add.html',        {'form': form}, context_instance=RequestContext(request))
复制代码

使用 form的is_valid()方法,验证它的数据是否合法,如果一个Form实体的数据是合法的,它就会有一个可用的cleaned_data属性。 这是一个包含干净的提交数据的字典。

这里我们默认作者是id=1,当然你也可以自己修改或者根据登录的session读取

博客提交后 使用HttpResponseRedirect 跳转到最新发表的博客页面

因为我们使用的是post 所以必须在表单后面添加 {% csrf_token %} 

然后在视图中使用  context_instance=RequestContext(request)

 

现在你会发现我们并没有使用tags,好吧,现在我们添加 tag标签功能

首先修改forms.py文件 添加

class TagForm(forms.Form):    tag_name = forms.CharField()

 然后修改视图

复制代码
 1 from sblog.forms import TagForm 2  3 def blog_add(request): 4     if request.method == 'POST': 5         form = BlogForm(request.POST) 6         tag = TagForm(request.POST) 7         if form.is_valid() and tag.is_valid(): 8             cd = form.cleaned_data 9             cdtag = tag.cleaned_data10             tagname = cdtag['tag_name']11             for taglist in tagname.split():12                 Tag.objects.get_or_create(tag_name=taglist.strip())13             title = cd['caption']14             author = Author.objects.get(id=1)15             content = cd['content']16             blog = Blog(caption=title, author=author, content=content)17             blog.save()18             for taglist in tagname.split():19                 blog.tags.add(Tag.objects.get(tag_name=taglist.strip()))20                 blog.save()21             id = Blog.objects.order_by('-publish_time')[0].id22             return HttpResponseRedirect('/sblog/blog/%s' % id)23     else:24         form = BlogForm()25         tag = TagForm(initial={'tag_name': 'notags'})26     return render_to_response('blog_add.html',27         {'form': form, 'tag': tag}, context_instance=RequestContext(request))
复制代码
for taglist in tagname.split():    Tag.objects.get_or_create(tag_name=taglist.strip())

表示将得到的tag字符串用空格分割开 并删除多余空格 

get_or_create表示首先获取tag_name 如果存在就不操作,不存在就创建

在blog_add.html 文件合适的位置 添加

复制代码
<div class="field">        <label for="id_tag">tags</label>        {% if tag.tag_name.errors %}        <div class="alert alert-error">            {{ tag.tag_name.errors }}        </div>        {% endif %}        {{ tag.tag_name }} </div>
复制代码

现在刷新 http://127.0.0.1:8080/sblog/blog/add/ 是不是看到tag输入框了,(添加多个标签使用空格隔开)

 

4、更新文章内容

修改urls.py文件 添加

url(r'^blog/(?P<id>\w+)/update/$', 'blog_update', name='updateblog'),

 

因为更新和添加所需表单内容相同,这里就直接使用blog_add.html 作为update的模板

 在views.py添加

复制代码
def blog_update(request, id=""):    id = id    if request.method == 'POST':        form = BlogForm(request.POST)        tag = TagForm(request.POST)        if form.is_valid() and tag.is_valid():            cd = form.cleaned_data            cdtag = tag.cleaned_data            tagname = cdtag['tag_name']            tagnamelist = tagname.split()            for taglist in tagnamelist:                Tag.objects.get_or_create(tag_name=taglist.strip())            title = cd['caption']            content = cd['content']            blog = Blog.objects.get(id=id)            if blog:                blog.caption = title                blog.content = content                blog.save()                for taglist in tagnamelist:                    blog.tags.add(Tag.objects.get(tag_name=taglist.strip()))                    blog.save()                tags = blog.tags.all()                for tagname in tags:                    tagname = unicode(str(tagname), "utf-8")                    if tagname not in tagnamelist:                        notag = blog.tags.get(tag_name=tagname)                        blog.tags.remove(notag)            else:                blog = Blog(caption=blog.caption, content=blog.content)                blog.save()            return HttpResponseRedirect('/sblog/blog/%s' % id)    else:        try:            blog = Blog.objects.get(id=id)        except Exception:            raise Http404        form = BlogForm(initial={'caption': blog.caption, 'content': blog.content}, auto_id=False)        tags = blog.tags.all()        if tags:            taginit = ''            for x in tags:                taginit += str(x) + ' '            tag = TagForm(initial={'tag_name': taginit})        else:            tag = TagForm()    return render_to_response('blog_add.html',        {'blog': blog, 'form': form, 'id': id, 'tag': tag},        context_instance=RequestContext(request))
复制代码

其中

复制代码
for taglist in tagnamelist:    blog.tags.add(Tag.objects.get(tag_name=taglist.strip()))    blog.save()tags = blog.tags.all()for tagname in tags:    tagname = unicode(str(tagname), "utf-8")    if tagname not in tagnamelist:        notag = blog.tags.get(tag_name=tagname)        blog.tags.remove(notag)
复制代码

作用是将tag与blog关联,并且去掉原有关联修改后不关联的tag 例如blog1 原有tag为1,2 ,3 修改后为2, 3 

这里的作用是去除blog1与tag 1的关联

5、删除文章

修改urls.py 添加

url(r'^blog/(?P<id>\w+)/del/$', 'blog_del', name='delblog'),

修改views.py 添加

复制代码
def blog_del(request, id=""):    try:        blog = Blog.objects.get(id=id)    except Exception:        raise Http404    if blog:        blog.delete()        return HttpResponseRedirect("/sblog/bloglist/")    blogs = Blog.objects.all()    return render_to_response("blog_list.html", {"blogs": blogs})
复制代码

完成后发现我们并没有相关的update delete 链接

将第二步中的注释去掉吧 现在刷新 blog show 页面是否看到了呢

 

最后源代码可以在  https://github.com/goodspeedcheng/sblog 可以看一下 希望大家把错误的地方提出纠正一下。

                                                                                                                                                       谢谢

以上 关于from的内容能在 django book 2    第七章找到

扩展阅读: https://docs.djangoproject.com/en/1.4/

 http://twitter.github.com/bootstrap/index.html

推荐 Django 最佳实践 - 中文版  https://github.com/brantyoung/zh-django-best-practices/blob/master/readme.rst/

0 0