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
相关推荐
卸任5 分钟前
Vibe coding工具使用心得
前端·ai编程
brien91 小时前
为什么模型标称 1M,Google Antigravity 聊到 256K 却突然失忆?我们给它做了个原生行内监控圆环
前端
修炼的dance1 小时前
录屏关键帧间隔多少合适?六档实测,2秒到10秒小了75.6%
前端
Lank_M1 小时前
关键帧从1秒拉到10秒,录屏小87.3%,摄像头小10.8%
前端
补码缩写1 小时前
用 ffprobe 拆录屏,八成字节在 29 个关键帧上
前端
百思不得小李1 小时前
一个复杂的动态表单是如何实现的
前端·设计模式
陈随易1 小时前
Cmder 停更 17 个月,2.0 支持 Windows Terminal
前端·后端·程序员
风骏时光牛马2 小时前
前沿视界
前端
kyriewen2 小时前
我扫了 814 个依赖,97 个还敢要 Node 10
前端·javascript·程序员
陈随易2 小时前
3000 万人在用的翻译插件,重写一遍就是一门生意
前端·后端·程序员