基于Django开发的SkyNet博客四——编辑界面

基于Django开发的SkyNet博客一——创建模型
基于Django开发的SkyNet博客二——base Template
基于Django开发的SkyNet博客三——登录注册界面
代码传送门 这是我这个项目的github代码库,目前项目正在更新,所以代码不是很全。
上一篇博客主要讲了博客的登录注册界面,这一节想先修改一下上一节的登录修改该界面,先来个图吧:

登录注册界面.png

这样修改主要是因为看到很多网站的登录注册都在一个html上,那么我也就改了一下。改动也不多,主要是html和views.py中修改了一丢丢

{% extends 'blog/base.html' %}
{% block title %}
    SkyNet登录
{% endblock %}
{% block content %}
    {% load static %}
    <link rel="stylesheet" href="{% static 'blog/css/form.css' %}" type="text/css">
    <script type="text/javascript" src="{% static 'blog/js/login.js' %}"></script>
    <div class="ui middle aligned center aligned grid">
        <div class="column">
            <div class="ui stacked segment">
                <div class="ui two item menu">
                    <a class="item {% if islogin %} active {% endif %}" href="{% url 'blog:login' %}">登录</a>
                    <a class="item {% if not islogin %} active {% endif %}" href="{% url 'blog:register' %}">注册</a>
                </div>
                {% if islogin %}
                    <div id="login-div">
                        <form class="ui login form segment" method="post">

                            <div class="field">
                                <div class="ui input">
                                    <input type="text" placeholder="邮箱或昵称" name="name">
                                </div>
                            </div>
                            <div class="field">
                                <div class="ui input">
                                    <input type="password" placeholder="密码" name="pwd">
                                </div>
                            </div>
                            <div class="ui fluid large teal submit button">登录</div>
                        </form>
                        </div>
                    {% else %}
                        <div id="register-div">
                            <form class="ui register form segment" method="post">
                                <div class="field">
                                    <div class="ui input">
                                        <input type="text" placeholder="昵称" name="name">
                                    </div>
                                </div>
                                <div class="field">
                                    <div class="ui input">
                                        <input type="text" placeholder="邮箱" name="email">
                                    </div>
                                </div>
                                <div class="field">
                                    <div class="ui input">
                                        <input type="password" placeholder="密码" name="pwd">
                                    </div>
                                </div>
                                <div class="field">
                                    <div class="ui input">
                                        <input type="password" placeholder="再次输入密码" name="pwd2">
                                    </div>
                                </div>

                                <div class="ui fluid large teal submit button">提交</div>
                            </form>
                        </div>
                    {% endif %}
            </div>
        </div>
    </div>
{% endblock %}

其实改动的并不多,在上一篇的基础上合并了两个html,添加了一个menu

<div class="ui two item menu">
    <a class="item {% if islogin %} active {% endif %}" href="{% url 'blog:login' %}">登录</a>
    <a class="item {% if not islogin %} active {% endif %}" href="{% url 'blog:register' %}">注册</a>
</div>

two item menu会将menu分为平分为两个部分,然后通过views.py传过来的islogin,来判断是否该item是否是active,同样也可控制显示登录窗口还是注册窗口。


其他的地方改动都很小,主要是views.py中login和register最后返回的时候返回一个islogin参数即可

@csrf_exempt
def login(request):
    if request.method == 'POST':
       //和上一篇博客中代码一致
       ......
    return render(request, 'blog/login.html',{"islogin":True})

登录注册界面就到这里了。


下面就开始来创建博客编辑界面了。
同样的先上个图

文章编辑.png

在博客二中的banner上有个写文章的按钮


banner-edit.png
//base.html
<div class="item">
    <button id="create_blog" class="ui primary button">写文章</button>
</div>

在js中对该button的click时间进行了监听

//base.js
$("#create_blog").on("click", function () {
    $.ajax({
        type: "get",
        url: "/blog/create_blog/",
        success: function (data) {
            jsonobj = JSON.parse(data);
            if(jsonobj.error == 1) {
                window.location.href = '/blog/login';
            }else {
                window.location.href = '/blog/edit/' + jsonobj.id;
            }
        }
    });
});

这段代码的主要意图是点击写文章按钮后,通过后台传递的error值来判断用户是否登录,重定向到登录界面,若已登录则重定向到编辑界面。
首先来看一下create_blog方法

//blog/urls.py
url(r'^create_blog', create_blog, name='create'),
def create_blog(request):
    if request.user.is_authenticated:
        blog = Blog.objects.create(user=request.user)
        return HttpResponse(simplejson.dumps({'error': 0, 'id': blog.pk}, ensure_ascii=False))
    else:
        return HttpResponse(simplejson.dumps({'error': 1}, ensure_ascii=False))

在这里我将models.py中的blog模型改动了一下,所有的值都有默认值,在创建的时候只需要传递user即可。下面看一下blog models

class Blog(models.Model):
    POST_STATUS = (
        ('P', '已发布'),
        ('D', '已删除'),
        ('E', '正在编辑'),
    )

    title = models.CharField('标题',max_length=150,default="无标题文章")
    body = models.TextField('正文',blank=True,default="")
    create_time = models.DateTimeField('创建时间',auto_now_add=True)
    modify_time = models.DateTimeField('最后一次修改',auto_now=True)
    status = models.CharField('文章状态',max_length=1, choices=POST_STATUS,default='E')
    views = models.PositiveIntegerField('浏览量', default=0)
    likes = models.PositiveIntegerField('喜欢', default=0)
    praises = models.PositiveIntegerField('点赞', default=0)
    category = models.ManyToManyField('Category',symmetrical=False,blank=True)
    user = models.ForeignKey('User',verbose_name='作者')

当页面重定向到编辑界面后,也就是上面第一章图的效果。

//urls.py
url(r'^edit/(?P<blog_id>\d+)', EditBlogView.as_view(), name='edit'),

这里url的定义使用到了TemplateView,也就是封装好的view请求,只是开放一些接口,参数而已。先看一下吧。

class EditBlogView(DetailView):
    model = Blog
    template_name = 'blog/user/edit.html'
    pk_url_kwarg = 'blog_id'
    context_object_name = 'blog'

    def get_context_data(self, **kwargs):
        context = super(EditBlogView, self).get_context_data(**kwargs)
        blogs = self.request.user.blog_set.all()
        context['blogs'] = blogs
        return context

  1. 继承DetailView,展示文章详情,一般用来查询单个数据。
  2. model即指定的model,将在该model中进行数据查询,template_name即指定查询结束将数据展示的模板中,pk_url_kwarg指查询的条件,context_object_name指定查询返回的结果。
  3. get_context_data一般用来传递额外的数据,这里我将该用户的所有文章传递给了EditBlogView,用来制作文章列表显示。

来看一下界面结构

{% extends 'blog/base.html' %}
{% block title %}
    文章编辑
{% endblock %}
{% block header %}
{% endblock %}
{% block content %}
    {% load static %}
    <link rel="stylesheet" href="{% static 'blog/css/edit.css' %}" type="text/css">
    <script type="text/javascript" src="{% static 'blog/js/edit.js' %}"></script>
    <i id="blog-id" data-index="{{ blog.pk }}" hidden></i>
    <div id="back-index">
        <a href="{% url 'blog:uindex' request.user.pk %} " class="ui primary button">返回主页</a>
    </div>

    {% include 'blog/util/bloglist.html' %}
    <div class="ui center aligned grid">
        <div class="column">
            <div class="ui menu">
                <a id="blog_list" class="item">文章列表</a>
                <div class="right menu">
                    <a id="save_blog" class="ui item">保存</a>
                    <a class="ui item">发布</a>
                </div>
            </div>
            <form class="ui large form">
                <div class="ui stacked segment">

                    <div class="field">
                        <div class="ui input">
                            <input id="title" type="text" placeholder="标题" name="title" value="{{ blog.title }}">
                        </div>
                    </div>
                    <div class="field">

                    </div>
                    <div class="field">
                        <div class="ui input">
                            <textarea id="body" name="body" rows="15">{{ blog.body }}</textarea>
                        </div>
                    </div>
                </div>
            </form>
        </div>
    </div>
{% endblock %}

在这里我将主界面分为两栏,一个是菜单栏,剩下的是标题和内容栏,其中内容列表使用的是{% include %}方式引入一个html。include和extends用法相同,include引入的话,可以将页面中的功能独立出去,这样能够保证页面的整体结构。

先来看一下保存按钮功能

$("#save_blog").on("click",function () {
    var $save_msg = $("<a class='ui item'>正在保存</a>");
    $(".right.menu").prepend($save_msg)
    var id = $("#blog-id").attr("data-index");
    var title = $("#title").val();
    var body = $("#body").val();
    $.ajax({
        type:"get",
        url:'../save_blog/'+id,
        data:{
            'title':title,
            'body':body
        },
        success:function (data) {
            $save_msg.text("已保存");
            $save_msg.animate({
                opacity:0,
            },2000,function () {
                $(".right.menu").remove($save_msg);
            });
        }
    })
});

在这里我添加了一个正在保存的item,然后想后台请求保存数据,最后保存成功则显示已保存,然后慢慢消失,最后删除item。

def save_blog(request, blog_id):
    blog = Blog.objects.get(pk=blog_id)
    blog.title = request.POST.get('title')
    blog.body = request.POST.get('body')
    print(blog.title,blog.body)
    blog.save()
    return HttpResponse()

由于这里不需要向前台传递数据,直接返回HttpResponse即可。


最后再展示一下sidebar的代码吧

//bloglist.html
{% load static %}
<link rel="stylesheet" type="text/css" href="{% static 'blog/css/util/bloglist.css' %}">
<div id="left-menu" class="ui sidebar vertical menu">
    <div class="item">
        <a>返回首页</a>
    </div>
    {% for blog in blogs %}
        <div id="menu-item" class="item">
            <a data-index="{{ blog.index }}">{{ blog.title }}</a>
            <i class="trash icon"></i>
        </div>
    {% endfor %}
</div>

//edit.js
$("#blog_list").click(function () {
    $(".ui.sidebar")
        .sidebar('setting', 'transition', 'overlay')
        .sidebar('toggle');
});

编辑界面就先写到这里了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,826评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,968评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,234评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,562评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,611评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,482评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,271评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,166评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,608评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,814评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,926评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,644评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,249评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,866评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,991评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,063评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,871评论 2 354

推荐阅读更多精彩内容