简体   繁体   中英

Django Ninja API framework Foreing Key ValueError: Cannot assign must be instance

My project running Django 4.1 and Ninja 0.19.1. I'm trying to make a post request via Swagger or Postman and getting an error ValueError: Cannot assign "115": "Offer.currency_to_sell" must be a "Currency" instance.

Post data is:

{
  "currency_to_sell_id": 115,
  "currency_to_buy_id": 116,
  "user_id": 1,
  "amount": 100,
  "exchange_rate": 10
}

Endpoint in api.py

@api.post("/add_offer/")
async def add_offer(request, payload: OfferIn):
    offer = await Offer.objects.acreate(**payload.dict())
    return {"id": offer.pk}

schemas.py

class OfferIn(ModelSchema):
    class Config:
        model = Offer
        model_fields = [
            "currency_to_sell",
            "currency_to_buy",
            "user",
            "amount",
            "exchange_rate",
        ]

Offer model is:

class Offer(models.Model):
    """Sell currency offer model."""

    currency_to_sell = models.ForeignKey(
        to="Currency",
        on_delete=models.CASCADE,
        related_name="currencies_to_sell",
        verbose_name="Currency to sell",
    )
    currency_to_buy = models.ForeignKey(
        to="Currency",
        on_delete=models.CASCADE,
        related_name="currencies_to_buy",
        verbose_name="Currency to buy",
    )
    amount = models.DecimalField(
        decimal_places=2, max_digits=11, blank=False, null=False, verbose_name="Amount"
    )
    exchange_rate = models.DecimalField(
        decimal_places=2,
        max_digits=11,
        blank=False,
        null=False,
        verbose_name="Exchange rate",
    )
    user = models.ForeignKey(
        to=User, on_delete=models.CASCADE, related_name="offers", verbose_name="User"
    )

What am I doing wrong? I tried different approach with Schema instead of ModelSchema and it worked.

class OfferIn(Schema):
    currency_to_sell_id: int = None
    currency_to_buy_id: int = None
    user_id: int = None
    amount: float
    exchange_rate: float

UPDATE. I do not know is this right approach, but it works.

@api.post("/offer/", tags=["Offer"])
async def add_offer(request, payload: OfferIn):

    currency_to_sell = await Currency.objects.aget(id=payload.currency_to_sell)
    currency_to_buy = await Currency.objects.aget(id=payload.currency_to_buy)
    user = await User.objects.aget(id=payload.user)
    payload.currency_to_sell = currency_to_sell
    payload.currency_to_buy = currency_to_buy
    payload.user = user
    offer = await Offer.objects.acreate(**payload.dict())
    return {"id": offer.pk}

I changed a data in payload.

As you can see in your Offer model you have a field called currency_to_sell , it contains an object of the Currency model so when you are sending an id in your POST request you're getting the following error:

Cannot assign "115": "Offer.currency_to_sell" must be a "Currency" instance.

Therefore you have two options:

  1. When you generate the form, add a hidden field that also includes the content type id as explained in this answer https://stackoverflow.com/a/32110462/14535309
  2. Change your Offer model in a way that the currency_to_sell is actually just an id of a Currency and then use that in your views to query the db for the required Currency object.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM