zoukankan      html  css  js  c++  java
  • 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是这个样子的

    View Code
    <!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中会用到的内容,比如导航栏、搜索框等

    View Code
    {% 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

    View Code
    {% 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 %}
    {% 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 %}
        {% block twitter %}
            <div id="weibo" class="well">
                {% for weibo in weibos %}
                    <p class="text-info">{{ weibo }}</p>
                    <p class="text-success"><small>{{ weibo.publish_time }}</small></p>
                    <hr class="soften">
                {% endfor %}
            </div>
        {% endblock %}
        {% 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

    View Code
    {% 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()

     然后修改视图

    blog_add
     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添加

    View Code
    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/

    ps: 大四学生求实习 邮箱: cacique1103#gmail.com


    作者:GoodSpeed Cheng
    出处:http://www.cnblogs.com/cacique/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。


  • 相关阅读:
    Java 应用性能调优实践
    Java序列化——实现Serializbale接口
    Bootstrap3快速使用
    C语言程序设计_zju——记录1
    《图解密码技术》——记录1
    电脑win10蓝屏,INACCESSIBLE BOOT DEVICE,处理方法
    读书笔记之《如何高效学习》
    读书笔记之《番茄工作法图解》
    读书笔记之《富爸爸与穷爸爸》
    读书笔记之《微习惯》
  • 原文地址:https://www.cnblogs.com/cacique/p/2709668.html
Copyright © 2011-2022 走看看