Django 学习五:前端页面设计

基本框架搭建好了后,我们就要开始丰富页面内容了。最起码,得有一个用户登录的表单不是么?(注册的事情我们先放一边。)

一、 原生HTML页面

删除原来的login.html文件中的内容,写入下面的代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录</title>
</head>
<body>

    <div style="margin: 15% 40%;">
        <h1>欢迎登录!</h1>
       <form action="/login/" method="post">
            <p>
                <label for="id_username">用户名:</label>
                <input type="text" id="id_username" name="username" placeholder="用户名" autofocus required />
            </p>
            <p>
                <label for="id_password">密码:</label>
                <input type="password" id="id_password" placeholder="密码" name="password" required >
            </p>
            <input type="submit" value="确定">
        </form>
    </div>

</body>
</html>

简单解释一下:

  • form标签主要确定目的地url和发送方法;
  • p标签将各个输入框分行;
  • label标签为每个输入框提供一个前导提示,还有助于触屏使用;
  • placeholder属性为输入框提供默认值;
  • autofocus属性为用户名输入框自动聚焦
  • required表示该输入框必须填写
  • passowrd类型的input标签不会显示明文密码

以上功能都是HTML5原生提供的,可以减少你大量的验证和JS代码,更详细的用法,请自行学习。

特别声明:所有前端的验证和安全机制都是不可信的,恶意分子完全可以脱离浏览器伪造请求数据!

启动服务器,访问http://127.0.0.1:8000/login/,可以看到如下图的页面:

14.png-9.4kB

二、引入Bootstrap

如果你的实际项目真的使用上面的那个页面,妥妥的被老板打死。代码虽然简单,速度虽然快,但没有CSS和JS,样子真的令人无法接受,在颜值即正义的年代,就是错误。

然而,大多数使用Django的人都不具备多高的前端水平,通常也没有专业的前端工程师配合,自己写的CSS和JS往往惨不忍睹。怎么办?没关系,我们有现成的开源前端框架!Bootstrap就是最好的框架之一!

前往Bootstrap中文网下载v3.3.7版本代码。建议同时下载用于生产环境的Bootstrap和源码两种版本。最后的Sass版本根据需要,自行决定。

用于生产环境的Bootstrap包含编译并压缩后的 CSS、JavaScript 和字体文件,但不包含文档和源码文件。这通常是给我们Django项目作为静态文件引入的。

而Bootstrap 源码包含Less、JavaScript 和 字体文件的源码,并且带有文档。其中的文档对我们很有用。

在Django的根目录下新建一个static目录,并将解压后的bootstrap-3.3.7-dist目录,整体拷贝到static目录中,如下图所示:

image.png

由于Bootstrap依赖JQuery,所以我们需要提前下载并引入JQuery,我这里使用的是jquery-3.2.1.js,当然别的版本也是可以的。(请自行下载JQuery)

在static目录下,新建一个css和js目录,作为以后的样式文件和js文件的存放地,将我们的jquery文件拷贝到static/js目录下。

image.png

三、静态文件设置

关于静态文件的设置,是很多初学者吐槽最多的地方。以后我们会一点一点讲解,这里先按步骤进行。

打开项目的settings文件,在最下面添加这么一行配置,用于指定静态文件的搜索目录:

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

四、创建base.html模板

既然要将前端页面做得像个样子,那么就不能和前面一样,每个页面都各写各的,单打独斗。一个网站有自己的统一风格和公用部分,可以把这部分内容集中到一个基础模板base.html中。现在,在根目录下的templates中新建一个base.html文件用作站点的基础模板。

在Bootstrap文档中,为我们提供了一个非常简单而又实用的基本模板,代码如下:

<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
    <title>Bootstrap 101 Template</title>

    <!-- Bootstrap -->
    <link href="css/bootstrap.min.css" rel="stylesheet">

    <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[if lt IE 9]>
      <script src="https://cdn.bootcss.com/html5shiv/3.7.3/html5shiv.min.js"></script>
      <script src="https://cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script>
    <![endif]-->
  </head>
  <body>
    <h1>你好,世界!</h1>

    <!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
    <script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>
    <!-- Include all compiled plugins (below), or include individual files as needed -->
    <script src="js/bootstrap.min.js"></script>
  </body>
</html>

我们将它整体拷贝到base.html文件中。然后修改login/templates/login/login.html文件,删除原来的所有内容,只写入如下一行代码:
{% extends 'base.html' %}
模板语言{% extends 'base.html' %},表示当前页面继承base.html文件中的所有内容。

启动服务器,访问localhost:8000/login/,暂时只能看见下面的内容,但没有关系,这表示我们的模板继承系统工作正常。

19.png-12.2kB

五、创建页面导航条

