Bootstrap

Django 和 Vue3 前后端分离开发笔记

Django 和 Vue3 前后端分离开发笔记

1. Django Ninja API

Django Ninja 是一个用于使用 Django 和 Python 3.6+ 类型提示构建 API 的网络框架。它具有以下主要特点:

  1. 简单易懂:设计为易于使用和符合直觉,适合快速上手。
  2. 快速执行:多亏了 Pydantic 和异步支持,具有非常高的性能。
  3. 快速编程:类型提示和自动文档生成让开发者只需关注业务逻辑。
  4. 基于标准:基于 OpenAPI(以前称为 Swagger)和 JSON 模式。
  5. 对 Django 友好:与 Django 核心和 ORM 有良好的集成。
  6. 可用于生产:被多家公司用于实际项目,稳定可靠。
创建和使用 NinjaAPI
  1. 安装 Django Ninja

    pip install django-ninja
    
  2. 创建 Django 项目(如果还没有):

    django-admin startproject apidemo
    cd apidemo
    
  3. urls.py 中配置 API

    # apidemo/urls.py
    from django.contrib import admin
    from django.urls import path
    from ninja import NinjaAPI
    
    api = NinjaAPI()
    
    @api.get("/add")
    def add(request, a: int, b: int):
        return {"result": a + b}
    
    urlpatterns = [
        path("admin/", admin.site.urls),
        path("api/", api.urls),
    ]
    
  4. 运行项目

    python manage.py runserver
    
  5. 访问 API
    打开浏览器,访问 http://127.0.0.1:8000/api/add?a=1&b=2,你将看到 JSON 响应为:

    {"result": 3}
    
  6. 交互式 API 文档
    访问 http://127.0.0.1:8000/api/docs,你将看到自动的、交互式 API 文档(由 OpenAPI / Swagger UI 或 Redoc 提供)。

NinjaAPI 的主要参数
  • title:API 的标题。
  • version:API 的版本。
  • description:API 的描述。
  • openapi_url:OpenAPI 规范的相对 URL。
  • docs_url:API 文档的相对 URL。
  • servers:目标主机列表,用于 OpenAPI 规范。
  • csrf:是否要求 CSRF 令牌(已弃用,现在由 auth 处理)。
  • auth:认证类。
  • renderer:默认响应渲染器。
  • parser:默认请求解析器。
  • openapi_extra:OpenAPI 规范的额外属性。
示例

以下是一个更复杂的示例,展示了如何使用 NinjaAPI 创建一个带有输入和输出模型的 API:

# apidemo/api.py
from ninja import NinjaAPI, Schema
from ninja import UploadedFile, File
from django.core.files.storage import FileSystemStorage
from django.shortcuts import get_object_or_404
from .models import Employee, Department

api = NinjaAPI()

class EmployeeIn(Schema):
    first_name: str
    last_name: str
    department_id: int = None
    birthdate: date = None

class EmployeeOut(Schema):
    id: int
    first_name: str
    last_name: str
    department_id: int = None
    birthdate: date = None

@api.post("/employees")
def create_employee(request, payload: EmployeeIn, cv: UploadedFile = File(...)):
    fs = FileSystemStorage()
    filename = fs.save(cv.name, cv)
    payload_dict = payload.dict()
    payload_dict['cv'] = filename
    employee = Employee.objects.create(**payload_dict)
    return {"id": employee.id}

@api.get("/employees/{employee_id}")
def get_employee(request, employee_id: int):
    employee = get_object_or_404(Employee, id=employee_id)
    return EmployeeOut.from_orm(employee)

在这个示例中,我们定义了两个模型 EmployeeInEmployeeOut,分别用于输入和输出。我们还创建了两个 API 端点:一个用于创建员工,另一个用于获取员工信息。

urls.py 中使用 api.py
# apidemo/urls.py
from django.contrib import admin
from django.urls import path
from .api import api

urlpatterns = [
    path("admin/", admin.site.urls),
    path("api/", api.urls),
]

2. 跨域请求问题

从你提供的信息来看,你遇到了一个常见的跨源资源共享(CORS)问题。这个错误信息表明,当你从 http://localhost:5173 发起请求到 http://127.0.0.1:8000/api/test/ 时,服务器没有返回 Access-Control-Allow-Origin 头,导致浏览器阻止了这次请求。

解决 CORS 问题的方法
1. 在服务器端设置 CORS 头

最根本的解决方法是在服务器端设置 Access-Control-Allow-Origin 头。

手动设置

from django.http import HttpResponse

def my_view(request):
    # 创建一个HttpResponse对象
    response = HttpResponse("这是我的响应内容")
    
    # 手动设置CORS头部
    response['Access-Control-Allow-Origin'] = '*'
    
    return response

