Closed joaoflaviosantos closed 1 year ago
Hi @joaoflaviosantos
sure - FilterSchemas are injected into OpenAPI schemas - so generate-client should pick it up as parameters just fine
Hello again @vitalik!
Not really.. When using "filters: JobFilterSchema = Query(...)" the schema does not appear in the OpenAPI documentation in the Schemas part. Only if we use the following format "filters: JobFilterSchema = None".
The package "openapi-typescript-codegen" even generates a "service" file, as follows:
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
import type { PaginatedResponseSchema_JobCreateSchemaOut_ } from '../models/PaginatedResponseSchema_JobCreateSchemaOut_';
import type { CancelablePromise } from '../core/CancelablePromise';
import { OpenAPI } from '../core/OpenAPI';
import { request as __request } from '../core/request';
export class JobsService {
/**
* Listagem paginada de jobs
* @param id
* @param state
* @param queueName
* @param q
* @param page
* @param pageSize
* @returns PaginatedResponseSchema_JobCreateSchemaOut_ OK
* @throws ApiError
*/
public static c996F4C8ControllerListaJobs(
id?: string,
state?: Array<string>,
queueName?: Array<string>,
q?: string,
page: number = 1,
pageSize: number = 100,
): CancelablePromise<PaginatedResponseSchema_JobCreateSchemaOut_> {
return __request(OpenAPI, {
method: 'GET',
url: '/api/jobs',
query: {
'id': id,
'state': state,
'queue_name': queueName,
'q': q,
'page': page,
'page_size': pageSize,
},
});
}
}
However, our need is for the package "openapi-typescript-codegen" to generate a "model" file, as below (when we use "filters: JobFilterSchema = None", which is incorrect):
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export type JobFilterSchema = {
id?: string;
state?: Array<string>;
queue_name?: Array<string>;
'q'?: string;
};
Is there any way for me to force the generation of the Schema in the documentation using the correct format "filters: JobFilterSchema = Query(...)"?
Thanks in advance!
Hello again @vitalik!
Here's how we solved this development requirement.
We chose to use the "service" class that the package "openapi-typescript-codegen" automatically generates for endpoint or controller (in this case we are using the Django Ninja Extra extension from @eadwinCode).
However, we added the "operation_id" parameter to each route/endpoint to fix the dynamic creation of functions names in the service class generated by the "openapi-typescript-codegen" package:
## External Imports
from ninja_extra import api_controller, route, ControllerBase
from ninja_extra.pagination import (
PageNumberPaginationExtra,
PaginatedResponseSchema,
paginate,
)
from ninja import Query
## Internal Imports
from apps.jobs.models import Job
from apps.jobs.schemas import (
JobCreateSchemaOut,
JobFilterSchema
)
@api_controller('/jobs', permissions=None, tags=['Jobs'])
class JobController(ControllerBase):
model = Job
@route.get(
'',
response=PaginatedResponseSchema[JobCreateSchemaOut],
summary='Listagem paginada de jobs',
url_name='listagem-paginada-de-jobs',
operation_id='listagem-paginada-de-jobs'
)
@paginate(PageNumberPaginationExtra, max_page_size=101)
def lista_jobs(self, filters: JobFilterSchema = Query(...)):
return filters.filter(self.model.objects.all())
In this way the code generated by the "openapi-typescript-codegen" package, was as follows:
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
import type { PaginatedResponseSchema_JobCreateSchemaOut_ } from '../models/PaginatedResponseSchema_JobCreateSchemaOut_';
import type { CancelablePromise } from '../core/CancelablePromise';
import { OpenAPI } from '../core/OpenAPI';
import { request as __request } from '../core/request';
export class JobsService {
/**
* Listagem paginada de jobs
* @param id
* @param state
* @param queueName
* @param q
* @param page
* @param pageSize
* @returns PaginatedResponseSchema_JobCreateSchemaOut_ OK
* @throws ApiError
*/
public static listagemPaginadaDeJobs(
id?: string,
state?: Array<string>,
queueName?: Array<string>,
q?: string,
page: number = 1,
pageSize: number = 100,
): CancelablePromise<PaginatedResponseSchema_JobCreateSchemaOut_> {
return __request(OpenAPI, {
method: 'GET',
url: '/api/jobs',
query: {
'id': id,
'state': state,
'queue_name': queueName,
'q': q,
'page': page,
'page_size': pageSize,
},
});
}
}
In this way, with the fixed names of the methods of the class it will be possible to create a function that extracts the parameters of the functions and converts them into typescript interfaces/types.
Thanks for your willingness to help. And again, congratulations on the excellent work!
Hello again @vitalik!
Unfortunately, due to technical limitations of typescript, it is not possible to generate a dynamic typing of the query functions of the "service" file, generated by the package "openapi-typescript-codegen" :
type ListagemPaginadaDeJobsParams = Parameters<typeof JobsService['listagemPaginadaDeJobs']>
Using the above code, it would generate the following type:
type ListagemPaginadaDeJobsParams = [id?: string | undefined, state?: string[] | undefined, queueName?: string[] | undefined, q?: string | undefined, page?: number | undefined, pageSize?: number | undefined]
Get type of parameter list of a function (parametersof?)
In that sense, can you help me in any way to externalize in openapi.json the FilterSchema classes?
I've actually tested it here, and the only way it works is if we use the FilterSchema in the route of the following method "filters: JobFilterSchema = None".
I think another approach would be to use the openapi_extra method. As I questioned in this other issue #791.
Thanks in advance for the help.
Hello again @vitalik!
For the record for future doubts:
This demand has been resolved on this other issue #791.
The final code was as follows, using the Django Ninja Extra extension from @eadwinCode:
## External Imports
from ninja_extra import NinjaExtraAPI
## Internal Imports
from apps.jobs.schemas import JobFilterSchema
class NinjaWithExtraOpenAPI(NinjaExtraAPI):
def get_openapi_schema(self, *args, **kwargs):
schema = super().get_openapi_schema(*args, **kwargs)
schema["components"]["schemas"]["JobFilterSchema"] = JobFilterSchema.schema()
return schema
api = NinjaWithExtraOpenAPI(...)
Again, thanks for the help and congratulations on the excellent work with Django Ninja!
Hello @vitalik! Thanks for this great project!
We are using Django Ninja to develop our retail application.
We are using the Python FilterSchema class, as described in the documentation section below:
https://django-ninja.rest-framework.com/guides/input/filtering/
On the frontend, we are using the "openapi-typescript-codegen" package, as exemplified in the section of the FastAPI library below:
https://fastapi.tiangolo.com/advanced/generate-clients/#generate-a-typescript-client
Our question is, can we include FiltersSchemas in the generation of OpenAPI documentation?
This would be very useful in typing the frontend query parameters, where we use the RTK Query from the Redux Tool Kit.
Thanks in advance!