Django 和 Vue3 前后端分离开发笔记
1. Django Ninja API
Django Ninja 是一个用于使用 Django 和 Python 3.6+ 类型提示构建 API 的网络框架。它具有以下主要特点:
- 简单易懂:设计为易于使用和符合直觉,适合快速上手。
- 快速执行:多亏了 Pydantic 和异步支持,具有非常高的性能。
- 快速编程:类型提示和自动文档生成让开发者只需关注业务逻辑。
- 基于标准:基于 OpenAPI(以前称为 Swagger)和 JSON 模式。
- 对 Django 友好:与 Django 核心和 ORM 有良好的集成。
- 可用于生产:被多家公司用于实际项目,稳定可靠。
创建和使用 NinjaAPI
-
安装 Django Ninja:
shpip install django-ninja
-
创建 Django 项目(如果还没有):
shdjango-admin startproject apidemo cd apidemo
-
在
urls.py
中配置 API:python# 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), ]
-
运行项目:
shpython manage.py runserver
-
访问 API :
打开浏览器,访问
http://127.0.0.1:8000/api/add?a=1&b=2
,你将看到 JSON 响应为:json{"result": 3}
-
交互式 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:
python
# 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)
在这个示例中,我们定义了两个模型 EmployeeIn
和 EmployeeOut
,分别用于输入和输出。我们还创建了两个 API 端点:一个用于创建员工,另一个用于获取员工信息。
在 urls.py
中使用 api.py
:
python
# 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
头。
手动设置
python
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 问题。
-
安装
django-cors-headers
:shpip install django-cors-headers
-
在
settings.py
中配置:python# apidemo/settings.py INSTALLED_APPS = [ ... 'corsheaders', ... ] MIDDLEWARE = [ ... 'corsheaders.middleware.CorsMiddleware', 'django.middleware.common.CommonMiddleware', ... ] CORS_ALLOWED_ORIGINS = [ "http://localhost:5173", ]
-
确保
CORS_ALLOWED_ORIGINS
包含你的前端开发服务器的 URL。
2. 使用代理
如果你无法修改服务器端的设置,可以在开发环境中使用代理来绕过 CORS 限制。Vite 提供了代理配置选项,可以在 vite.config.js
中设置。
-
创建或修改
vite.config.js
:javascript// 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/, '') } } } });
-
修改请求 URL :
在前端代码中,将请求 URL 从
http://127.0.0.1:8000/api/test/
改为/api/test/
。javascript// 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); });
检查和重试
-
检查 URL 的合法性:
- 确保
http://127.0.0.1:8000/api/test/
是正确的,并且服务器已经启动。 - 尝试在浏览器中直接访问该 URL,看是否能返回预期的结果。
- 确保
-
重试请求:
- 有时候网络问题可能导致请求失败,可以尝试重新发送请求。
-
检查网络连接:
- 确保你的开发环境的网络连接正常,没有防火墙或代理服务器阻止请求。
总结
CORS 问题通常是由于服务器端没有正确设置 Access-Control-Allow-Origin
头导致的。你可以通过在服务器端设置 CORS 头或在开发环境中使用代理来解决这个问题。如果问题仍然存在,建议检查 URL 的合法性和网络连接,适当重试请求。
Vue3 前端项目设置
1. 创建 Vue3 项目
你可以使用 Vue CLI 或 Vite 来创建 Vue3 项目。这里以 Vite 为例:
sh
npm create vite@latest frontend --template vue
cd frontend
npm install
npm install axios
2. 配置 main.js
确保在 main.js
中引入 Vue 和 Axios:
javascript
// 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 请求:
vue
<!-- 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 项目
sh
npm run dev
确保你的 Vue3 项目运行在 http://localhost:5173
,并且通过 Vite 配置的代理正确地将请求发送到 Django 后端。
数据库模型示例
为了完整演示,这里提供一个简单的数据库模型示例:
python
# 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. 迁移数据库
sh
python manage.py makemigrations
python manage.py migrate
测试和调试
-
确保后端和前端都在运行:
- 后端:
http://127.0.0.1:8000
- 前端:
http://localhost:5173
- 后端:
-
检查浏览器控制台:
- 查看是否有任何错误信息。
- 确认请求是否成功,并且返回的数据是否正确。
-
使用 Postman 或浏览器开发者工具:
- 使用 Postman 测试 API 端点。
- 使用浏览器开发者工具查看网络请求和响应。