下面我们为页面增加一个导航条,Bootstrap提供了现成的导航条组件,代码如下:

<nav class="navbar navbar-default">
  <div class="container-fluid">
    <!-- Brand and toggle get grouped for better mobile display -->
    <div class="navbar-header">
      <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
        <span class="sr-only">Toggle navigation</span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
      </button>
      <a class="navbar-brand" href="#">Brand</a>
    </div>

    <!-- Collect the nav links, forms, and other content for toggling -->
    <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
      <ul class="nav navbar-nav">
        <li class="active"><a href="#">Link <span class="sr-only">(current)</span></a></li>
        <li><a href="#">Link</a></li>
        <li class="dropdown">
          <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
          <ul class="dropdown-menu">
            <li><a href="#">Action</a></li>
            <li><a href="#">Another action</a></li>
            <li><a href="#">Something else here</a></li>
            <li role="separator" class="divider"></li>
            <li><a href="#">Separated link</a></li>
            <li role="separator" class="divider"></li>
            <li><a href="#">One more separated link</a></li>
          </ul>
        </li>
      </ul>
      <form class="navbar-form navbar-left">
        <div class="form-group">
          <input type="text" class="form-control" placeholder="Search">
        </div>
        <button type="submit" class="btn btn-default">Submit</button>
      </form>
      <ul class="nav navbar-nav navbar-right">
        <li><a href="#">Link</a></li>
        <li class="dropdown">
          <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
          <ul class="dropdown-menu">
            <li><a href="#">Action</a></li>
            <li><a href="#">Another action</a></li>
            <li><a href="#">Something else here</a></li>
            <li role="separator" class="divider"></li>
            <li><a href="#">Separated link</a></li>
          </ul>
        </li>
      </ul>
    </div><!-- /.navbar-collapse -->
  </div><!-- /.container-fluid -->
</nav>

显示效果是这样的:

23.png-6.4kB

其中有一些部分,比如搜索框是我们目前还不需要的,需要将多余的内容裁剪掉。同时,有一些名称和url地址等需要按我们的实际内容修改。最终导航条的代码如下:

<nav class="navbar navbar-default">
      <div class="container-fluid">
        <!-- Brand and toggle get grouped for better mobile display -->
        <div class="navbar-header">
          <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#my-nav" aria-expanded="false">
            <span class="sr-only">切换导航条</span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
          </button>
          <a class="navbar-brand" href="#">Mysite</a>
        </div>

        <!-- Collect the nav links, forms, and other content for toggling -->
        <div class="collapse navbar-collapse" id="my-nav">
          <ul class="nav navbar-nav">
            <li class="active"><a href="/index/">主页</a></li>
          </ul>
          <ul class="nav navbar-nav navbar-right">
            <li><a href="/login/">登录</a></li>
            <li><a href="/register/">注册</a></li>
          </ul>
        </div><!-- /.navbar-collapse -->
      </div><!-- /.container-fluid -->
    </nav>

砍掉了很多内容,不过没关系,有需要的话随时可以增加。

下面用上面的代码,替换掉base.html中的h1标签。再次刷新页面,显示效果如下:

20.png-14.1kB

