Django+Nginx+uwsgi搭建自己的博客(四)
由于在上篇博文中仍然介绍了相当多的后端部分,导致原定于上篇介绍的前端部分“跳票”到了这篇。在此篇博文中,我将会介绍Users App和主页的前端部分,从而形成我们博客的一个雏形。
在前端部分,我们主要使用前端模板来建立我们的网页。Django提供了默认的模板引擎供我们使用。借助模板引擎,我们可以方便地将服务器的数据显示在页面中,实现前后端的交互。此外,模板的另一个好处是可继承性。借助模板继承,我们可以建立一个父模板,然后在其中填入不同的内容来快速建立不同的页面,从而大大减少了我们的工作量。
前端部分分为App和主页两部分。App的前端主要对应App中的views.py中的各个视图函数,而主页的前端是用于对应myblog/views.py中的视图函数的。
我们首先来建立主页的前端部分。在myblog目录下,建立一个名为templates的文件夹,这里是我们存放模板的目录,我们会把父模板和子模板的目录都放在这里。进入该目录,并在其中再建立一个名为myblog的目录,在这里是我们存放子模板的地方,目录结构如下:
- ├── templates
- │ ├── myblog
- │ │ ├── 404.html
- │ │ └── index.html
- │ └── parentTemplate.html
├── templates
│ ├── myblog
│ │ ├── 404.html
│ │ └── index.html
│ └── parentTemplate.html
我们要在templates目录中建立名为parentTemplate.html的文件作为我们的父模板,代码如下:
- <!DOCTYPE html>
- <html lang="zh">
- <head>
- <meta charset="UTF-8">
- <title>Cap_Liu的博客</title>
- </head>
- <style type="text/css">
- body{
- color: #efd;
- background: #F3F8C5;
- margin:7px;
- }
- h1{
- padding: 2em;
- background: #675;
- }
- h2{
- color: #000000;
- margin-top:2em;
- text-align: center;
- }
- p{
- margin:1em 0;
- }
- .introduce{
- color: #000000;
- margin-left: auto;
- margin-right: 85%;
- }
- .list{
- color: #000000;
- margin-left: auto;
- position:relative;
- left: 20%;
- top: -20px;
- }
- .nav{
- color: #000000;
- top: -20px;
- text-align: right;
- }
- .content{
- color: #000000;
- top: -20px;
- }
- .content p{
- text-indent: 5em;
- }
- .articlelist{
- text-align: left;
- font-size: 20px;
- }
- .articlelistinfo{
- text-align: left;
- font-size: 20px;
- }
- </style>
- <body>
- <h1>BetrayArmy的博客</h1>
- <div class="introduce">
- {% block introduce %}
- {% endblock %}
- </div>
- <div class="nav">
- {% block nav %}
- {% endblock %}
- </div>
- <div class="content">
- {% block content %}
- {% endblock %}
- </div>
- </body>
- </html>
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>Cap_Liu的博客</title>
</head>
<style type="text/css">
body{
color: #efd;
background: #F3F8C5;
margin:7px;
}
h1{
padding: 2em;
background: #675;
}
h2{
color: #000000;
margin-top:2em;
text-align: center;
}
p{
margin:1em 0;
}
.introduce{
color: #000000;
margin-left: auto;
margin-right: 85%;
}
.list{
color: #000000;
margin-left: auto;
position:relative;
left: 20%;
top: -20px;
}
.nav{
color: #000000;
top: -20px;
text-align: right;
}
.content{
color: #000000;
top: -20px;
}
.content p{
text-indent: 5em;
}
.articlelist{
text-align: left;
font-size: 20px;
}
.articlelistinfo{
text-align: left;
font-size: 20px;
} </style>
<body>
<h1>BetrayArmy的博客</h1>
<div class="introduce">
{% block introduce %}
{% endblock %}
</div>
<div class="nav">
{% block nav %}
{% endblock %}
</div>
<div class="content">
{% block content %}
{% endblock %}
</div>
</body>
</html>
在模板中,使用{% block name %}和{% endblock %}来定义模板的内容块,我们可以在子模板中填写对应块的内容。这个父模板很简单,定义了一些CSS样式以及定义了三个div:个人介绍introduce,导航栏nav,以及内容区content。
然后我们开始编写我们的子模板templates/myblog/index.html。该html是真正的主页,它会继承以上的父模板,并负责将myblog/views.py中的index函数返回的数据显示在上面三个内容块中,代码如下:
- <!--templates/myblog/index.html-->
- {% extends "parentTemplate.html" %}
- {% block introduce %}
- {% if curruser.username != "anony" or curruser.username != "" %}
- <div>
- {% if curruser.logoimage %}
- <img src="{{ curruser.logoimage.url }}" width="64" height="64" />
- {% endif %}
- </div>
- <a href="{% url 'users:userInfo' curruser.username %}">{{ curruser.username }}</a>
- {% endif %}
- {% endblock %}
- {% block nav %}
- {% if curruser.username == "anony" or curruser.username == "" %}
- <a href="{% url 'users:userregister' %}">用户注册</a>
- <a href="{% url 'users:userlogin' %}">用户登录</a>
- {% else %}
- 用户:{{ curruser.username }}
- <a href="{% url 'users:logoff' %}">退出登录</a>
- <a href="{% url 'blogs:addblog' %}">写博文</a>
- {% endif %}
- {% endblock %}
- {% block content %}
- <div class="list">
- {% if blog_list %}
- <ul>
- {% for blog in blog_list %}
- <div class="articlelist">
- <a href="{% url 'blogs:content' blog.id %}">{{ blog.title }}</a>-<a href="{% url 'users:userInfo' blog.auther.username %}">{{ blog.auther }}</a>
- <div class="articlelistinfo">
- <span title="阅读次数">阅读 {{ blog.readcount }}</span>
- <span title="创建时间">{{ blog.createdate|date:"Y-m-d H:i:s" }}</span>
- </div>
- </div>
- {% endfor %}
- </ul>
- {% else %}
- <p>No blogs</p>
- {% endif %}
- </div>
- {% endblock %}
<!--templates/myblog/index.html-->
{% extends "parentTemplate.html" %} {% block introduce %}
{% if curruser.username != "anony" or curruser.username != "" %}
<div>
{% if curruser.logoimage %}
<img src="{{ curruser.logoimage.url }}" width="64" height="64" />
{% endif %}
</div>
<a href="{% url 'users:userInfo' curruser.username %}">{{ curruser.username }}</a>
{% endif %}
{% endblock %}
{% block nav %}
{% if curruser.username == "anony" or curruser.username == "" %}
<a href="{% url 'users:userregister' %}">用户注册</a>
<a href="{% url 'users:userlogin' %}">用户登录</a>
{% else %}
用户:{{ curruser.username }}
<a href="{% url 'users:logoff' %}">退出登录</a>
<a href="{% url 'blogs:addblog' %}">写博文</a>
{% endif %}
{% endblock %}
{% block content %}
<div class="list">
{% if blog_list %}
<ul>
{% for blog in blog_list %}
<div class="articlelist">
<a href="{% url 'blogs:content' blog.id %}">{{ blog.title }}</a>-<a href="{% url 'users:userInfo' blog.auther.username %}">{{ blog.auther }}</a>
<div class="articlelistinfo">
<span title="阅读次数">阅读 {{ blog.readcount }}</span>
<span title="创建时间">{{ blog.createdate|date:"Y-m-d H:i:s" }}</span>
</div>
</div>
{% endfor %}
</ul>
{% else %}
<p>No blogs</p>
{% endif %}
</div>
{% endblock %}
这里介绍一下模板语言中的一些关键字:
{% extends "parentTemplate.html" %}:在模板中,使用{% extends 模板名 %}这种关键字来声明该页面继承于哪个模板。若某网页继承了某模板,其就可以修改父模板的block内容,以及使用定义在父模板中的CSS样式。
{% block introduct %}:由于继承了parentTemplate模板,因此这里的block名称要与父模板中的block名称一样,以实现填写对应block内容的目的。
{% if curruser.username != "anony" or curruser.username != "" %}和{% endif %}:模板语言中的条件判断,每个{% if %}必须要有一个{% endif %}与之对应。
在模板中,可以直接使用通过服务器传入的python对象,并访问其方法和属性。curruser即为通过myblog/views.py中的index函数传回的对象,如下所示:
- # myblog/views.py
- def index(request):
- try:
- username = request.session['username']
- user = Users.objects.get(username=username)
- except KeyError:
- user = Users.objects.get(username='anony')
- except Users.DoesNotExist:
- user = Users.objects.get(username='anony')
- blogList = Blog.objects.filter(draft=False).order_by('title')
- content = { 'blog_list':blogList,
- '<span style="color:#ff0000;">curruser</span>':<span style="color:#ff0000;">user</span>
- }
- return render(request, 'myblog/index.html', content)
# myblog/views.py
def index(request):
try:
username = request.session['username']
user = Users.objects.get(username=username)
except KeyError:
user = Users.objects.get(username='anony')
except Users.DoesNotExist:
user = Users.objects.get(username='anony')
blogList = Blog.objects.filter(draft=False).order_by('title')
content = { 'blog_list':blogList,
'curruser':user
}
return render(request, 'myblog/index.html', content)
在index函数中,通过字典向index.html传递了两个参数:名为curruser的Users类对象和名为blog_list的list对象,而我们可以在html模板中直接访问这两个对象,包括获得其属性、对其进行遍历等操作。若想访问对象的属性,可以通过.运算符来进行。
{% url ‘users:userregister’ [参数名] %}:html中<a>标签或表单action属性中的url地址。该标签与urls.py中的url列表项一一对应,如users:userregister指的是在Users App中的urls.py文件中的名为userregister项,如下所示:
- # Users App urls.py
- from django.conf.urls import url,include
- from . import views
- from myblog.views import index
- app_name='<span style="color:#ff0000;">users</span>'
- urlpatterns = [
- url(r'^$', index, name='index'),
- url(r'^userregister/$',views.userregister,name='<span style="color:#ff0000;">userregister</span>'),
- url(r'^userlogin/$',views.userlogin,name='userlogin'),
- url(r'^loginResult/(?P<info>.*)$',views.loginResult,name='loginResult'),
- url(r'^registerResult/(?P<info>.*)$',views.registerResult,name='registerResult'),
- url(r'^logoff/$',views.logoff,name='logoff'),
- url(r'^userinfo/(?P<username>.*)$',views.userInfo,name='userInfo')
- ]
- # 红字即为users:userregister的来源
# Users App urls.py
from django.conf.urls import url,include
from . import views
from myblog.views import index app_name='users'
urlpatterns = [
url(r'^$', index, name='index'),
url(r'^userregister/$',views.userregister,name='userregister'),
url(r'^userlogin/$',views.userlogin,name='userlogin'),
url(r'^loginResult/(?P<info>.*)$',views.loginResult,name='loginResult'),
url(r'^registerResult/(?P<info>.*)$',views.registerResult,name='registerResult'),
url(r'^logoff/$',views.logoff,name='logoff'),
url(r'^userinfo/(?P<username>.*)$',views.userInfo,name='userInfo')
]
# 红字即为users:userregister的来源
若url后面有参数,则直接加在url名称后即可。
{% for blog in blog_list %}和{% endfor %}:for循环操作。该循环会遍历blog_list中的每个元素,并将其相关信息显示在网页中。由于Blog的部分还没有写,因此之前的index函数中的blogList和页面中的这个for循环可以先跳过。
另一个404.html的模板就相对简单多了,如下所示:
- <!-- 404.html -->
- {% extends "parentTemplate.html" %}
- {% block content %}
- <div class="list">
- <p>页面未找到!</p>
- <p><a href="{% url 'index' %}">返回首页</a></p>
- </div>
- {% endblock %}
<!-- 404.html -->
{% extends "parentTemplate.html" %}
{% block content %}
<div class="list">
<p>页面未找到!</p>
<p><a href="{% url 'index' %}">返回首页</a></p>
</div>
{% endblock %}
现在,主页的前端页面已经建立完成,我们可以如法炮制,建立Users App的前端页面。
我们回到users文件夹下,同样建立templates目录,然后可以将之前建立好的parentTemplate.html拷贝过来,重命名为userTemplate.html;然后建立users目录,此时users/templates目录结构如下:
- ├── users
- │ ├── loginResult.html
- │ ├── registerResult.html
- │ ├── userinfo.html
- │ ├── userlogin.html
- │ └── userregister.html
- └── userTemplate.html
├── users
│ ├── loginResult.html
│ ├── registerResult.html
│ ├── userinfo.html
│ ├── userlogin.html
│ └── userregister.html
└── userTemplate.html
可以看到,Users App的前端部分共有5个页面,分别对应users/views.py中除了logoff函数外的5个view函数。
首先来看userregister.html,这一页面主要就是显示了用户注册的表单,如图所示:
因此其模板也比较简单:从服务器获得表单对象并将其显示出来:
- <!-- userregister.html -->
- {% extends "userTemplate.html" %}
- {% block content %}
- <h3>新用户注册</h3>
- <form action="{% url 'users:userregister' %}" method="post" enctype="multipart/form-data">
- {% csrf_token %}
- {{ form.as_p }}
- <p><input type="submit" value="提交"></p>
- </form>
- {% endblock %}
<!-- userregister.html -->
{% extends "userTemplate.html" %}
{% block content %}
<h3>新用户注册</h3>
<form action="{% url 'users:userregister' %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<p><input type="submit" value="提交"></p>
</form>
{% endblock %}
这里出现了一个新参数:{% csrf_token %},这是Django提供的csrf校验功能,一般来说都要加上,防止跨站伪造请求。此外,由于该表单有文件上传功能,因此enctype要设置为"multipart/form-data"。而form为前一篇博文中介绍的ModelForm,通过as_p方法,在页面中会将表单的每项用<p>标签显示出来。
然后就是registerResult.html,这一页面用于显示注册成功与否:
- <!-- registerResult.html -->
- {% extends "userTemplate.html" %}
- {% block content %}
- <h3>{{ result_info }}</h3>
- <a href="{% url 'index' %}" >返回首页</a>
- {% endblock %}
<!-- registerResult.html -->
{% extends "userTemplate.html" %}
{% block content %}
<h3>{{ result_info }}</h3>
<a href="{% url 'index' %}" >返回首页</a>
{% endblock %}
接下来是userlogin.html与loginResult.html,这两个页面与userregister.html/registerResult.html基本完全相同,因此一块放出来:
- <!-- userlogin.html -->
- {% extends "userTemplate.html" %}
- {% block content %}
- <h3>用户登录</h3>
- <form action="{% url 'users:userlogin' %}" method="post">
- {% csrf_token %}
- {{ form.as_p }}
- <p><input type="submit" value="登录"></p>
- </form>
- {% endblock %}
- <!-- loginResult.html -->
- {% extends "userTemplate.html" %}
- {% block content %}
- <h3>{{ result_info }}</h3>
- <a href="{% url 'index' %}" >返回首页</a>
- {% endblock %}
<!-- userlogin.html -->
{% extends "userTemplate.html" %}
{% block content %}
<h3>用户登录</h3>
<form action="{% url 'users:userlogin' %}" method="post">
{% csrf_token %}
{{ form.as_p }}
<p><input type="submit" value="登录"></p>
</form>
{% endblock %} <!-- loginResult.html -->
{% extends "userTemplate.html" %}
{% block content %}
<h3>{{ result_info }}</h3>
<a href="{% url 'index' %}" >返回首页</a>
{% endblock %}
最后一个页面是userinfo.html,用于显示用户信息:
- <!-- userinfo.html -->
- {% extends "userTemplate.html" %}
- {% block content %}
- <h3>用户{{ username }}资料</h3>
- <p>用户名: {{ username }}</p>
- <p>注册时间: {{ registertime|date:"Y-m-d" }}</p>
- <p>生日: {{ birthday|date:"Y-m-d H:i:s" }}</p>
- <p>电子邮件: {{ email }}</p>
- <p><a href="{% url 'index' %}">返回首页</a></p>
- {% endblock %}
<!-- userinfo.html -->
{% extends "userTemplate.html" %}
{% block content %}
<h3>用户{{ username }}资料</h3>
<p>用户名: {{ username }}</p>
<p>注册时间: {{ registertime|date:"Y-m-d" }}</p>
<p>生日: {{ birthday|date:"Y-m-d H:i:s" }}</p>
<p>电子邮件: {{ email }}</p>
<p><a href="{% url 'index' %}">返回首页</a></p>
{% endblock %}
注意,这里的registertime和birthday由于在Model中均为DateTimeField,因此我们需要用|date的方式告诉前端应将其显示成正确的日期或时间格式,否则会显示不正确。
现在,我们的博客算是有了个基本的雏形,可以在上面注册用户并登录了。然而,如果现在我们注册了一个有头像的用户并登录,我们会发现在主页上并不能显示出用户头像,这是因为我们现在并没有处理静态文件。在下一篇博客中,我将介绍怎样把我们的博客使用uwsgi+nginx的方式部署在本地,这将会是一个大难点,敬请期待~
Django+Nginx+uwsgi搭建自己的博客(四)的更多相关文章
- Django+Nginx+uwsgi搭建自己的博客(五)
在上一篇博文中,向大家介绍了Users App和Index的前端部分的实现,以及前端与Django的通信部分.至此,我们的博客已经具备一个简单的雏形,可以将其部署在本地的服务器上了.目前较为流行的we ...
- Django+Nginx+uwsgi搭建自己的博客(一)
最近对写爬虫有些厌倦了,于是将方向转移到了Web开发上.其实在之前自己也看过一部分Flask的资料,但总觉得Flask的资料有些零散,而且需要的各种扩展也非常多.因此,我将研究方向转移到了另一个主流的 ...
- Django+Nginx+uwsgi搭建自己的博客(八)
在这篇博客中,我们开始为我们的博客开发Blogs App和Users App相关的管理功能,以便每个用户都能管理自己的博客以及评论.目前,Users App的管理功能相对简单,主要功能为查看用户资料以 ...
- Django+Nginx+uwsgi搭建自己的博客(七)
上一篇博客中介绍了Blogs App的部分后端功能的实现,在这篇博客中,将继续为大家介绍Blogs App中前端功能的实现. 首先来看发布博客功能的前端页面.在blogs/templates/blog ...
- Django+Nginx+uwsgi搭建自己的博客(六)
这篇应该是2017年的最后一篇博客了,在这里首先祝大家元旦快乐! 从这篇博客开始,将会介绍Blogs App的功能实现,包括数据模型的建立.相关功能的视图函数的实现.前端页面的设计等,这意味着我们即将 ...
- Django+Nginx+uwsgi搭建自己的博客(二)
在上一篇博客中,为大家介绍了Django的一些基本概念以及建立了第一个App——Users,并且在数据库中建立了对应的表. 在这篇博客中,将为大家继续介绍数据库模型的定义和相关操作,以及Users A ...
- Django+Nginx+uwsgi搭建自己的博客(三)
(本来打算在这篇博文中介绍Users App的前端部分的,但写着写着就发现还需要铺垫很多东西才能把整个项目串的比较流畅些,因此这篇就继续介绍了后端的一些东西,前端的部分只好跳票到下一篇了-) 在上一篇 ...
- python3.x +django + nginx + uwsgi 搭建web服务
最近一直在用django开发自己的网站.在开发和线上环境的对接过程中遇到了许多的坑.所以想以一个老鸟的经历来写一下怎么 搭建web服务 一.python3.x .django .nginx .uwsg ...
- Linux - 搭建Web项目(Django + nginx + uwsgi)
工作中碰到需要使用Django + nginx + uwsgi 搭建项目环境 1. 搭建基本环境 需要有python环境,不多做说明 需要安装nginx,不多做说明 需要安装uwsgi: yum in ...
随机推荐
- KeyDown,KeyPress和KeyUp详解(转)
1.按键的类型 Windows窗体将键盘输入标识为由按位Keys枚举表示的虚拟键代码.使用Keys枚举,可以综合一系列按键以生成单个值,这些值与WM_KEYDOWN和WM_SYSKEYDOWNWind ...
- 2015/10/9 Python核编初级部分学习总结
终于在十一长假之后的两天看完了<Python核心编程>的初级部分.虽然到后来两章,类和环境看得越来越慢,越来越难以理解.很多东西只能靠强记,也没办法真正掌握了,我想了想,还是不强迫自己去背 ...
- Android Studio 更新失败的解决办法
编辑$ANDROID_STUDIO_HOME/bin/ 下的 studio.exe.vmoptions(如果系统用的Ubuntu,文件应该是studio.vmoptions或者如果是64位系统,应该是 ...
- jquery键盘事件全记录
很多时候,我们需要获取用户的键盘事件,下面就一起来看看jquery是如何操作键盘事件的. 一.首先需要知道的是: 1.keydown() keydown事件会在键盘按下时触发. 2.keyup() k ...
- windows下gitlab配置 生成ssh key
Git-1.9.5-preview20141217 1. 安装git,从程序目录打开 "Git Bash" 2. 键入命令:ssh-keygen -t rsa -C "e ...
- 【CodeForces】947 D. Picking Strings
[题目]D. Picking Strings [题意]给定只含'A','B','C'的字符串,支持以下变换:1.A - BC 2.B - AC 3.C - AB 4.AAA - empty ...
- 通过jquery.validate.js校验表单字段是否合法
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/ ...
- NYOJ 814 又见拦截导弹 (模拟)
题目链接 描述 大家对拦截导弹那个题目应该比较熟悉了,我再叙述一下题意:某国为了防御敌国的导弹袭击,新研制出来一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:它的第一发炮弹能够到达任意的高度,但是以 ...
- 蓝色的oa模板html_综合信息服务管理平台OA模板——后台
链接:http://pan.baidu.com/s/1qXGGOAK 密码:2otu
- 【C++自我精讲】基础系列六 PIMPL模式
[C++自我精讲]基础系列六 PIMPL模式 0 前言 很实用的一种基础模式. 1 PIMPL解释 PIMPL(Private Implementation 或 Pointer to Implemen ...