Skip to content

前后端 HTTP 通信:以 Vue.js 和 Django 为例

2409 字约 8 分钟

网络全栈

2025-07-19

相关信息

之所以想写这篇文章是因为这段时间正好在做一个Django + Vue.js 的全栈项目,而我之前只在 FIT2081里有一些 Kotlin Jetpack Compose 的移动应用开发经验。尽管某种意义上来说,移动开发和传统的全栈开发有很多相似之处,但仍然存在一些关键的区别,尤其是我使用了 Kotlin Jetpack Compose 这个现代的声明式框架。得益于 Kotlin 的良好设计,使用 Jetpack Compose 开发移动应用的体验非常流畅,在使用 ORM 和 ViewModel 的时候,Kotlin 的生态提供了很好的支持,以至于后端的 model 和 viewmodel 还有 view 之间的交互非常自然,几乎无缝衔接。然而这样良好的编程体验却让我忽略了一个现在我才意识到的问题,前端和后端之间交互的复杂性

在 Web 开发中,前端和后端之间的通信对于创建动态和交互式应用程序至关重要。这种通信主要通过 HTTP 协议来处理。在本文中,我们将探讨 HTTP 的基础知识,并以 Vue.js 和 Django 为例,展示如何设置前端和后端之间的通信。

理解 HTTP

HTTP 是网络数据通信的基础。它是一个客户端-服务器协议,意味着请求由接收方(通常是 Web 浏览器)发起。一个完整的文档是由获取的不同的子文档重建的,例如,文本、布局描述、图像、视频、脚本等等。尽管 HTTP 可以用来传输任何类型的数据,有些甚至结构十分复杂,但 HTTP 协议本身并不关心数据的内容;它只关心数据的传输方式,因此,每一条 HTTP 信息的结构其实都十分简单。

注意

但是要注意,虽然本文中使用的称呼一直都是 HTTP 请求和 HTTP 响应,但实际上本文只讨论了一种最主流的 HTTP 请求和响应的模式,也叫做 RESTful API。RESTful API 是一种基于 HTTP 协议的架构风格,强调无状态、资源导向和统一接口。它使用标准的 HTTP 方法(如 GET、POST、PUT、DELETE)来操作资源,并通过 URL 来标识资源。其他常见的 API 风格还包括 GraphQL 和 gRPC,如果读者对这些感兴趣,可以自行查阅相关资料。

HTTP 请求结构

正如上文所示,HTTP 请求从客户端开始,因此我们先解释客户端的请求结构。

HTTP 请求是客户端向服务器发送的消息,请求服务器执行某个操作或返回某些数据。一个 HTTP 请求通常包含以下部分:

一个 HTTP 请求由以下部分组成:

  1. 请求行: 包括 HTTP 方法(例如,GET、POST、PUT、DELETE)、请求目标(通常是 URL)和 HTTP 版本。 其中:
  • HTTP 方法:指示请求的类型,例如 GET(获取资源)、POST(提交数据)、PUT(更新资源)或 DELETE(删除资源)。
  • 请求目标:通常是服务器上的资源路径,例如在一个后端运行的进程中,有一个url /api/users/,专门用于获取用户列表。
  • HTTP 版本:例如 HTTP/1.1 或 HTTP/2。
  1. 标头: 这些是键值对,提供有关请求的附加信息,例如内容类型、身份验证令牌和缓存指令。
  2. 正文: 这是一个可选部分,包含发送到服务器的数据,通常与 POST 和 PUT 等方法一起使用,例如提交表单数据或上传文件。这一部分往往需要涉及 json 等结构化数据格式的转换。

HTTP 响应结构

一个 HTTP 响应由以下部分组成:

  1. 状态行: 包括 HTTP 版本、状态代码(例如,200、404、500)和状态消息。
  2. 标头: 与请求标头类似,这些标头提供有关响应的信息。
  3. 正文: 包含从服务器发回的数据,可以是 HTML、JSON、XML 或其他格式,但通常是 JSON 格式。

常见的 HTTP 状态代码

  • 200 OK: 请求已成功。
  • 201 Created: 请求已完成,并导致创建了一个或多个新资源。
  • 400 Bad Request: 由于明显的客户端错误,服务器无法或不会处理该请求。
  • 404 Not Found: 服务器找不到请求的资源。
  • 500 Internal Server Error: 服务器遇到了不知道如何处理的情况。

使用 Django 设置后端

Django 是一个高级 Python Web 框架,鼓励快速开发和简洁、实用的设计。让我们创建一个返回用户列表的简单 API 端点。

现在,让我们创建一个简单的 Django 视图和 URL 配置。

提示

以下代码使用了 Python 的装饰器(decorator)功能,这是一种在函数或方法调用前后添加额外功能的方式。装饰器可以让代码更简洁、更易读。 详细可以阅读 Python 装饰器。简单来说,装饰器通过把其装饰的函数传入另外一个函数,并返回一个新的函数来实现功能的扩展。这是一种常见的高阶函数用法。

views.py

from django.http import JsonResponse # 从 Django 的 HTTP 模块导入 JsonResponse
from rest_framework.decorators import api_view # 从 Django REST Framework 导入 api_view 装饰器

@api_view(['GET'])
def user_list(request):
    """
    一个以 JSON 格式返回用户列表的视图。
    """
    # 此处只是一个示例数据,实际应用中可数据库查询获取json,这在许多数据库中都很容易实现。
    users = [
        {'id': 1, 'name': 'Alice'},
        {'id': 2, 'name': 'Bob'},
    ]
    return JsonResponse(users, safe=False)

urls.py

from django.urls import path
from .views import user_list

# 这是一个 URL 配置,将 API 端点映射到视图函数,用于与前端进行通信。
urlpatterns = [
    path('api/users/', user_list, name='user-list'),
]

使用 Vue.js 设置前端

Vue.js 是一个用于构建用户界面的渐进式 JavaScript 框架。我们将使用 axios 库向我们的 Django 后端发出 HTTP 请求。

现在,让我们创建一个 Vue 组件来获取和显示用户列表。

UserList.vue

<template>
  <div>
    <h1>用户列表</h1>
    <ul>
      <li v-for="user in users" :key="user.id">{{ user.name }}</li>
    </ul>
  </div>
</template>

<script>
import axios from 'axios';

export default {
  data() {
    return {
      users: [],
    };
  },
  mounted() {
    this.fetchUsers();
  },
  methods: {
    // 处理网络通信使用异步函数,如果你不了解具体原理,那么你只需要知道这么做是为了保证程序的执行顺序和结果正确
    async fetchUsers() {
      try {
        // await 关键字用于等待异步操作完成,只能用在声明为 async 的函数中
        const response = await axios.get('/api/users/'); 
        this.users = response.data;
      } catch (error) {
        console.error('获取用户时出错:', error);
      }
    },
  },
};
</script>

在此示例中,fetchUsers 方法向 后端暴露的/api/users/ 端点发送 GET 请求。当接收到数据时,它会存储在 users 数组中并显示在模板中。

在实际中,前端和后端进程往往运行在不同的端口上,因此需要配置 CORS(跨源资源共享)来允许跨域请求。Django 可以通过安装 django-cors-headers 包来轻松处理这一点。

结论

虽然我还是一名学习中的开发者,但通过这次使用 Vue.js 和 Django 搭建全栈项目的过程,我更清楚地意识到:前后端之间的通信其实远比我最初以为的要复杂得多。

HTTP 协议作为前后端沟通的桥梁,不只是简单的“请求-响应”,它背后涉及的请求方法、状态码、数据格式、跨域策略等,都在不同层面上影响着应用的健壮性和用户体验。本文只是一个初步的整理和总结,真正的系统开发远比示例代码要复杂得多,还需要考虑安全性、接口设计规范、错误处理、性能优化等等。

在写这篇文章的过程中,我也开始意识到 RESTful 只是众多 API 设计风格中的一种。随着了解逐渐加深,我也希望未来能尝试像 GraphQL 或 gRPC 这样的新方案,看看它们在实际开发中和 REST 有什么不同。

进一步阅读