mdconaway / fastapi-cruddy-framework

A holistic CRUD/MVC framework for FastAPI, with endpoint policies and relationships
MIT License
12 stars 4 forks source link

nested resources path support #5

Closed nashrafeeg closed 2 months ago

nashrafeeg commented 2 months ago

hi is there support for nested resource paths for nested models eg /users/{user_id}/posts/{post_id}/comments/{comment_id}/report or /section/{section_id}/posts/{post_id}/comments/{comment_id}/

given models are defined as below

class Comment author:str content:str favorited:List[str]=[] parent:Comment children:List[Comment]=[] post:Post class Post: author:User content:str comments:List[Comment]=[] section:Section class Section: owner:User name:str Posts:List[Post]=[] class User: posts:List[Post]=[] comments:List[Comment]=[] owns:List[Sections]=[]

mdconaway commented 2 months ago

Hi @nashrafeeg, thanks for your interest in this library!

Generally speaking, the path style you mentioned (something like /users/{user_id}/posts/{post_id}/comments/{comment_id}/report) is not required as each resource level in such a path structure is effectively redundant or superfluous.

Lets walk through an example demonstrating why this is true.

Given the schemas or path you outlined in your example: a user can have many posts, any one post can have many comments, and each comment can have a report.

To assemble the path as specified: /users/{user_id}/posts/{post_id}/comments/{comment_id}/report

A client would need to have a-priori knowledge of: user_id, post_id and comment_id

This would require the client to gather the relevant ids in three separate requests before assembling a route that fundamentally only needs to be represented as /comments/{comment_id}/report, a path which is already generated for you by cruddy.

In addition, if any parent id was incorrect or inaccessible to a client, all of the subordinate path segments would also fail or be unavailable.

And the relevant data object this path would be seeking to fetch would merely be a report object.

More generally, the data payload returned by cruddy for each resource already contains a links object for each data element which is designed to route a client to the proper REST endpoint to fetch that object's relations.

A client can therefore follow the links specified in the response data if it needs to gather related data.

In your example, if a client fetched some user object (with an example id of d7537642-1d65-12ec-7315-2dce1e2ee5d3) that user object would have an internal links object with a posts key, where the value of user.links.posts would point to the relative URL /users/d7537642-1d65-12ec-7315-2dce1e2ee5d3/posts, indicating the client can simply launch a GET request to that relative url to assemble the posts for that object.

If what you actually need is a way to sideload multiple data types simultaneously, and potentially specify multiple filters simultaneously, I would recommend you look into adding the cruddy graphQL controller to your application. This controller will span all of your resources and allow a client to send a single request that still routes through your individual resource policies for data security.

This graphQL controller / router is demonstrated here: https://github.com/mdconaway/fastapi-cruddy-framework/blob/master/examples/fastapi_cruddy_sqlite/controllers/graphql.py

Is mounted for routing here: https://github.com/mdconaway/fastapi-cruddy-framework/blob/master/examples/fastapi_cruddy_sqlite/router/application.py#L28

With root graphQL query model defined here: https://github.com/mdconaway/fastapi-cruddy-framework/blob/master/examples/fastapi_cruddy_sqlite/models/query.py

And the common graphQL model classes are defined here to avoid circular imports: https://github.com/mdconaway/fastapi-cruddy-framework/blob/master/examples/fastapi_cruddy_sqlite/models/common/graphql.py

In the next minor version of cruddy, there will be an automatic graphQL generator that should make enabling graphQL even simpler, but for now the graphQL layer can be added in this manual fashion.

Does the above explanation and possible graphQL solution help solve the problem you are seeking to address?

nashrafeeg commented 2 months ago

hi thanks for taking time to explain yes i believe the graphql solution fits my use case. thanks