zoukankan      html  css  js  c++  java
  • Django+Nginx+uwsgi搭建自己的博客(四)

    由于在上篇博文中仍然介绍了相当多的后端部分,导致原定于上篇介绍的前端部分“跳票”到了这篇。在此篇博文中,我将会介绍Users App和主页的前端部分,从而形成我们博客的一个雏形。

    在前端部分,我们主要使用前端模板来建立我们的网页。Django提供了默认的模板引擎供我们使用。借助模板引擎,我们可以方便地将服务器的数据显示在页面中,实现前后端的交互。此外,模板的另一个好处是可继承性。借助模板继承,我们可以建立一个父模板,然后在其中填入不同的内容来快速建立不同的页面,从而大大减少了我们的工作量。

    前端部分分为App和主页两部分。App的前端主要对应App中的views.py中的各个视图函数,而主页的前端是用于对应myblog/views.py中的视图函数的。

    我们首先来建立主页的前端部分。在myblog目录下,建立一个名为templates的文件夹,这里是我们存放模板的目录,我们会把父模板和子模板的目录都放在这里。进入该目录,并在其中再建立一个名为myblog的目录,在这里是我们存放子模板的地方,目录结构如下:

    1. ├── templates  
    2. │   ├── myblog  
    3. │   │   ├── 404.html  
    4. │   │   └── index.html  
    5. │   └── parentTemplate.html  
    ├── templates
    │   ├── myblog
    │   │   ├── 404.html
    │   │   └── index.html
    │   └── parentTemplate.html

    我们要在templates目录中建立名为parentTemplate.html的文件作为我们的父模板,代码如下:
    1. <!DOCTYPE html>  
    2. <html lang="zh">  
    3. <head>  
    4.     <meta charset="UTF-8">  
    5.     <title>Cap_Liu的博客</title>  
    6. </head>  
    7. <style type="text/css">  
    8.     body{  
    9.         color: #efd;  
    10.         background: #F3F8C5;  
    11.         margin:7px;  
    12.     }  
    13.     h1{  
    14.         padding: 2em;  
    15.         background: #675;  
    16.     }  
    17.     h2{  
    18.         color: #000000;  
    19.         margin-top:2em;  
    20.         text-align: center;  
    21.     }  
    22.     p{  
    23.         margin:1em 0;  
    24.     }  
    25.     .introduce{  
    26.         color: #000000;  
    27.         margin-left: auto;  
    28.         margin-right: 85%;  
    29.     }  
    30.     .list{  
    31.         color: #000000;  
    32.         margin-left: auto;  
    33.         position:relative;  
    34.         left: 20%;  
    35.         top: -20px;  
    36.     }  
    37.     .nav{  
    38.         color: #000000;  
    39.         top: -20px;  
    40.         text-align: right;  
    41.     }  
    42.     .content{  
    43.         color: #000000;  
    44.         top: -20px;  
    45.     }  
    46.     .content p{  
    47.         text-indent: 5em;  
    48.     }  
    49.     .articlelist{  
    50.         text-align: left;  
    51.                 font-size: 20px;  
    52.     }  
    53.     .articlelistinfo{  
    54.         text-align: left;  
    55.         font-size: 20px;  
    56.     }  
    57.       
    58. </style>  
    59. <body>  
    60. <h1>BetrayArmy的博客</h1>  
    61. <div class="introduce">  
    62. {% block introduce %}  
    63. {% endblock %}  
    64. </div>  
    65. <div class="nav">  
    66. {% block nav %}  
    67. {% endblock %}  
    68. </div>  
    69. <div class="content">  
    70. {% block content %}  
    71. {% endblock %}  
    72. </div>  
    73. </body>  
    74. </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函数返回的数据显示在上面三个内容块中,代码如下:

    1. <!--templates/myblog/index.html-->  
    2. {% extends "parentTemplate.html" %}  
    3.   
    4. {% block introduce %}  
    5. {% if curruser.username  != "anony" or curruser.username  != "" %}  
    6. <div>  
    7. {% if curruser.logoimage %}  
    8. <img src="{{ curruser.logoimage.url }}" width="64" height="64" />  
    9. {% endif %}  
    10. </div>  
    11. <a href="{% url 'users:userInfo' curruser.username %}">{{ curruser.username }}</a>  
    12. {% endif %}  
    13. {% endblock %}  
    14. {% block nav %}  
    15. {% if curruser.username  == "anony" or curruser.username  == "" %}  
    16. <a href="{% url 'users:userregister' %}">用户注册</a>  
    17. <a href="{% url 'users:userlogin' %}">用户登录</a>  
    18. {% else %}  
    19. 用户:{{ curruser.username }}  
    20. <a href="{% url 'users:logoff' %}">退出登录</a>  
    21. <a href="{% url 'blogs:addblog' %}">写博文</a>  
    22. {% endif %}  
    23. {% endblock %}  
    24. {% block content %}  
    25. <div class="list">  
    26. {% if blog_list %}  
    27.     <ul>  
    28.     {% for blog in blog_list %}  
    29.         <div class="articlelist">  
    30.         <a href="{% url 'blogs:content' blog.id %}">{{ blog.title }}</a>-<a href="{% url 'users:userInfo' blog.auther.username %}">{{ blog.auther }}</a>  
    31.         <div class="articlelistinfo">  
    32.         <span title="阅读次数">阅读 {{ blog.readcount }}</span>  
    33.         <span title="创建时间">{{ blog.createdate|date:"Y-m-d H:i:s" }}</span>  
    34.         </div>  
    35.         </div>  
    36.     {% endfor %}  
    37.     </ul>  
    38. {% else %}  
    39.     <p>No blogs</p>  
    40. {% endif %}  
    41. </div>  
    42. {% 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函数传回的对象,如下所示:

    1. # myblog/views.py  
    2. def index(request):  
    3.     try:  
    4.         username = request.session['username']  
    5.         user = Users.objects.get(username=username)  
    6.     except KeyError:  
    7.         user = Users.objects.get(username='anony')  
    8.     except Users.DoesNotExist:  
    9.         user = Users.objects.get(username='anony')  
    10.     blogList = Blog.objects.filter(draft=False).order_by('title')  
    11.     content = { 'blog_list':blogList,  
    12.                 '<span style="color:#ff0000;">curruser</span>':<span style="color:#ff0000;">user</span>  
    13.                }  
    14.     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项,如下所示:

    1. # Users App urls.py  
    2. from django.conf.urls import url,include  
    3. from . import views  
    4. from myblog.views import index  
    5.   
    6. app_name='<span style="color:#ff0000;">users</span>'  
    7. urlpatterns = [  
    8.     url(r'^$', index, name='index'),  
    9.     url(r'^userregister/$',views.userregister,name='<span style="color:#ff0000;">userregister</span>'),  
    10.     url(r'^userlogin/$',views.userlogin,name='userlogin'),  
    11.     url(r'^loginResult/(?P<info>.*)$',views.loginResult,name='loginResult'),  
    12.     url(r'^registerResult/(?P<info>.*)$',views.registerResult,name='registerResult'),  
    13.     url(r'^logoff/$',views.logoff,name='logoff'),  
    14.     url(r'^userinfo/(?P<username>.*)$',views.userInfo,name='userInfo')  
    15. ]  
    16. # 红字即为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的模板就相对简单多了,如下所示:

    1. <!-- 404.html -->  
    2. {% extends "parentTemplate.html" %}  
    3. {% block content %}  
    4. <div class="list">  
    5. <p>页面未找到!</p>  
    6. <p><a href="{% url 'index' %}">返回首页</a></p>  
    7. </div>  
    8. {% 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目录结构如下:

    1. ├── users  
    2. │   ├── loginResult.html  
    3. │   ├── registerResult.html  
    4. │   ├── userinfo.html  
    5. │   ├── userlogin.html  
    6. │   └── userregister.html  
    7. └── 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,这一页面主要就是显示了用户注册的表单,如图所示:



    因此其模板也比较简单:从服务器获得表单对象并将其显示出来:

    1. <!-- userregister.html -->  
    2. {% extends "userTemplate.html" %}  
    3. {% block content %}  
    4. <h3>新用户注册</h3>  
    5. <form action="{% url 'users:userregister' %}" method="post" enctype="multipart/form-data">  
    6. {% csrf_token %}  
    7. {{ form.as_p }}  
    8. <p><input type="submit" value="提交"></p>  
    9. </form>  
    10. {% 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,这一页面用于显示注册成功与否:

    1. <!-- registerResult.html -->  
    2. {% extends "userTemplate.html" %}  
    3. {% block content %}  
    4. <h3>{{ result_info }}</h3>  
    5. <a href="{% url 'index' %}" >返回首页</a>  
    6. {% 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基本完全相同,因此一块放出来:
    1. <!-- userlogin.html -->  
    2. {% extends "userTemplate.html" %}  
    3. {% block content %}  
    4. <h3>用户登录</h3>  
    5. <form action="{% url 'users:userlogin' %}" method="post">  
    6. {% csrf_token %}  
    7. {{ form.as_p }}  
    8. <p><input type="submit" value="登录"></p>  
    9. </form>  
    10. {% endblock %}  
    11.   
    12. <!-- loginResult.html -->  
    13. {% extends "userTemplate.html" %}  
    14. {% block content %}  
    15. <h3>{{ result_info }}</h3>  
    16. <a href="{% url 'index' %}" >返回首页</a>  
    17. {% 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,用于显示用户信息:
    1. <!-- userinfo.html -->  
    2. {% extends "userTemplate.html" %}  
    3. {% block content %}  
    4. <h3>用户{{ username }}资料</h3>  
    5. <p>用户名: {{ username }}</p>  
    6. <p>注册时间: {{ registertime|date:"Y-m-d" }}</p>  
    7. <p>生日: {{ birthday|date:"Y-m-d H:i:s" }}</p>  
    8. <p>电子邮件: {{ email }}</p>  
    9. <p><a href="{% url 'index' %}">返回首页</a></p>  
    10. {% 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的方式部署在本地,这将会是一个大难点,敬请期待~

  • 相关阅读:
    jekins 实现Django项目的自动部署(ubuntu16.04,python2.7,django1.11)
    Ubuntu16.04 安装 Django
    小米笔记本 air 12.5寸 支持硬盘参数
    editplus5激活码
    jmeter UDV
    c语言 快速排序
    html禁止文本输入框记录输入记录,单击input出现输入过的记录
    python pstats ,profile 性能分析
    python profile性能分析
    python 获取本地语言和编码的代码
  • 原文地址:https://www.cnblogs.com/xiaoyaojinzhazhadehangcheng/p/8360452.html
Copyright © 2011-2022 走看看