vitalik / django-ninja

💨 Fast, Async-ready, Openapi, type hints based framework for building APIs
https://django-ninja.dev
MIT License
6.96k stars 420 forks source link

Primary key is not an integer #897

Open msopacua opened 10 months ago

msopacua commented 10 months ago

My models don't use Autofield, but CUIDs, which are strings. Any foreign key in a model throws an error, that the <fieldname>_Id is not an integer. I know it isn't, but how do I make pydantic believe it?

% find $VIRTUAL_ENV/lib/python3.11/site-packages/ninja -name '*.py' -exec pcregrep -rn '(?<!operation)_id' {} + |sed -e 's,^.*-packages/ninja/,,'
openapi/schema.py:117:        op_id = operation.operation_id or self.api.get_openapi_operation_id(operation)
openapi/schema.py:118:        if op_id in self.all_operation_ids:
openapi/schema.py:120:                f'operation_id "{op_id}" is already used (func: {operation.view_func})'
openapi/schema.py:122:        self.all_operation_ids.add(op_id)
openapi/schema.py:124:            "operationId": op_id,

How do we tell Ninja that foreign keys are a string or do we need to exclude the FK name (child) and reimplement it?

vitalik commented 10 months ago

@msopacua could you provide more details - what's CUID ? is it some external field ?

could you make some reproducable example ?

msopacua commented 10 months ago

Hmm, I tried that, but in the simple case I can't trigger the error. What I'm seeing is this:

ValidationError                           Traceback (most recent call last)
Cell In[4], line 1
----> 1 MySchema.from_orm(rec)

File ~/..../python3.11/site-packages/ninja/schema.py:164, in Schema.from_orm(cls, obj)
    157 getter_dict = cls.__config__.getter_dict
    158 obj = (
    159     # DjangoGetter also needs the class so it can find resolver methods.
    160     getter_dict(obj, cls)
    161     if issubclass(getter_dict, DjangoGetter)
    162     else getter_dict(obj)
    163 )
--> 164 return super().from_orm(obj)

File ~/.../python3.11/site-packages/pydantic/main.py:579, in pydantic.main.BaseModel.from_orm()

ValidationError: 1 validation error for MySchema
child_id
  value is not a valid integer (type=type_error.integer)

If I do that with a simple Book/Author model it works as expected. I'll have to dig a bit deeper to what the issue is here. In the mean time, I can work around it with the model_exclude for the FK and reimplementing it using a resolver.

I'll close this, till I can figure out the underlying cause.

msopacua commented 10 months ago

Ok, I figured out the issue.

The problem is multi-table inheritance. When I change the model to abstract it works.

Here's a repo showing the issue with 2 tests, one failing, one succeeding.

msopacua commented 10 months ago

Added the 1.x branch to show it is also happening with 1.x.