question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

FastAPI-TortoiseORM: Problem regarding ForeignKeyField

See original GitHub issue

I use FastAPI with TortoiseORM to create a simple todo app. The problem happened when i tried to connect the todo models to the user using ForeignKeyField. Here’s the code. main.py

from typing import List
import os

from fastapi import FastAPI, Depends, HTTPException, status

from models import User, Todo, User_pydantic, UserIn_pydantic, Todo_pydantic, TodoIn_pydantic
from tortoise.contrib.fastapi import register_tortoise, HTTPNotFoundError

app = FastAPI()

@app.post("/users/", response_model=User_pydantic)
async def create_user(user: UserIn_pydantic):
    user_obj = await User.create(**user.dict(exclude_unset=True))
    return await User_pydantic.from_tortoise_orm(user_obj)


@app.get("/users/", response_model=List[User_pydantic])
async def read_all_users():
    return await User_pydantic.from_queryset(User.all())

models.py

from tortoise.models import Model
from tortoise import fields
from tortoise.contrib.pydantic import pydantic_model_creator


class Todo(Model):
    id = fields.IntField(pk=True)
    title = fields.CharField(500)
    description = fields.TextField(null=True)

Todo_pydantic = pydantic_model_creator(Todo, name="Todo")
TodoIn_pydantic = pydantic_model_creator(Todo, name="TodoIn", exclude_readonly=True)

class User(Model):
    id = fields.IntField(pk=True)
    username = fields.CharField(500, unique=True)
    email = fields.CharField(100, unique=True)
    password = fields.CharField(100)
    is_active = fields.BooleanField(default=True)
    todo: fields.ForeignKeyNullableRelation[Todo] = fields.ForeignKeyField("models.Todo", related_name="todo", null=True)

    class PydanticMeta:
        exclude = ["is_active", "todo"]

User_pydantic = pydantic_model_creator(User, name="User")
UserIn_pydantic = pydantic_model_creator(User, name="UserIn", exclude_readonly=True)

My expected result when creating a user Input

{
  "username":"string",
  "email":"string",
  "password:"string"
}

Output

{
  "id":1,
  "username":"string",
  "password":"string",
  "is_active":True,
  "todo":[]
}

The real result Input

{
  "username":"string",
  "email":"string",
  "password":"string"
}

Output

{
  "id":1,
  "username":"string",
  "password":"string",
  "is_active":True,
}

Error message in Swagger UI

{
  "detail": [
    {
      "loc": [],
      "msg": "null value in column \"todo_id\" of relation \"user\" violates not-null constraint\nDETAIL:  Failing row contains (6, bob, bob@email.com, bob123, t, null).",
      "type": "IntegrityError"
    }
  ]
}

Notice that there is no todo column in the output when creating a user

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:5 (1 by maintainers)

github_iconTop GitHub Comments

1reaction
metakotcommented, Nov 2, 2020

You need to clearly understand what you doing. In the function create_todo_list you take the user_id but are not using it anywhere =) And the docs for FastAPI is rare state-of-the-art, spoon-feeding almost anything what you need to know.

0reactions
BryanEgbertcommented, Oct 31, 2020

Thanks @metakot, the code removed the error when creating a user, but there is an internal server error when creating the todo for specific user. Due to the lack of tutorial for FastAPI w/ Tortoise ORM in relational models, i don’t know how to solve this. Here’s the code in main.py that relate to the problem i’m having.

@app.post("/users/{user_id}/todo/", response_model=Todo_pydantic)
async def create_todo_list(user_id: int, todo: TodoIn_pydantic):
    todo_obj = await Todo.create(**Todo.dict(exclude_unset=True))
    return await Todo_pydantic.from_tortoise_orm(todo_obj)


@app.get("/items/", response_model=List[Todo_pydantic])
async def read_todo():
    return await Todo_pydantic.from_queryset(Todo.all())

The updated models

class User(Model):
    id = fields.IntField(pk=True)
    username = fields.CharField(500, unique=True)
    email = fields.CharField(100, unique=True)
    password = fields.CharField(100)
    is_active = fields.BooleanField(default=True)

User_pydantic = pydantic_model_creator(User, name="User")
UserIn_pydantic = pydantic_model_creator(User, name="UserIn", exclude_readonly=True)

class Todo(Model):
    id = fields.IntField(pk=True)
    title = fields.CharField(500)
    description = fields.TextField(null=True)
    user = fields.ForeignKeyField("models.User", related_name="user", null=True)

Todo_pydantic = pydantic_model_creator(Todo, name="Todo")
TodoIn_pydantic = pydantic_model_creator(Todo, name="TodoIn", exclude_readonly=True)
Read more comments on GitHub >

github_iconTop Results From Across the Web

FastAPI + Tortoise ORM + FastAPI Users (Python) - ...
It was working fine, I receive only the user items (using owner_id), but my item table uses an external unique ID (the item...
Read more >
tortoise/community - Gitter
I am currently trying to add tortoise orm to my demo fastapi and when I define the models for tortoise orm. I got...
Read more >
Python Tortoise ORM Integration with FastAPI
In this post, I have not dealt with foreign keys, foreign key fields, or many to many, or other types of relationships between...
Read more >
FastAPI Examples — Tortoise ORM v0.17.3 Documentation
from tortoise import fields, models from tortoise.contrib.pydantic import pydantic_model_creator class Users(models.Model): """ The User model """ id ...
Read more >
Tortoise ORM - Tortoise ORM v0.19.3 Documentation
Tortoise ORM is supported on CPython >= 3.7 for SQLite, MySQL and PostgreSQL. ... An ORM (Object Relational Mapper) is designed to address...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found