月度归档:2016年11月

Django博客系统开发06

用户登录

博客作为内容管理系统(CMS)的一种形式,也应当具有CMS的两个功能:内容管理、权限管理。在之前的几篇中,我们已经实现了内容管理。现在实现用户管理,即用户的登录和登出以及页面权限管理。

首先我们现在一共有以下views: index(), post_view(), post_create(), post_edit(), post_drafts(), post_publish(), post_delete()。在这些views中,出了index()和post_views()这两个属于内容展现的方法以外,其他方法应该都受到登录保护。所以,我们引入django自带的@login_required注解来处理这些方法。

首先在hzblog/views.py中引入login_required,并在需要登录验证的方法前加上注解。

from django.contrib.auth.decorators import login_required

@login_required
def post_create(request):
    ...

@login_required
def post_edit(request, pk):
    ...

@login_required
def post_drafts(request):
    ...

@login_required
def post_publish(request, pk):
    ...

@login_required
def post_delete(request, pk):
    ...

然后,在hzsite/urls.py中引入登录登出的路由。注意,由于整个系统使用统一的登录登出路由,所以这里不是在app的urls.py中引入路由。

from django.contrib.auth import views

urlpatterns = [
    ...
    url(r'^accounts/login/$', views.login, name='login'),
    url(r'^accounts/logout/$', views.logout, name='logout'),
    ...
]

这里,我们还要修改一下hzsite/settings.py配置文件,将login/logout操作后的跳转页面定义到’/’目录,即首页。在settings.py中,加入两行:

LOGIN_REDIRECT_URL = '/'
LOGOUT_REDIRECT_URL = '/'

引入路由之后,我们创建一个登录页面进行登录。创建hzblog/templates/registration/目录,在目录下创建login.html模板

{% extends "blog/base.html" %}

{% block content %}

{% if form.errors %}
<p>Your username and password didn't match. Please try again.</p>
{% endif %}

<form method="post" action="{% url 'login' %}">
{% csrf_token %}
<table>
<tr>
    <td>{{ form.username.label_tag }}</td>
    <td>{{ form.username }}</td>
</tr>
<tr>
    <td>{{ form.password.label_tag }}</td>
    <td>{{ form.password }}</td>
</tr>
</table>

<input type="submit" value="login" />
<input type="hidden" name="next" value="{{ next }}" />
</form>

{% endblock %}

最后,我们修改base.html模板,在头部加上登录登出的按钮

...
    <div class="page-header">
        {% if user.is_authenticated %}
            <a href="{% url 'logout' %}" class="top-menu"><span class="glyphicon glyphicon-log-out"></span></a>
            <a href="{% url 'hzblog:post_create' %}" class="top-menu"><span class="glyphicon glyphicon-plus"></span></a>
            <a href="{% url 'hzblog:post_drafts' %}" class="top-menu"><span class="glyphicon glyphicon-list-alt"></span></a>
            <p class="top-menu">Hello {{ user.username }}</p>
        {% else %}
            <a href="{% url 'login' %}" class="top-menu"><span class="glyphicon glyphicon-log-in"></span></a>
        {% endif %}
        <h1><a href="/">ZIVER'S</a></h1>
    </div>
...

下面运行博客测试一下功能

 python manage.py runserver 0.0.0.0:8080

未登录状态点开首页时,右上角显示登录按钮

1

点击登录或者使用需要登录的功能(修改、删除等),跳转到登录页面

2

输入用户信息登录后,右上角出现欢迎信息和只有登录后才可见的按钮

3

登录功能完美实现。

Django博客系统开发05

文章的增删改发布

通过之前的步骤,我们已经有了一个初步的网站页面(首页+Django Admin),其实我们已经可以通过admin页面来对文章进行操作了,但是为了更像是一个真正的博客,我们应该能够从前端进行对文章的增删改查。

查看文章(post_view)

我们现在只有一个页面–首页。在首页中,我们获取到的是全部已经发布的文章列表。现在,我们创建一个文章详情页,当用户点击首页的文章标题时,将跳转到这个页面。

首先,我们为这个页面添加路由,在hzblog/urls.py中加入一行

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

然后,我们修改模板文件,增加跳转链接。在index.html中修改标题的href属性:

<h1><a href="{% url 'hzblog:post_view' pk=post.pk %}">{{ post.title }}</a></h1>

这里使用了url方法来获得post_view的真实url。hzblog:post_view(即AppName:RouterName)这种写法时因为我们之前在hzblog/urls.py中进行了如下定义:

...
app_name = 'hzblog'

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

如果是在hzsite/urls.py中定义的url,则不需要添加app前缀,直接使用’post_views’。

下面,创建列表页对应的view。修改views.py,加入post_view方法:

from django.shortcuts import render, get_object_or_404

def post_view(request, pk):
    post = get_object_or_404(Post, pk=pk)
    return render(request, 'blog/post_view.html', {'post': post})

通过view,请求将会被render到post_view.html这个模板。现在我们创建这个模板(hzblog/templates/blog/post_view.html):

{% extends 'blog/base.html' %}

{% block content %}
    <div class="date">
        {% if post.published_date %}
            {{ post.published_date }}
        {% endif %}
    </div>
    <h1>{{ post.title }}</h1>
    <p>{{ post.text|linebreaks }}</p>
{% endblock %}

这时候,我们访问

http://localhost:8080/post/2/

20161127145736

我们就能够看到文章详情页了。

Django小结

这里可以对创建一个页面/功能的流程进行一个小结。

  1. 在urls.py中添加新页面/功能的路由
  2. 在views.py中添加对应的方法来处理路由发送过来的请求,将数据渲染到对应模板
  3. 在templates文件夹下创建新页面/功能的模板,将views发送过来的数据进行展现

创建文章(post_create)

所谓的创建文章,我们可以理解成向服务器提交一个表单,表单中包含了文章的信息和内容。所以,我们先引入Django的Form来完成我们的功能。首先创建hzblog/forms.py

from django import forms
from .models import Post

class PostForm(forms.ModelForm):

    class Meta:
        model = Post
        fields = ('title', 'text',)

所以接下来,我们按照上面做的小结,开始增加创建文章功能的流程。首先,添加路由

url(r'^post/create/$', views.post_create, name='post_create'),

然后增加views

from django.shortcuts import redirect

def post_create(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('hzblog:post_view', pk=post.pk)
    else:
        form = PostForm()
    return render(request, 'blog/post_edit.html', {'form': form})

这里使用了一个redirect方法,即创建完文章之后跳转到post_view页面。而在返回中,我们将请求发送到了post_edit模板。这个模板现在还没有创建,因为我们的新增文章和编辑文章都将使用这个模板,所以会在接下来的编辑文章功能部分创建。

最后我们修改模板base.html,在page-header这个div中,增加创建文章按钮:

...
    <div class="page-header">
        <a href="{% url 'hzblog:post_create' %}" class="top-menu"><span class="glyphicon glyphicon-plus"></span></a>
        <h1><a href="/">ZIVER'S</a></h1>
    </div>
...

编辑文章(post_edit)

在创建文章功能中,我们遗留了post_edit这个模板没有添加。在编辑文章功能中,我们将实现这个模板。还是之前的流程,我们先创建路由

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

然后增加view方法

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('hzblog:post_view', pk=post.pk)
    else:
        form = PostForm(instance=post)
    return render(request, 'blog/post_edit.html', {'form': form})

最后增加post_edit.html模板

{% extends 'blog/base.html' %}

{% 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_view.html中增加编辑文章的按钮

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

修改完成后,post_views.html内容如下:

{% extends 'blog/base.html' %}

{% block content %}
    <div class="date">
        {% if post.published_date %}
            {{ post.published_date }}
        {% endif %}
        <a class="btn btn-default" href="{% url 'hzblog:post_edit' pk=post.pk %}"><span class="glyphicon glyphicon-pencil"></span></a>
    </div>
    <h1>{{ post.title }}</h1>
    <p>{{ post.text|linebreaks }}</p>
{% endblock %}

测试

在完成以上功能后,我们可以稍微测试一下效果。因为增加和修改文章都是需要以用户身份执行的,而我们的前端登陆功能还没有实现,所以我们首先用django自带的amin登陆到我们的博客:

http://localhost:8080/admin

然后访问首页

20161127152833

由于没有新文章的发布,首页依然只有一篇文章。右上角有了创建文章的按钮,点击按钮创建文章

20161127152939

这里就有一个可以填写的表单,填写后点击save

20161127153004

保存后,跳转到了文章的详情页。此时的文章还没有发布,所以不会在首页显示,发布后文章右上角将显示发布时间。现在右上角有编辑按钮,点击按钮将回到文章编辑页(和新建文章是同一个模板)。接下来,我们将实现发布功能。

草稿列表(post_drafts)

未发布的文章称为草稿,为了实现发布功能,我们先实现草稿列表页,将未发布的文章列出来。

首先添加路由

url(r'^drafts/$', views.post_drafts, name='post_drafts'),

然后增加view方法

def post_drafts(request):
    posts = Post.objects.filter(published_date__isnull=True).order_by('-created_date')
    return render(request, 'blog/post_drafts.html', {'posts': posts})

之后增加post_drafts.html模板

{% extends 'blog/base.html' %}
{% block content %}
    {% for post in posts %}
        <div class="post">
            <p class="date">created: {{ post.created_date|date:'d-m-Y' }}</p>
            <h1><a href="{% url 'hzblog:post_view' pk=post.pk %}">{{ post.title }}</a></h1>
            <p>{{ post.text|truncatechars:200 }}</p>
        </div>
    {% endfor %}
{% endblock %}

最后在base.html中增加草稿列表页入口按钮

...
    <div class="page-header">
        <a href="{% url 'hzblog:post_create' %}" class="top-menu"><span class="glyphicon glyphicon-plus"></span></a>
        <a href="{% url 'hzblog:post_drafts' %}" class="top-menu"><span class="glyphicon glyphicon-list-alt"></span></a>
        <h1><a href="/">ZIVER'S</a></h1>
    </div>
...

发布文章(post_publish)

增加路由

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

增加view方法

def post_publish(request, pk):
    post = get_object_or_404(Post, pk=pk)
    post.publish()
    return redirect('hzblog:post_view', pk=pk)

在post_view页面中增加发布按钮

将下面内容

{% if post.published_date %}
    {{ post.published_date }}
{% endif %}

修改为

{% if post.published_date %}
    {{ post.published_date }}
{% else %}
    <a class="btn btn-default" href="{% url 'blog.views.post_publish' pk=post.pk %}">Publish</a>
{% endif %}

删除文章(post_delete)

增加路由

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

增加view方法

def post_delete(request, pk):
    post = get_object_or_404(Post, pk=pk)
    post.delete()
    return redirect('hzblog:index')

在post_view页面中增加发布按钮

 ...  
    <div class="date">
    ...
    {% endif %}
        ...
        <a class="btn btn-default" href="{% url 'hzblog:post_delete' pk=post.pk %}"><span class="glyphicon glyphicon-remove"></span></a>
    </div>
...

至此,博客的基本功能:查看文章,创建文章,编辑文章,删除文章,发布文章功能完成。

Django博客系统开发04

前端改造

在之前的几篇完成后,我们得到了一个简陋的首页,下面我们使用Bootstrap来美化一下我们的前端。

下载Bootstrap

需要下载的是Bootstrap的css和js,以及jquery。这里就不仔细说明了,下载后放到新建的static/目录下即可。现在,整个项目的结构如下:

hzsite
├── hzblog
│   ├── admin.py
│   ├── apps.py
│   ├── __init__.py
│   ├── models.py
│   ├── templates
│   │   └── blog
│   │       └── index.html
│   ├── tests.py
│   ├── urls.py
│   └── views.py
├── hzsite
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── manage.py
└── static
    ├── css
    │   ├── bootstrap.min.css
    │   ├── bootstrap.min.css.map
    │   ├── bootstrap-theme.min.css
    │   ├── bootstrap-theme.min.css.map
    │   └── style.css
    └── js
        ├── bootstrap.min.js
        └── jquery-3.1.1.min.js

注意到这里还有一个style.css,我将在这个文件中定义主体css。

style.css内容如下:

.page-header {
    background-color: #417690;
    margin-top: 0;
    padding: 5px 20px 10px 40px;
}
.page-header h1, .page-header h1 a, .page-header h1 a:visited, .page-header h1 a:active {
    color: #ffffff;
    font-size: 28pt;
    text-decoration: none;
}
.content {
    margin-left: 40px;
}
h1, h2, h3, h4 {
    font-family: 'Microsoft YaHei', cursive;
}
.date {
    float: right;
    color: #828282;
}
.save {
    float: right;
}
.post-form textarea, .post-form input {
    width: 100%;
}
.top-menu, .top-menu:hover, .top-menu:visited {
    color: #ffffff;
    float: right;
    font-size: 26pt;
    margin-right: 20px;
}
.post {
    margin-bottom: 70px;
}
.post h1 a, .post h1 a:visited {
    color: #000000;
}

配置静态目录

下面我们把刚才创建的static目录添加到配置中,修改hzsite/settings.py增加以下内容:

STATICFILES_DIRS = (
    os.path.join(BASE_DIR, "static"),
)

写入到配置后,我们就可以在模板中直接调用static目录下的css和js了。

修改template

修改index.html

{% load staticfiles %}
<html>
<head>
    <title>ZIVER'S</title>
    <script src="{% static 'js/jquery-3.1.1.min.js' %}"></script>
    <link rel="stylesheet" href="{% static 'css/bootstrap.min.css' %}">
    <link rel="stylesheet" href="{% static 'css/bootstrap-theme.min.css' %}">
    <script src="{% static 'js/bootstrap.min.js' %}"></script>
    <link rel="stylesheet" href="{% static 'css/style.css' %}">
</head>
<body>
    <div class="page-header">
        <h1><a href="/">ZIVER'S</a></h1>
    </div>
    <div class="content">
        <div class="row">
            <div class="col-md-8">
                {% for post in posts %}
                    <div class="post">
                        <h1><a href="">{{ post.title }}</a></h1>
                        <p>published: {{ post.published_date }}</p>
                        <p>{{ post.text|linebreaks }}</p>
                    </div>
                {% endfor %}
            </div>
        </div>
    </div>
</body>
</html>

现在,我们的博客首页看起来就舒服多了。

7

模板继承

Django的模板系统支持模板继承,所以我们可以使用继承的方法来减少前端代码的冗余。在index.html的基础上把页面上一般不改变的地方拆分出来创建base.html。内容如下:

<html>
<head>
    <title>ZIVER'S</title>
    <script src="{% static 'js/jquery-3.1.1.min.js' %}"></script>
    <link rel="stylesheet" href="{% static 'css/bootstrap.min.css' %}">
    <link rel="stylesheet" href="{% static 'css/bootstrap-theme.min.css' %}">
    <script src="{% static 'js/bootstrap.min.js' %}"></script>
    <link rel="stylesheet" href="{% static 'css/style.css' %}">
</head>
<body>
    <div class="page-header">
        <h1><a href="/">ZIVER'S</a></h1>
    </div>
    <div class="content">
        <div class="row">
            <div class="col-md-8">
            {% block content %}
            {% endblock %}
            </div>
        </div>
    </div>
</body>
</html>

然后删除掉index.html中的重复内容,并在开头加上模板引用。修改完后的index.html如下:

{% extends 'blog/base.html' %}
{% block content %}
{% for post in posts %}
    <div class="post">
        <h1><a href="">{{ post.title }}</a></h1>
        <p>published: {{ post.published_date }}</p>
        <p>{{ post.text|linebreaks }}</p>
    </div>
{% endfor %}
{% endblock content %}

修改完成后,刷新页面,应该不会有任何变化。

 

Django博客系统开发03

路由Django URL

Django框架通过urls.py文件中的规则对系统进行路由控制。首先我们在主路由hzsite/urls.py中引入hzblog的路由设置:

from django.conf.urls import url
from django.contrib import admin

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'', include('hzblog.urls')),
]

然后,在hzsite/urls.py中设置具体的路由规则

from django.conf.urls import url
from . import views

urlpatterns = [
    url(r'^$', views.index, name='index'),
]

这里我们添加了一条规则,当用户访问网站根目录时,有views中的index方法处理。下面我们去views.py中添加index方法对请求进行处理。

from django.shortcuts import render
from .models import Post

def index(request):
    posts = Post.objects.filter(published_date__isnull=False).order_by('-published_date')
    return render(request, 'blog/index.html', {'posts': posts})

对于路由发来的请求,index函数先调用models查找出符合要求的文章list,然后调用render方法将获取到的数据render到index.html这个模板页面。

最后,我们只需要创建这个index.html模板文件即可。

mkdir -p hzblog/templates/blog
vim hzblog/templates/blog/index.html

模板如下

<html>
<head>
    <title>ZIVER'S</title>
</head>
<body>
    <div>
        <h1><a href="/">ZIVER'S</a></h1>
    </div>
    {% for post in posts %}
    <div>
        <p>published: {{ post.published_date }}</p>
            <h1><a href="">{{ post.title }}</a></h1>
            <p>{{ post.text|linebreaks }}</p>
    </div>
    {% endfor %}
</body>
</html>

这时候,开启服务器,访问我们的主页就能看到如下页面了

