如何在Django Ninja中为含外键的模型编写POST请求接口?
Django Ninja外键模型POST接口错误解决
问题重现
为带外键的ORDER模型编写POST接口时,触发如下错误:
ValueError: Cannot assign "1": "ORDER.productID" must be a "PRODUCT" instance.
相关代码如下:
模型代码
from django.db import models class PRODUCT(models.Model): name = models.CharField(max_length=50) price = models.FloatField() def __str__(self): return f'{self.name}- {self.price}' class CUSTOMER(models.Model): name = models.CharField(max_length=50) email = models.EmailField(max_length=254) def __str__(self): return f'{self.name}-{self.email}' class ORDER(models.Model): productID = models.ForeignKey(PRODUCT, on_delete=models.CASCADE, null=True,blank=True) customerID = models.ForeignKey(CUSTOMER, on_delete=models.CASCADE,null=True,blank=True) quantity = models.IntegerField() price = models.FloatField() def __str__(self): return f'{CUSTOMER.pk}-{PRODUCT.pk}-{self.quantity}'
Schema定义
class ORDERin(Schema): productID: int customerID: int quantity: int price: float class ORDERout(Schema): id: int productID: int customerID: int quantity: int price: float
POST接口代码
from ninja import Router from myapp.models import ORDER from myapp.schemas import ORDERin,ORDERout from typing import List order_router = Router() @order_router.post('/post') def post_order(request, data: ORDERin): qs = ORDER.objects.create(**data.dict()) return {List[ORDERout]}
错误原因
Django的外键字段(如ORDER.productID)要求传入对应模型的实例对象,而非直接传入整数ID。当前Schema传递的是整数ID,直接解构传给create()会触发类型不匹配错误。同时接口返回的return {List[ORDERout]}是语法错误,需用Schema序列化创建好的实例。
修复方案
方案一:修改Schema字段名匹配Django外键ID后缀
Django会自动为外键字段生成字段名_id的数据库列,直接在Schema中使用该后缀名即可传递ID:
- 更新ORDERin Schema:
class ORDERin(Schema): productID_id: int # 对应外键的ID列 customerID_id: int quantity: int price: float
- 修正接口返回逻辑:
@order_router.post('/post', response=ORDERout) def post_order(request, data: ORDERin): order = ORDER.objects.create(**data.dict()) return ORDERout.from_orm(order)
方案二:在接口中根据ID获取模型实例
保持原Schema不变,先通过ID查询对应PRODUCT和CUSTOMER实例,再传入create():
@order_router.post('/post', response=ORDERout) def post_order(request, data: ORDERin): # 获取对应模型实例 product = PRODUCT.objects.get(pk=data.productID) customer = CUSTOMER.objects.get(pk=data.customerID) # 创建订单 order = ORDER.objects.create( productID=product, customerID=customer, quantity=data.quantity, price=data.price ) return ORDERout.from_orm(order)
注:若需处理ID不存在的情况,可添加try-except捕获DoesNotExist异常,返回404错误。
额外优化建议
- 遵循Django命名规范:模型名用单数(如
Product而非PRODUCT),外键字段名用小写下划线格式(如product而非productID),提升代码可读性。 - 使用Django Ninja的
ModelSchema自动生成Schema,减少手动编写工作量:
from ninja import ModelSchema class ORDERin(ModelSchema): class Config: model = ORDER fields = ['productID', 'customerID', 'quantity', 'price']
内容的提问来源于stack exchange,提问作者invisible
相关产品推荐
相关产品推荐

