django 简易博客开发 3 静态文件、from 应用与自定义
首先还是贴一下源代码地址 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 Tag def 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 forms class 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 HttpResponseRedirect
from django.template import RequestContext
from sblog.models import Author
from sblog.forms import BlogForm def 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_data
10 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].id
22 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/
django 简易博客开发 1 安装、创建、配置、admin使用
http://www.cnblogs.com/cacique/archive/2012/09/29/2707976.html
django 简易博客开发 2 模板和数据查询
http://www.cnblogs.com/cacique/archive/2012/09/30/2709143.html
django 简易博客开发 3 静态文件、from 应用与自定义
http://www.cnblogs.com/cacique/archive/2012/10/01/2709668.html
django 简易博客开发 4 comments库使用及ajax支持
http://www.cnblogs.com/cacique/archive/2012/10/03/2710803.html
django 简易博客开发 5 markdown支持、代码高亮、gravatar头像服务
http://www.cnblogs.com/cacique/archive/2012/10/07/2713703.html
django 简易博客开发 3 静态文件、from 应用与自定义的更多相关文章
- django 简易博客开发 5 markdown支持、代码高亮、gravatar头像服务
上一篇博客介绍了comments库使用及ajax支持,现在blog已经具备了基本的功能,但是只能发表文字,不支持富文本编辑.今天我们利用markdown添加富文本支持. markdown语法说明: h ...
- django 简易博客开发 4 comments库使用及ajax支持
首先还是贴一下源代码地址 https://github.com/goodspeedcheng/sblog 上一篇文章我们介绍了静态文件使用以及如何使用from实现对blog的增删改,这篇将介绍如何给 ...
- django 简易博客开发 2 模板和数据查询
首先还是贴一下项目地址 https://github.com/goodspeedcheng/sblog 因为代码全在上面 上一篇博客我们介绍了 django的安装配置,新建project,新建a ...
- django 简易博客开发 1 安装、创建、配置、admin使用
首先贴一下项目地址吧 https://github.com/goodspeedcheng/sblog 到现在位置项目实现的功能有: 1.后台管理使用Admin ,前端显示使用bootstrap 2. ...
- django 简易博客开发 1 安装、创建、配置、admin使用(转)
Django 自称是“最适合开发有限期的完美WEB框架”.本文参考<Django web开发指南>,快速搭建一个blog 出来,在中间涉及诸多知识点,这里不会详细说明,如果你是第一次接触D ...
- Django个人博客开发 | 前言
本渣渣不专注技术,只专注使用技术,不是一个资深的coder,是一个不折不扣的copier 1.前言 自学 Python,始于 Django 框架,Scrapy 框架,elasticsearch搜索引擎 ...
- 简易博客开发(8)----django1.9 博客部署到pythonanywhere上
准备工作 首先需要注册一下,pythonanywhere的免费账户有一定的限制,只能创建一个web app,不能绑定独立域名,不能通过ssh连接,不过只是搭一个project也是够用了. 注册成功之后 ...
- Django练习——博客系统小试
在上一篇博客Todolist的基础上(http://blog.csdn.net/hcx25909/article/details/24251427),本周继续进行实践,这次我要搭建一个简单的博客系统. ...
- Django搭建简易博客
Django简易博客,主要实现了以下功能 连接数据库 创建超级用户与后台管理 利用django-admin-bootstrap美化界面 template,view与动态URL 多说评论功能 Markd ...
随机推荐
- dircolors - 设置‘ls'显示结果的颜色
SYNOPSIS[总览] dircolors [-b] [--sh] [--bourne-shell] [-c] [--csh] [--c-shell] [-p] [--print-database] ...
- Win10本地搭建Apache+PHP运行环境
微软全新操作系统Windows10在190个国家和地区正式同步上市,正版Windows7.Windows8.1用户均可在一年内免费升级.介绍一下在升级后的Windwos10系统上安装及配置Apache ...
- 《少年先疯队》第九次团队作业:Beta冲刺第三天
3.1 今日完成任务情况 姚玉婷:酒店系统中剩余功能的完善 马丽莎:酒店系统中管理员功能的测试 张 琼:酒店系统中会员功能的测试 孙苗坤:酒店系统中其余管理功能的测试文档的编写 3.2 成员贡献时 ...
- 【传智播客】Libevent学习笔记(二):创建event_base
目录 00. 目录 01. 简介 02. 创建默认的event_base 03. 创建复杂的event_base 3.1 event_config_new函数 3.2 event_base_new_w ...
- UVa-1585-得分
#include <stdio.h> #include <string.h> int main() { char s[100]; int T; scanf("%d&q ...
- IDEA ctrl+alt+L 格式化快捷键无效时解决
这几天发现自己Intellij IDEA ctrl+alt+L格式化代码无效 设置里面按照快捷键搜索 按了 ctrl+alt+L 也没反应 但是我设置的确实是默认的 ctrl+alt+L 最后终于找到 ...
- 树莓派 Centos7 安装EPEL 7
cat > /etc/yum.repos.d/epel.repo << EOF [epel] name=Epel rebuild for armhfp baseurl=https:/ ...
- Linux 之 nano 编辑器的使用
在Linux操作系统中,有很多的文本编辑器,最为重要的就是vi文本编辑器,下面来介绍一个简单的nano文本编辑器.nano的使用简单,我们可以直接加上文件名就能够打开一个旧文件或新文件,我们可以打开一 ...
- 13. OPTIMIZER_TRACE
13. OPTIMIZER_TRACE OPTIMIZER_TRACE表提供由跟踪语句的优化程序跟踪功能生成的信息. 要启用跟踪,请使用optimizer_trace系统变量. 有关详细信息,请参阅M ...
- ThinkPHP foreach标签
$optionvalue = array( 'MSGTYPE_TEXT'=>'文本消息', 'MSGTYPE_EVENT_SCAN'=>'扫描事件', 'MSGTYPE_EVENT_sub ...