6

由于没有加入样式,所以现在的页面比较简陋。这里只显示了Sample 02这篇文章,是因为我们之前在shell中只publish了这一篇,而在index方法中使用过滤器只筛选出了published文章。

Django博客系统开发02

模型Model

Model即MVC模式中的模型,主要是通过ORM与数据库对接,执行对数据库的一些操作。博客系统的所有的模型都将在hzblog/models.py中定义。下面定义我们的第一个Model——Post:

from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User

class Post(models.Model):
    author = models.ForeignKey(User)
    title = models.CharField(max_length=200)
    text = models.TextField()
    created_date = models.DateTimeField(default=timezone.now)
    published_date = models.DateTimeField(blank=True, null=True)

    def publish(self):
        self.published_date = timezone.now()
        self.save()

    def __str__(self):
        return self.title

定义完成后,我们使用migrate命令在数据库中生成相应的表结构

python manage.py makemigrations hzblog
python manage.py migrate hzblog

第一步中,django将为我们创建model修改后需要更改的sql。第二步中将这些更改写入到数据库中。

下面我们在django shell中创建一篇文章

python manage.py shell
>>> from hzblog.models import Post
>>> Post.objects.all()
<QuerySet []>
>>> from django.contrib.auth.models import User
>>> User.objects.create(username='Henry')
<User: Henry>
>>> henry = User.objects.get(username='Henry')
>>> Post.objects.create(author = henry, title = 'Sample 01', text = 'Test')
<Post: Sample 01>
>>> Post.objects.all()
[<Post: Sample 01>]

同样的方法,创建其他Sample文章,现在我们就有了三篇文章

>>> Post.objects.filter(author=user)
[<Post: Sample 01>, <Post: Sample 02>, <Post: Sample 03>]

下面,我们筛选出其中的Sample 02这篇文章并发布

>>> post = Post.objects.get(id=2)
>>> post.publish()
>>> Post.objects.filter(published_date__isnull=False)
[<Post: Sample 02>]

这时候,我们就通过django shell用CLI的方式创建了三篇文章并发布了其中一篇。

后台管理Django Admin

Django框架提供了一个简单的后台管理界面Django Admin。我们先创建一个管理员账号admin:

python manage.py createsuperuser

创建完成后,我们就可以用这个账号登陆Django后台。

http://localhost:8080/admin

2

接下来,我们把我们创建的Post这个Model注册到Django Admin中:

修改hzblog/admin.py

from django.contrib import admin
from .models import Post

admin.site.register(Post)

下面,我们登陆到Django后台,现在已经可以看到我们刚才通过shell创建的几篇文章了。

3

Django后台界面

4

文章列表页

5

文章详情页

Django博客系统开发01

环境搭建

开发环境

这里使用的是Ubuntu 16.04 LTS Server版本的系统,所以系统自带了Python3.5版本。但是系统默认使用的是Python2.7, 需要使用Python3时使用Python3命令。为了让开发环境相互隔离,我使用virtualenv创建独立的虚拟环境。

首先安装pip3

apt update
apt upgrade
apt install python3-pip

这里还需要安装一些依赖库以用于之后数据库的连接

apt install python-dev
apt install libmysqlclient-dev

(CentOS对应为python34-devel、mysql-devel)

然后安装虚拟环境virtualenv

pip install virtualenv

现在,我们到/var/www/目录下创建一个虚拟环境,并将虚拟环境所在目录命名为venv

cd /var/www/
virtualenv venv -p /usr/bin/python3 --no-site-packages

然后,激活这个虚拟环境

root@ubuntu:var/www# . venv/bin/activate
(venv) root@ubuntu:/var/www#

然后,安装django和mysqlclient用于连接mysql数据库(当然也可以使用pymysql这样的工具)

pip install django
pip install mysqlclient

现在,我们就有了开发所需要的软件环境,接下来开始构建项目。

创建项目

在/var/www/目录下执行一下命令创建我们的工程(hzsite)

django-admin startproject hzsite

创建后,工程的结构如下:

hzsite
    ├───manage.py
    └───hzsite
         settings.py
         urls.py
         wsgi.py
         __init__.py

数据库

博客的数据使用MySQL数据库存储,所以我们需要先新建一个数据库

mysql -u root -p
> create database hzsite;

配置项目

修改hzsite/settings.py文件中的以下配置

修改ALLOW_HOSTS

ALLOWED_HOSTS = ['*']

修改TIME_ZONE

TIME_ZONE = 'Asia/Shanghai'

修改数据库连接配置

# Database
# https://docs.djangoproject.com/en/1.10/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'hzsite',
        'USER': 'root',
        'PASSWORD': 'password',
        'HOST': '127.0.0.1',
        'PORT': '3306',
    }
}

完成后,执行migrate命令生成数据库结构

python manage.py migrate

显示如下则成功

Operations to perform:
 Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
 Applying contenttypes.0001_initial... OK
 Applying auth.0001_initial... OK
 Applying admin.0001_initial... OK
 Applying admin.0002_logentry_remove_auto_add... OK
 Applying contenttypes.0002_remove_content_type_name... OK
 Applying auth.0002_alter_permission_name_max_length... OK
 Applying auth.0003_alter_user_email_max_length... OK
 Applying auth.0004_alter_user_username_opts... OK
 Applying auth.0005_alter_user_last_login_null... OK
 Applying auth.0006_require_contenttypes_0002... OK
 Applying auth.0007_alter_validators_add_error_messages... OK
 Applying auth.0008_alter_user_username_max_length... OK
 Applying sessions.0001_initial... OK

完成后,使用以下命令在本机8080端口启动服务器

python manage.py runserver 0.0.0.0:8080

使用浏览器访问,出现It Works提示页面则配置成功

1

创建新应用

一个Django Project中可以包含多个Application。这里我们创建一个hzblog应用作为博客系统的主要App。

python manage.py startapp hzblog

创建完成后在hzsite/settings.py中注册这个app

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'hzblog',
]

至此,基本的环境和博客系统的目录结构就有了。

Django博客系统开发

一直想用Python实现一个博客系统来替换掉现在臃肿的WordPress。之前尝试过使用Flask框架来实现,但是由于功力不足,Flask这种小型框架做起来还是困难比较大的,所以决定还是从Django入手吧。在这之后应该会有一系列的文章来完成一个这个博客系统的实现,虽然离WordPress应该差距不小,但是至少应该能够实现一个博客系统需要的基本功能。

