Search code examples
pythondjangodjango-rest-frameworkdatabase-schemadjango-ninja

how to make a post request for a model with a foreign key in django-ninja using api


My models looks like this:

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}'

The schemas I used are:

class ORDERin(Schema):
    productID: int
    customerID: int
    quantity: int
    price: float

class ORDERout(Schema):
    id: int
    productID: int 
    customerID: int
    quantity: int
    price: float

This is how I tried to do the post api

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]}

When I tried to test this post request, I got this error: "ValueError: Cannot assign "1": "ORDER.productID" must be a "PRODUCT" instance." I don't know what I messed up here, probably my schemas but I don't know how to do it the right way.


Solution

  • Update your schemas

    from pydantic import BaseModel
    class ORDERin(BaseModel):
        productID: int
        customerID: int
        quantity: int
        price: float
    
    class ORDERout(BaseModel):
        id: int
        productID: int
        customerID: int
        quantity: int
        price: float
    

    and update your api

    from ninja import Router
    from myapp.models import ORDER, PRODUCT, CUSTOMER
    from myapp.schemas import ORDERin, ORDERout
    
    order_router = Router()
    
    @order_router.post('/post', response=List[ORDERout])
    def post_order(request, data: ORDERin):
        product = PRODUCT.objects.get(pk=data.productID)
        customer = CUSTOMER.objects.get(pk=data.customerID)
        
        order = ORDER(
            productID=product,
            customerID=customer,
            quantity=data.quantity,
            price=data.price
        )
        order.save()
        
        return [ORDERout(**order.__dict__)]
    

    Ensure that you've imported the necessary modules correctly and that the app's models and schemas are properly structured. This code should work correctly now, creating an ORDER instance with the appropriate references to PRODUCT and CUSTOMER instances and returning a list of ORDERout instances in the API response.