如果你使用的是 Django,可以安装 django-cors-headers 库来处理 CORS 问题。

  1. 安装 django-cors-headers

    pip install django-cors-headers
    
  2. settings.py 中配置

    # apidemo/settings.py
    
    INSTALLED_APPS = [
        ...
        'corsheaders',
        ...
    ]
    
    MIDDLEWARE = [
        ...
        'corsheaders.middleware.CorsMiddleware',
        'django.middleware.common.CommonMiddleware',
        ...
    ]
    
    CORS_ALLOWED_ORIGINS = [
        "http://localhost:5173",
    ]
    
  3. 确保 CORS_ALLOWED_ORIGINS 包含你的前端开发服务器的 URL

2. 使用代理

如果你无法修改服务器端的设置,可以在开发环境中使用代理来绕过 CORS 限制。Vite 提供了代理配置选项,可以在 vite.config.js 中设置。

  1. 创建或修改 vite.config.js

    // vite.config.js
    import { defineConfig } from 'vite';
    import vue from '@vitejs/plugin-vue';
    
    export default defineConfig({
      plugins: [vue()],
      server: {
        proxy: {
          '/api': {
            target: 'http://127.0.0.1:8000', 
            changeOrigin: true,
            rewrite: (path) => path.replace(/^\/api/, '')
          }
        }
      }
    });
    
  2. 修改请求 URL
    在前端代码中,将请求 URL 从 http://127.0.0.1:8000/api/test/ 改为 /api/test/

    // src/components/Person.vue
    fetch('/api/test/')
      .then(response => {
        if (!response.ok) {
          throw new Error('Network response was not ok');
        }
        return response.json();
      })
      .then(data => {
        console.log(data);
      })
      .catch(error => {
        console.error('There was a problem with the fetch operation:', error);
      });
    
检查和重试
  1. 检查 URL 的合法性

    • 确保 http://127.0.0.1:8000/api/test/ 是正确的,并且服务器已经启动。
    • 尝试在浏览器中直接访问该 URL,看是否能返回预期的结果。
  2. 重试请求

    • 有时候网络问题可能导致请求失败,可以尝试重新发送请求。
  3. 检查网络连接

    • 确保你的开发环境的网络连接正常,没有防火墙或代理服务器阻止请求。
总结

CORS 问题通常是由于服务器端没有正确设置 Access-Control-Allow-Origin 头导致的。你可以通过在服务器端设置 CORS 头或在开发环境中使用代理来解决这个问题。如果问题仍然存在,建议检查 URL 的合法性和网络连接,适当重试请求。

Vue3 前端项目设置

1. 创建 Vue3 项目

你可以使用 Vue CLI 或 Vite 来创建 Vue3 项目。这里以 Vite 为例:

npm create vite@latest frontend --template vue
cd frontend
npm install
npm install axios
2. 配置 main.js

确保在 main.js 中引入 Vue 和 Axios:

// frontend/src/main.js
import { createApp } from 'vue'
import App from './App.vue'
import axios from 'axios'

const app = createApp(App)
app.config.globalProperties.$axios = axios
app.mount('#app')
3. 创建组件

创建一个简单的组件来测试 API 请求:

<!-- frontend/src/components/Person.vue -->
<template>
    <div>
        <button @click="sendRequest">发送请求</button>
        <hr>
        <p>{{ response }}</p>
    </div>
</template>

<script setup>
import { ref } from 'vue';
import axios from 'axios';

const response = ref(null);

async function sendRequest() {
    try {
        const res = await axios.get('/api/test/');
        response.value = res.data;
    } catch (error) {
        console.error('请求失败:', error);
    }
}
</script>

<style scoped>
button {
    padding: 10px 20px;
    margin-bottom: 10px;
}
</style>
4. 运行 Vue3 项目
npm run dev

确保你的 Vue3 项目运行在 http://localhost:5173,并且通过 Vite 配置的代理正确地将请求发送到 Django 后端。

数据库模型示例

为了完整演示,这里提供一个简单的数据库模型示例:

# apidemo/models.py
from django.db import models

class Department(models.Model):
    name = models.CharField(max_length=100)

    def __str__(self):
        return self.name

class Employee(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    department = models.ForeignKey(Department, on_delete=models.SET_NULL, null=True, blank=True)
    birthdate = models.DateField(null=True, blank=True)
    cv = models.FileField(upload_to='cvs/', null=True, blank=True)

    def __str__(self):
        return f"{self.first_name} {self.last_name}"
5. 迁移数据库
python manage.py makemigrations
python manage.py migrate

测试和调试

  1. 确保后端和前端都在运行

    • 后端:http://127.0.0.1:8000
    • 前端:http://localhost:5173
  2. 检查浏览器控制台

    • 查看是否有任何错误信息。
    • 确认请求是否成功,并且返回的数据是否正确。
  3. 使用 Postman 或浏览器开发者工具

    • 使用 Postman 测试 API 端点。
    • 使用浏览器开发者工具查看网络请求和响应。
;