目录

源码

https://github.com/cnzh/hzsite

目标

实现一个基于Django框架的简单博客,第一阶段应该至少实现以下功能:

  1. 增加、修改、删除文章
  2. 用户登录、登出
  3. 草稿系统,草稿发布逻辑
  4. 基本的前端界面

之后会对这些功能迭代,Todo:

  1. 页面导航
  2. 文章搜索
  3. Redis缓存
  4. MarkDown集成
  5. 富文本编辑

环境

  1. Ubuntu 16.04 LTS
  2. Django 1.10
  3. MySQL 5.7
  4. Python 3.5

参考

代码结构很大程度上参考了Django Girlstutorial以及tutorial-extensions系列教程,这里进行说明。

CentOS 7部署Nagios监控

部署说明

  • 系统:CentOS 7.2
  • 环境需求:Apache(httpd), PHP
  • 权限:root/sudoer
  • master服务器(192.168.50.101)
  • slave服务器(192.168.50.102)

安装Nagios 4

首先,我们在master服务器上安装Nagios相关服务。

安装依赖环境

由于安装采用源码编译的方式,所以需要安装一些基本的库

sudo yum install gcc glibc glibc-common gd gd-devel make net-snmp openssl-devel xinetd unzip

创建Nagios用户组

我们创建一个nagios用户和nagcmd组以用来运行nagios服务

sudo useradd nagios
sudo groupadd nagcmd
sudo usermod -a -G nagcmd nagios

下面我们安装Nagios。

编译安装Nagios

首先从官方Nagios下载地址下载Nagios源码(点击页面表单框下面的Skip to download)。然后选择最新的下载地址。下载完后解压。作文时最新的稳定版本为4.2.2。

cd ~
wget https://assets.nagios.com/downloads/nagioscore/releases/nagios-4.2.2.tar.gz
tar xvf nagios-4.2.2.tar.gz
cd nagios-4.2.2

使用以下命令编译安装

./configure --with-command-group=nagcmd

make all

sudo make install
sudo make install-commandmode
sudo make install-init
sudo make install-config
sudo make install-webconf

最后,我们将apache用户添加到nagcmd组,这样就可以在web端运行命令了。

sudo usermod -G nagcmd apache

编译安装Nagios Plugins

同样采用编译安装的方式安装Nagios插件。源码可以在这里下载:下载地址。作文时最新的版本为2.1.4。

cd ~
wget http://nagios-plugins.org/download/nagios-plugins-2.1.4.tar.gz

tar xvf nagios-plugins-2.1.4.tar.gz

cd nagios-plugins-2.1.4

./configure --with-nagios-user=nagios --with-nagios-group=nagios --with-openssl

make

sudo make install

编译安装NRPE

同样采用编译安装的方式安装NRPE扩展。源码可以在这里下载:下载地址。作文时最新的版本为2.15。

cd ~
wget http://downloads.sourceforge.net/project/nagios/nrpe-2.x/nrpe-2.15/nrpe-2.15.tar.gz

tar xvf nrpe-2.15.tar.gz

cd nrpe-2.15

./configure --enable-command-args --with-nagios-user=nagios --with-nagios-group=nagios --with-ssl=/usr/bin/openssl --with-ssl-lib=/usr/lib/x86_64-linux-gnu

make all
sudo make install
sudo make install-xinetd
sudo make install-daemon-config

这里还需要对nrpe进行一些配置。编辑nrpe的执行脚本:

sudo vi /etc/xinetd.d/nrpe

修改only_from字段的值,在其后加上本机的IP地址

only_from = 127.0.0.0 192.168.50.101

重启NRPE服务

sudo service xinetd restart

至此,Nagios安装就完成了,下面需要对Nagios进行配置。

配置Nagios 4

下面,我们在master服务器上修改一些配置。当然,刚才的所有操作也是在master服务器上完成的。

修改Nagios主配置文件

首先,修改配置文件

sudo vim /usr/local/nagios/etc/nagios.cfg

找到以下行,取消行前的#注释符

#cfg_dir=/usr/local/nagios/etc/servers

保存并退出。接下来,创建servers目录用来存放以后的slave服务器配置信息

sudo mkdir /usr/local/nagios/etc/servers

修改Nagios联系人信息

sudo vi /usr/local/nagios/etc/objects/contacts.cfg

将email字段的邮箱地址改为自己的邮箱,保存并退出。

增加check_nrpe指令

这里,我们向Nagios中增加一条我们自定义的指令

sudo vi /usr/local/nagios/etc/objects/commands.cfg

在最后加上以下行

define command{
        command_name check_nrpe
        command_line $USER1$/check_nrpe -H $HOSTADDRESS$ -c $ARG1$
}

保存并推出。此时,我们就多了一条check_nrpe指令可以使用。

配置Apache

这一步是用httpd在Nagios web服务前增加一道认证。添加nagiosadmin用户,并输入密码。

sudo htpasswd -c /usr/local/nagios/etc/htpasswd.users nagiosadmin

下面重启nagios和httpd以使配置生效

sudo systemctl start nagios.service
sudo systemctl restart httpd.service

使用chkconfig命令使nagios开机运行

sudo chkconfig nagios on

访问Nagios页面

通过以上的配置,我们就可以在Nagios的web页面看到一些信息。由于我们在master服务器上也配置了NRPE,所以Nagios会对本机也进行监测,所以可以看到的实际上是master服务器自身的参数信息。

http://192.168.50.101/nagios

hosts_link

监控slave服务器

下面我们在slave服务器上配置NRPE以用于监测。以下操作在slave服务器上进行。

安装EPEL环境

sudo yum install epel-release

安装NRPE和Nagios Plugins

sudo yum install nrpe nagios-plugins-all

下面修改NRPE的配置文件,将master服务器的ip加入白名单

sudo vi /etc/nagios/nrpe.cfg

在allowed_hosts字段中添加master服务器IP(注意,这里是逗号分隔,之前的only_from字段是空格分隔)。

allowed_hosts=127.0.0.1,192.168.50.101

将slave服务器加入配置列表

下面,回到master服务器,我们需要将刚才新建的slave服务器的信息添加到servers列表中。在servers目录下创建slave机器的配置文件

sudo vi /usr/local/nagios/etc/servers/slave_01.cfg

添加以下配置,替换掉host_name、alias、address三个字段为你自己的配置。

define host {
        use                             linux-server
        host_name                       slave_01
        alias                           slave_01
        address                         192.168.50.102
        max_check_attempts              5
        check_period                    24x7
        notification_interval           30
        notification_period             24x7
}

保存并退出。重启nagios服务以使配置生效。

sudo systemctl reload nagios.service

此时,再次登录到nagios的web页面,就能看到我们的这台slave服务器的信息了。

http://192.168.50.101/nagios

CentOS更新yum国内源

这里选择163的源(源地址)。首先备份/etc/yum.repos.d/CentOS-Base.repo

mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup

下载CentOS7的源,并重命名输出到以上目录

cd etc/yum.repos.d/
wget http://mirrors.163.com/.help/CentOS7-Base-163.repo -O CentOS-Base.repo

运行以下命令生成缓存

yum clean all
yum makecache

执行更新

yum -y update

创建一个Maven工程

在Eclipse中集成MAVEN

在最新版的Eclipse中,已经集成了maven插件。现在所需要做的就是对其进行配置。首先在preference中,找到maven相关配置。在Installation条目下添加之前安装maven的目录: 20161120142046 然后修改User Settings条目,将settings.xml指向之前配置的文件 20161120142056 这样,我们就已经可以在Eclipse中使用MAVEN了。

创建一个MAVEN项目

点击File -> New -> Maven Project,选择Create a simple project,点击Next: 20161120141744 填写Group Id和Artifact Id,其他默认,点击Finish: 20161120141616 完成后,我们就有了一个典型的maven project。目录结构如下: 20161120141840