You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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:

  1. 更新ORDERin Schema:
class ORDERin(Schema):
    productID_id: int  # 对应外键的ID列
    customerID_id: int
    quantity: int
    price: float
  1. 修正接口返回逻辑:
@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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 09:50:55