`

为什么会这样,因为Bootstrap的CSS和JS文件没有被正常导入!

六、使用Boostrap静态文件

通过{% static '相对路径' %}这个Django为我们提供的静态文件加载方法,可以将页面与静态文件链接起来。当然,还有一种办法是使用CDN,如果有可靠的源,也是可以使用的。

最后,base.html内容如下:

{% load staticfiles %}
<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
    <title>{% block title %}base{% endblock %}</title>

    <!-- Bootstrap -->
    <link href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}" rel="stylesheet">

    <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[if lt IE 9]>
      <script src="https://cdn.bootcss.com/html5shiv/3.7.3/html5shiv.min.js"></script>
      <script src="https://cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script>
    <![endif]-->
    {% block css %}{% endblock %}
  </head>
  <body>
    <nav class="navbar navbar-default">
      <div class="container-fluid">
        <!-- Brand and toggle get grouped for better mobile display -->
        <div class="navbar-header">
          <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#my-nav" aria-expanded="false">
            <span class="sr-only">切换导航条</span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
          </button>
          <a class="navbar-brand" href="#">Mysite</a>
        </div>

        <!-- Collect the nav links, forms, and other content for toggling -->
        <div class="collapse navbar-collapse" id="my-nav">
          <ul class="nav navbar-nav">
            <li class="active"><a href="/index/">主页</a></li>
          </ul>
          <ul class="nav navbar-nav navbar-right">
            <li><a href="/login/">登录</a></li>
            <li><a href="/register/">注册</a></li>
          </ul>
        </div><!-- /.navbar-collapse -->
      </div><!-- /.container-fluid -->
    </nav>

    {% block content %}{% endblock %}


    <!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
    <script src="{% static 'js/jquery-3.2.1.js' %}"></script>
    <!-- Include all compiled plugins (below), or include individual files as needed -->
    <script src="{% static 'bootstrap-4.0.0-dist/js/bootstrap.min.js' %}"></script>
  </body>
</html>

要点:

  • 通过页面顶端的{% load staticfiles %}加载后,才可以使用static方法;
  • 通过{% block title %}base{% endblock %},设置了一个动态的页面title块;
  • 通过{% block css %}{% endblock %},设置了一个动态的css加载块;
  • 通过{% block content %}{% endblock %},为具体页面的主体内容留下接口;
  • 通过{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}将样式文件指向了我们的实际静态文件,下面的js脚本也是同样的道理。

更多的前端页面知识,实在难以一言述尽,只能一点点解说,所以需要大家具备一定的基础。做Django开发,其实就是全栈开发,没有一定的前端能力,是做不好的。

好了,现在刷新下我们的页面,可以看到如下的效果:

21.png-10.5kB

由于Bootstrap以移动端优先的特性,我们的这个页面是可以动态调整的,尝试缩放一下屏幕大小,导航条会自动折叠和展开,也就是说你写的前端页面可以在手机、ipad上正常访问,但是IE.....,我们忘记它吧,哭。

七、设计登录页面

当前的登录页面只有网站的整体导航条,还没有添加最主要的登录表单。

Bootstarp提供了一个基本的表单样式,代码如下:

<form>
  <div class="form-group">
    <label for="exampleInputEmail1">Email address</label>
    <input type="email" class="form-control" id="exampleInputEmail1" placeholder="Email">
  </div>
  <div class="form-group">
    <label for="exampleInputPassword1">Password</label>
    <input type="password" class="form-control" id="exampleInputPassword1" placeholder="Password">
  </div>
  <div class="form-group">
    <label for="exampleInputFile">File input</label>
    <input type="file" id="exampleInputFile">
    <p class="help-block">Example block-level help text here.</p>
  </div>
  <div class="checkbox">
    <label>
      <input type="checkbox"> Check me out
    </label>
  </div>
  <button type="submit" class="btn btn-default">Submit</button>
</form>

外观如下:

25.png-17.5kB

我们结合Bootstrap和前面自己写的form表单,修改login/templates/login/login.html成符合项目要求的样子:

{% extends 'base.html' %}
{% load staticfiles %}
{% block title %}登录{% endblock %}
{% block css %}<link href="{% static 'css/login.css' %}" rel="stylesheet"/>{% endblock %}


{% block content %}
    <div class="container">
        <div class="col-md-4 col-md-offset-4">
          <form class='form-login' action="/login/" method="post">
              <h2 class="text-center">欢迎登录</h2>
              <div class="form-group">
                <label for="id_username">用户名:</label>
                <input type="text" name='username' class="form-control" id="id_username" placeholder="Username" autofocus required>
              </div>
              <div class="form-group">
                <label for="id_password">密码:</label>
                <input type="password" name='password' class="form-control" id="id_password" placeholder="Password" required>
              </div>
              <button type="reset" class="btn btn-default pull-left">重置</button>
              <button type="submit" class="btn btn-primary pull-right">提交</button>
          </form>
        </div>
    </div> <!-- /container -->
{% endblock %}

说明:

通过{% extends 'base.html' %}继承了‘base.html’模板的内容;
通过{% block title %}登录{% endblock %}设置了专门的title;
通过block css引入了针对性的login.css样式文件;
主体内容定义在block content内部
添加了一个重置按钮。
在static/css目录中新建一个login.css样式文件,这里简单地写了点样式,不算复杂。

body {
  background-color: #eee;
}
.form-login {
  max-width: 330px;
  padding: 15px;
  margin: 0 auto;
}
.form-login .form-control {
  position: relative;
  height: auto;
  -webkit-box-sizing: border-box;
     -moz-box-sizing: border-box;
          box-sizing: border-box;
  padding: 10px;
  font-size: 16px;
}
.form-login .form-control:focus {
  z-index: 2;
}
.form-login input[type="text"] {
  margin-bottom: -1px;
  border-bottom-right-radius: 0;
  border-bottom-left-radius: 0;
}
.form-login input[type="password"] {
  margin-bottom: 10px;
  border-top-left-radius: 0;
  border-top-right-radius: 0;
}

刷新页面,效果如下:

26.png-39.9kB

这个UI算不上好看,同样可以称为简陋,但是比较纯粹,你完全可以在这个基础上,定制一些自己的CSS样式,比如添加个背景图,就像我下面这样。这些工作不是本项目实战的重点,大家可以自行设计。

27.png-507.5kB

原文:http://www.liujiangblog.com/course/django/107

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