CRUD(增删改查)例子
CRUD - Create, Retrieve, Update, Delete (增删改查)是持久存储的四项基本功能。
这个示例将向你展示如何用 Django Ninja 来实现这些功能。
假设你有以下需要对其执行这些操作的 Django 模型:
class Department(models.Model):
title = models.CharField(max_length=100)
class Employee(models.Model):
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
department = models.ForeignKey(Department, on_delete=models.CASCADE)
birthdate = models.DateField(null=True, blank=True)
cv = models.FileField(null=True, blank=True)
现在让我们来对 Employee 创建 CRUD 操作。
C: 创建
创建一个 employee 对象的话,需要定义一个输入 schema:
from datetime import date
from ninja import Schema
class EmployeeIn(Schema):
first_name: str
last_name: str
department_id: int = None
birthdate: date = None
这个 schema 将是我们的传入的 payload:
@api.post("/employees")
def create_employee(request, payload: EmployeeIn):
employee = Employee.objects.create(**payload.dict())
return {"id": employee.id}
Tip
Schema
对象有 .dict()
方法,所有模式属性都表示为一个字典。
你可以传递它作为 **kwargs
给到 Django 模型的create
方法 (或模型的 __init__
).
参考下面的代码片段去处理文件上传 (通过 Django models 的形式):
from ninja import UploadedFile, File
@api.post("/employees")
def create_employee(request, payload: EmployeeIn, cv: UploadedFile = File(...)):
payload_dict = payload.dict()
employee = Employee(**payload_dict)
employee.cv.save(cv.name, cv) # will save model instance as well
return {"id": employee.id}
如果你仅仅需要上传一个文件:
from django.core.files.storage import FileSystemStorage
from ninja import UploadedFile, File
STORAGE = FileSystemStorage()
@api.post("/upload")
def create_upload(request, cv: UploadedFile = File(...)):
filename = STORAGE.save(cv.name, cv)
# Handle things further
R: 查
单个对象
现在为了获取 employee 对象,我们将定义一个模式,它将描述我们的响应会是什么样子。在这里,我们基本上将使用与 EmployeeIn
相同的模式,但会添加一个额外的属性 id
:
class EmployeeOut(Schema):
id: int
first_name: str
last_name: str
department_id: int = None
birthdate: date = None
注意
定义响应模式并非真正必需的,但当你进行定义时,你将获得结果验证、文档以及自动将 ORM 对象转换为 JSON 的功能。
我们将把这个模式用作我们使用 GET
方式获取 employee 视图的 响应
类型:
@api.get("/employees/{employee_id}", response=EmployeeOut)
def get_employee(request, employee_id: int):
employee = get_object_or_404(Employee, id=employee_id)
return employee
响应
模式会自动进行结果验证并转换为 JSON:
@api.get("/employees/{employee_id}", response=EmployeeOut)
def get_employee(request, employee_id: int):
employee = get_object_or_404(Employee, id=employee_id)
return employee
获取对象列表
要输出 employees 的列表,我们可以复用相同的 EmployeeOut
模式。我们只需将响应模式设置为 EmployeeOut
的List。
from typing import List
@api.get("/employees", response=List[EmployeeOut])
def list_employees(request):
qs = Employee.objects.all()
return qs
另一个很酷的技巧 - 注意我们只是返回了一个 Django ORM 查询集:
@api.get("/employees", response=List[EmployeeOut])
def list_employees(request):
qs = Employee.objects.all()
return qs
U: 更新
更新相当简单。我们只需使用 PUT
方法并同时传递 employee_id
:
@api.put("/employees/{employee_id}")
def update_employee(request, employee_id: int, payload: EmployeeIn):
employee = get_object_or_404(Employee, id=employee_id)
for attr, value in payload.dict().items():
setattr(employee, attr, value)
employee.save()
return {"success": True}
注意
在这里我们使用了 payload.dict
方法来设置所有对象的属性:
for attr, value in payload.dict().items()
你也可以明确的写成这样:
employee.first_name = payload.first_name
employee.last_name = payload.last_name
employee.department_id = payload.department_id
employee.birthdate = payload.birthdate
部分更新
为了允许用户进行部分更新,使用 payload.dict(exclude_unset=True).items()
。这确保了只有指定的字段会被更新。
强制严格字段验证
默认情况下,任何提供的不存在于模式中的字段将被静默忽略。要对这些无效字段引发错误,你可以在模式的 Config 类中设置 extra = "forbid"
。例如:
class EmployeeIn(Schema):
# your fields here...
class Config:
extra = "forbid"
D: 删除
删除也相当简单。我们只需通过 id
获取员工并从数据库中删除它:
@api.delete("/employees/{employee_id}")
def delete_employee(request, employee_id: int):
employee = get_object_or_404(Employee, id=employee_id)
employee.delete()
return {"success": True}
最终代码
这是一个完整的 CRUD 示例:
from datetime import date
from typing import List
from ninja import NinjaAPI, Schema
from django.shortcuts import get_object_or_404
from employees.models import Employee
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):
employee = Employee.objects.create(**payload.dict())
return {"id": employee.id}
@api.get("/employees/{employee_id}", response=EmployeeOut)
def get_employee(request, employee_id: int):
employee = get_object_or_404(Employee, id=employee_id)
return employee
@api.get("/employees", response=List[EmployeeOut])
def list_employees(request):
qs = Employee.objects.all()
return qs
@api.put("/employees/{employee_id}")
def update_employee(request, employee_id: int, payload: EmployeeIn):
employee = get_object_or_404(Employee, id=employee_id)
for attr, value in payload.dict().items():
setattr(employee, attr, value)
employee.save()
return {"success": True}
@api.delete("/employees/{employee_id}")
def delete_employee(request, employee_id: int):
employee = get_object_or_404(Employee, id=employee_id)
employee.delete()
return {"success": True}
大功告成
本教程到此结束!查看 How-to 系列 以获取更多信息。
Django ninja 周边生态:
-
django-ninja-crud : 是一个基于django-ninja来简化CRUD接口开发的框架,提供声明式的模型视图集及基于场景的测试方法。
-
django-ninja-extra : 是一个可以让开发者摆脱冗长Django文档,仅用少量代码就能快速构建强大Web应用和现代API接口的工具。
-
django-ninja-jwt : 为django-ninja提供的JSON Web Token插件,用于实现身份验证等相关功能,是从一个流行的Django Rest Framework插件分支而来。
评论
本文总阅读量次