Web应用程序:设置应用程序的样式并部署

一、设置项目"学习笔记"的样式

之前,我们特意一直专注于项目"学习笔记"的功能,没有考虑样式设置的问题。这是一种不错的开发方法,因为能正确运行的应用程序才是有用的。应用程序能够正确运行之后,外观就显得很重要了,因为漂亮的应用程序才能吸引用户。

本节将安装应用程序 django-bootstrap5,并将其添加到项目"学习笔记"中。然后使用它来设置这个项目中各个页面的样式,确保页面的外观一致。

1. 应用程序 django-bootstrap5

下面使用 django-bootstrap5 将 Bootstrap 集成到项目"学习笔记"中。这个应用程序会下载必要的 Bootstrap 文件,并将它们放到项目的合适位置上,让你能够在项目的模板中使用样式设置指令。

为了安装 django-bootstrap5,在活动的虚拟环境中执行如下命令:

python 复制代码
pip install django-bootstrap5

接下来,需要将 django-bootstrap5 添加到 settings.py 的INSTALLED_APPS 中:

python 复制代码
INSTALLED_APPS = [
    # 添加我的应用
    'learning_logs',
    'accounts',
    # 第三方应用程序
    'django_bootstrap5'
]

2. 使用 Bootstrap 设置项目"学习笔记"的样式

Bootstrap 包含大量样式设置工具,还提供了大量模板,用于设置项目的总体风格。对于 Bootstrap 初学者来说,模板比样式设置工具用起来容易得多。要查看 Bootstrap 提供的模板,可访问其官网主页并单击 Examples。我们将使用模板 Navbar static,它提供了简单的顶部导航栏以及用于放置页面内容的容器。

3. 修改 base.html

我们需要修改模板 base.html,以使用前述 Bootstrap 模板。这里将分五步逐步修改 base.html。这个文件很大,可以直接从配套的源代码文件中复制过来。即便复制了这个文件,也应仔细阅读接下来的几小节,弄明白都做了哪些修改。

  • 定义 HTML 头部

对 base.html 所做的第一个修改是,在其中定义 HTML 头部。我们将添加一些代码,以便能够在模板中使用 Bootstrap。此外,还要给页面添加标题。请删除 base.html 的全部代码,并输入如下代码:

base.html

html 复制代码
<!--编写的 HTML 文档-->
<!DOCTYPE html>
<!--首先,将这个文件声明为使用英语-->
<html lang="en">
<!--HTML 文件分为两大部分:头部(head)和主体(body)。在这个文件中,头部始于起始标签 <head>-->
<head >
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!--    HTML 文件的头部不包含任何页面内容,而只向浏览器提供正确显示页面所需的信息。这里包含一个<title> 元素-->
    <title>Learning Log</title>
    <!--  在头部末尾,加载 django-bootstrap5 提供的模板标签集  -->
    {% load django_bootstrap5 %}
    {% bootstrap_css %}
    {% bootstrap_javascript %}
</head>
  • 定义导航栏

定义页面顶部导航栏的代码很长,因为需要同时支持较窄的手机屏幕和较宽的台式机显示器。

下面是导航栏定义代码的开头:

base.html

html 复制代码
<body>
  <nav class="navbar navbar-expand-md navbar-light bg-light mb-4 border">
    <div class="container-fluid">
      <a class="navbar-brand" href="{% url 'learning_logs:index' %}">
        Learning Log
      </a>
      <button class="navbar-toggler" type="button" data-bs-toggle="collapse"
        data-bs-target="#navbarCollapse" aria-controls="navbarCollapse"
        aria-expanded="false" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
      </button>
      <div class="collapse navbar-collapse" id="navbarCollapse">
        <ul class="navbar-nav me-auto mb-2 mb-md-0">
          <li class="nav-item">
            <a class="nav-link" href="{% url 'learning_logs:topics' %}">
              Topics
            </a>
          </li>
        </ul>
      </div>
    </div>
  </nav>
  {% block content %}{% endblock content %}
</body>
  • 添加用户账户链接

还需要添加与用户账户相关的链接。我们先来添加与账户相关的链接,再添加注销表单。

对文件 base.html 做如下修改:

html 复制代码
<ul class="navbar-nav ms-auto mb-2 mb-md-0">
  {% if user.is_authenticated %}
    <li class="nav-item">
      <span class="navbar-text me-2">Hello, {{ user.username }}.</span>
    </li>
  {% else %}
    <li class="nav-item">
      <a class="nav-link" href="{% url 'accounts:register' %}">Register</a>
    </li>
    <li class="nav-item">
      <a class="nav-link" href="{% url 'accounts:login' %}">Log in</a>
    </li>
  {% endif %}
</ul>
  • 在导航栏中添加注销表单

我们将其放在了 base.html 的末尾。下面将其放在一个更好的地方------导航栏中:

base.html

html 复制代码
        {% if user.is_authenticated %}
          <form action="{% url 'accounts:logout' %}" method='post'>
            {% csrf_token %}
            <button name='submit' class='btn btn-outline-secondary btn-sm'>
              Log out
            </button>
          </form>
        {% endif %}
  • 定义页面的主要部分

base.html 的余下部分包含页面的主要部分:

base.html

html 复制代码
<main class="container">
    <div class="pb-2 mb-2 border-bottom">
      {% block page_header %}{% endblock page_header %}
    </div>
    <div>
      {% block content %}{% endblock content %}
    </div>
  </main>

上面代码综合如下:

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Learning Log</title>
    {% load django_bootstrap5 %}
    {% bootstrap_css %}
    {% bootstrap_javascript %}
</head>
<body>
  <nav class="navbar navbar-expand-md navbar-light bg-light mb-4 border">
    <div class="container-fluid">
      <a class="navbar-brand" href="{% url 'learning_logs:index' %}">
        Learning Log
      </a>
      <button class="navbar-toggler" type="button" data-bs-toggle="collapse"
        data-bs-target="#navbarCollapse" aria-controls="navbarCollapse"
        aria-expanded="false" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
      </button>
      <div class="collapse navbar-collapse" id="navbarCollapse">
        <ul class="navbar-nav me-auto mb-2 mb-md-0">
          <li class="nav-item">
            <a class="nav-link" href="{% url 'learning_logs:topics' %}">
              Topics
            </a>
          </li>
        </ul>
        <ul class="navbar-nav ms-auto mb-2 mb-md-0">
          {% if user.is_authenticated %}
            <li class="nav-item">
              <span class="navbar-text me-2">Hello, {{ user.username }}.</span>
            </li>
          {% else %}
            <li class="nav-item">
              <a class="nav-link" href="{% url 'accounts:register' %}">Register</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="{% url 'accounts:login' %}">Log in</a>
            </li>
          {% endif %}
        </ul>
        {% if user.is_authenticated %}
          <form action="{% url 'accounts:logout' %}" method='post'>
            {% csrf_token %}
            <button name='submit' class='btn btn-outline-secondary btn-sm'>
              Log out
            </button>
          </form>
        {% endif %}
      </div>
    </div>
  </nav>
  <main class="container">
    <div class="pb-2 mb-2 border-bottom">
      {% block page_header %}{% endblock page_header %}
    </div>
    <div>
      {% block content %}{% endblock content %}
    </div>
  </main>
</body>
</html>

4. 使用 jumbotron 设置主页的样式

下面使用 Bootstrap 元素 jumbotron 来修改主页。jumbotron 元素是一个大框,在页面中显得鹤立鸡群,通常用于在主页中呈现简要的项目描述和让用户采取行动的元素。

修改后的文件 index.html 如下所示:

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    {% extends 'learning_logs/base.html' %}
    {% block page_header %}
      <div class="p-3 mb-4 bg-light border rounded-3">
        <div class="container-fluid py-4">
          <h1 class="display-3">Track your learning.</h1>
          <p class="lead">Make your own Learning Log, and keep a list of the
            topics you're learning about. Whenever you learn something new
            about a topic, make an entry summarizing what you've learned.</p>
          <a class="btn btn-primary btn-lg mt-1"
            href="{% url 'accounts:register' %}">Register >></a>
        </div>
      </div>
    {% endblock page_header %}
    {% block content %}
    <p>Learning Log helps you keep track of your learning, for any topic you're interested in.</p>
    {% endblock content %}
</body>
</html>

5. 设置登录页面的样式

我们改进了登录页面的整体外观,但还未设置登录表单的样式。下面来修改文件 login.html,让表单的外观与页面的其他部分一致:

login.html

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
  {% extends 'learning_logs/base.html' %}
  {% load django_bootstrap5 %}

  {% block page_header %}
    <h2>Log in to your account.</h2>
  {% endblock page_header %}

  {% block content %}
    {% if form.errors %}
      <p>Your username and password didn't match. Please try again.</p>
    {% endif %}
    
    <form action="{% url 'accounts:login' %}" method='post'>
      {% csrf_token %}
      {% bootstrap_form form %}
      {% bootstrap_button button_type="submit" content="Log in" %}
    </form>
  {% endblock content %}
</body>
</html>

运行结果如下:

6. 设置页面 topics 的样式

下面来确保用于查看信息的页面也有合适的样式,首先来设置页面topics 的样式:

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    {% extends 'learning_logs/base.html' %}

    {% block page_header %}
      <h1>Topics</h1>
    {% endblock page_header %}

    {% block content %}
      <ul class="list-group border-bottom pb-2 mb-4">
        {% for topic in topics %}
          <li class="list-group-item border-0">
            <a href="{% url 'learning_logs:topic' topic.id %}">
              {{ topic.text }}
            </a>
          </li>
        {% empty %}
          <li class="list-group-item border-0">No topics have been added yet.</li>
        {% endfor %}
      </ul>
      <a href="{% url 'learning_logs:new_topic' %}">Add a new topic</a>
    {% endblock content %}
</body>
</html>

7. 设置页面 topic 中条目的样式

在页面 topic 中,我们将使用 Bootstrap 组件 card 来突出显示每个条目。card 是带灵活的预定义样式的嵌套 <div>,非常适合用于显示主题的条目:

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    {% extends 'learning_logs/base.html' %}

    {% block page_header %}
      <h1>{{ topic.text }}</h1>
    {% endblock page_header %}

    {% block content %}
      <p>
        <a href="{% url 'learning_logs:new_entry' topic.id %}">Add new entry</a>
      </p>

      {% if entries %}
        <ul class="list-group border-bottom pb-2 mb-4">
          {% for entry in entries %}
            <li class="list-group-item border-0">
              <h4>
                {{ entry.date_added|date:'M d, Y H:i' }}
                <small><a href="{% url 'learning_logs:edit_entry' topic.id entry.id %}">Edit entry</a></small>
              </h4>
              <div>{{ entry.text|linebreaks }}</div>
            </li>
          {% endfor %}
        </ul>
      {% else %}
        <p>There are no entries for this topic yet.</p>
      {% endif %}
    {% endblock content %}
</body>
</html>

运行结果如下:

二、部署"学习笔记"

至此,项目"学习笔记"的外观已经很专业了,下面将其部署到服务器上,让任何有互联网连接的人都能够使用它。我们将使用 Platform.sh,这是一个基于 Web 的平台,供我们管理 Web 应用程序的部署。我们将让"学习笔记"在 Platform.sh 上运行起来。

1. 注册 Platform.sh 账户

要注册账户,请访问 Platform.sh 官方主页,并单击 Free Trial 按钮。编写期间Platform.sh 提供了免费试用服务(free tier),不要求你提供信用卡。在试用期间,你可以部署应用程序和少量资源,这让你能够在在线环境中测试应用程序,进而决定是否要购买收费托管套餐。

2. 安装 Platform.sh CLI

要将项目部署到 Platform.sh 服务器上并对其进行管理,需要使用Platform.sh CLI(command lineinterface,命令行界面)中的工具。要安装该 CLI 的最新版本,可访问其文档 Command line interface (CLI),并根据你使用的操作系统按相应的说明做。

在大多数系统中,可以在终端窗口中执行如下命令来安装 Platform.sh CLI:

python 复制代码
curl -fsS https://platform.sh/cli/installer | php

执行这个命令后,要使用该 CLI,需要打开一个新的终端窗口

3. 安装 platformshconfig

还需安装一个名为 platformshconfig 的包。这个包可帮助我们监测项目运行在本地系统还是 Platform.sh 服务器上。为了安装这个包,可在活动的虚拟环境中执行如下命令:

python 复制代码
pip install platformshconfig

4. 创建文件 requirements.txt

远程服务器需要知道项目"学习笔记"依赖于哪些包,因此我们将使用pip 生成一个文件,在其中列出这些包。为此,在活动的虚拟环境中执行如下命令:

python 复制代码
pip freeze > requirements.txt

命令 freeze 让 pip 将项目中当前安装的所有包的名称都写入文件requirements.txt。请打开文件 requirements.txt,查看项目中安装的包及其版本:

requirements.txt

python 复制代码
asgiref==3.5.2
beautifulsoup4==4.11.1
Django==4.1
django-bootstrap5==21.3
platformshconfig==2.4.0
soupsieve==2.3.2.post1
sqlparse==0.4.2

项目"学习笔记"依赖于 7 个特定版本的包,因此只在远程服务器有相应的环境时才能正确地运行。在这 7 个包中,有 3 个是我们手动安装的,其他4 个是作为依赖的包自动安装的。

5. 其他部署需求

在线服务器还需要另外两个包,它们用于为生产环境中的项目提供服务,因为在生产环境中,可能有很多用户同时发出请求。

在 requirements.txt 所在的目录中,新建一个文件并将其命名为requirements_remote.txt,然后在其中添加如下两个包:

6. 添加配置文件

所有托管平台都需要一些配置,这样项目才能在服务器上正确地运行。本节将添加如下三个配置文件。

  • platform.app.yaml:这是项目的主配置文件,向 Platform.sh 指出了当前部署的项目是什么类型的以及该项目需要什么样的资源,还包含用于在服务器上构建项目的命令。
  • platform/routes.yaml:这个文件定义了通往项目的路由。Platform.sh收到请求后,将根据这些配置将请求交给特定的项目。
  • platform/services.yaml:这个文件定义了项目所需的其他服务。

这些都是 YAML(YAML Ain't Markup Language,YAML 不是标记语言)文件。YAML 是一种旨在用于编写配置文件的语言,无论是人还是计算机都能轻松地读取。你可以手动编写或修改典型的 YAML 文件,计算机也能够读取并准确无误地解读这种文件。

  • 配置文件 .platform.app.yaml

个配置文件是最长的,因为它控制着整个配置过程。我们将分几部分进行介绍。你既可以在文本编辑器中手动输入它,也可以从本书的源代码文件中找到它。

下面是文件 .platform.app.yaml 的第一部分,应将该文件存储在manage.py 所在的目录中:

python 复制代码
name: "ll_project"
type: "python:3.10"

relationships:
  database: "db:postgresql"

# 应用程序被暴露到网上时使用的配置
web:
  upstream:
    socket_family: unix
  commands:
    start: "gunicorn -w 4 -b unix:$SOCKET ll_project.wsgi:application"
  locations:
    "/":
      passthru: true
    "/static":
      root: "static"
      expires: 1h
      allow: true

# 应用程序的永久性磁盘的大小(单位为 MB)
disk: 512

# 设置用于读写日志的本地挂载
mounts:
  "logs":
    source: local
    source_path: logs

# 在应用程序生命周期的不同时间点执行的钩子(hook)
hooks:
  build: |
    pip install --upgrade pip
    pip install -r requirements.txt
    pip install -r requirements_remote.txt
    mkdir logs
    python manage.py collectstatic
    rm -rf logs
  deploy: |
    python manage.py migrate
  • 配置文件 routes.yaml

路由(route)指的是请求在被服务器处理的过程中经过的路径。Platform.sh 需要知道应将收到的请求发送到哪里。

manage.py 所在的目录中新建一个文件夹,并将其命名为.platform(不要遗漏开头的句点)。在这个文件夹中新建一个文件,将其命名为 routes.yaml,并在其中输入如下内容:

python 复制代码
"https://{default}/":
  type: upstream
  upstream: "ll_project:http"
"https://www.{default}/":
  type: redirect
  to: "https://{default}/"

这个文件确保 URL 形如 https://project_url.com 和www.project_url.com 的请求都将被路由到同一个地方。

  • 配置文件 services.yaml

这是最后一个配置文件,它指定了项目运行所需的服务。将这个文件与 routes.yaml 一起保存到目录 .platform/ 中:

platform/services.yaml

7. 为部署到 Platform.sh 而修改 settings.py

现在需要在 settings.py 末尾添加一个片段,在其中指定一些Platform.sh 环境设置:

python 复制代码
from pathlib import Path
from platformshconfig import Config

config = Config()

if config.is_valid_platform():
    # 添加 Platform.sh 域名到允许的 host
    ALLOWED_HOSTS.append('.platformsh.site')

    # 设置静态文件根目录
    if config.appDir:
        STATIC_ROOT = Path(config.appDir) / 'static'

    # 设置 Django 的 SECRET_KEY
    if config.projectEntropy:
        SECRET_KEY = config.projectEntropy

    # 仅在运行而非构建时配置数据库
    if not config.in_build():
        db_settings = config.credentials('database')
        DATABASES = {
            'default': {
                'ENGINE': 'django.db.backends.postgresql',
                'NAME': db_settings['path'],
                'USER': db_settings['username'],
                'PASSWORD': db_settings['password'],
                'HOST': db_settings['host'],
                'PORT': db_settings['port'],
            },
        }

8. 使用 Git 跟踪项目文件

使用 Git 意味着在尝试实现新功能时无须担心破坏项目。在将项目部署到服务器上时,需要确保部署的是可行版本。

  • 安装 Git

你的系统中,可能已经安装了 Git。要确定是否安装了 Git,可打开一个新的终端窗口,并在其中执行命令 git --version:

  • 配置 Git

Git 跟踪是谁修改了项目,即便项目由一个人开发也是如此。为了进行跟踪,Git 需要知道你的用户名和电子邮箱地址。因此,你必须提供用户名,但对于练习项目,可随便伪造一个电子邮箱地址:

  • 忽略文件

无须让 Git 跟踪项目中的每个文件,因此我们让它忽略一些文件。在manage.py 所在的文件夹中创建一个名为 .gitignore 的文件(请注意,这个文件名以句点打头且不包含扩展名),并在其中输入如下代码:

python 复制代码
ll_env/
__pycache__/
*.sqlite3
  • 提交项目

我们需要为"学习笔记"初始化一个 Git 仓库,将所有必要的文件都加入进来,并提交项目的初始状态,如下所示:

9. 在 Platform.sh 上创建项目

当前,项目"学习笔记"虽然还运行在本地系统上,但已经经过了配置,能够在远程服务器上正确地运行。下面使用 Platform.sh CLI 在远程服务器上新建一个项目,再将项目"学习笔记"推送到该服务器上。

打开一个终端窗口,切换到目录 learning_log/,并执行如下命令:

python 复制代码
platform login

下面来创建一个项目。输出很多,我们将分几部分来介绍创建过程。首先,执行命令 create:

python 复制代码
platform create
python 复制代码
ll_project
python 复制代码
us-3.platform.sh

10. 推送到 Platform.sh

最后一步是将代码推送到远程服务器上,然后就可以查看项目的在线版本了。请执行如下命令:

python 复制代码
platform push

11. 查看线上项目

完成推送工作后,就可以打开项目了:

python 复制代码
platform url
相关推荐
夕除2 小时前
javaweb--08
前端·firefox
小李子呢02112 小时前
前端八股Vue---生命周期函数
前端·javascript·vue.js
浪客川2 小时前
【百例RUST - 007】结构体
java·前端·rust
美狐美颜sdk2 小时前
视频平台如何实现实时美颜?Android/iOS直播APP美颜SDK接入指南
android·前端·人工智能·ios·音视频·第三方美颜sdk·视频美颜sdk
ZHENGZJM2 小时前
前端流式通信 Hook:useBlogStream 详解
前端·全栈开发
人道领域2 小时前
【黑马点评日记02】Redis解决Tomcat集群Session共享问题
java·前端·后端·架构·tomcat·firefox
MRDONG12 小时前
从 Prompt 到智能体:深入理解 APE、Active-Prompt、DSP、PAL、ReAct 与 Reflexion
前端·react.js·prompt
翻斗包菜2 小时前
实战:使用 HAProxy 搭建高可用 Web 负载均衡集群
运维·前端·负载均衡
凯强同学2 小时前
不上班,想裸辞,可以不可以?
服务器·前端·javascript