python-restx / flask-restx

Fork of Flask-RESTPlus: Fully featured framework for fast, easy and documented API development with Flask
https://flask-restx.readthedocs.io/en/latest/
Other
2.16k stars 335 forks source link

How to reuse the nested Resource methods in the encompassing Resource methods ? #441

Open realnitinworks opened 2 years ago

realnitinworks commented 2 years ago

I have a resource called Profile which nests a list of Port resources like so:

{
        "profile": "abcd"
        "ports": [
            {
                "port": "5687"
                "state": "state"
                "protocol": "protocol"
                "direction": "direction"
            }
        ]
 }

The profile key uniquely identifies theProfile resource and the ports key represents the nested list of Port resources. The port key in the Port resource uniquely identifies a port for the given Profile.

The two Resources are modeled like so:

PortModel = api.model("Port", 
    {
        "port": fields.String(required=True),
        "state": fields.String(required=True),
        "protocol": fields.String(),
        "direction": fields.String()
    },
)

ProfileModel = api.model("Profile",
    {
        "profile": fields.String(required=True),
        "ports": fields.List(fields.Nested(PortModel), required=True),
    },
)

The skeleton implementation of the two Resources is given below:

class Profile(Resource):    
    @api.expect(ProfileModel)
    def post(self):
        pass

class PortsList(Resource):
    @api.expect([PortModel])
    def post(self, profile):
        pass

Then the routes are as given below:

api.add_resource(Profile, "api/v1.0/profiles/")
api.add_resource(PortsList, "/api/v1.0/profiles/<profile>/ports")

Question:

When a POST request comes to /api/v1.0/profiles/<profile>/ports with the following body:

[
    {
        "port": "5687"
        "state": "state"
        "protocol": "protocol"
        "direction": "direction"
    }
]

the backend should create the list of Port resources for the given profile.

Similarly, when a POST request comes to api/v1.0/profiles with the following body:

{
    "profile": "abcd"
    "ports": [
        {
            "port": "5687"
            "state": "state"
            "protocol": "protocol"
            "direction": "direction"
        }
    ]
 }

Is it possible for the post method of Profile resource to automatically invoke and reuse the post method of Port resource passing to it the profile which uniquely identifies the Profile resource? If so, do I need to write my own code or the framework has the capability to handle this?

thedumbterminal commented 2 years ago

I've done this manually with a couple of linked SQLAlchemy models and then use the request body to create these models in code. Once the outer model is synced to the DB the linked models will be too.

realnitinworks commented 2 years ago

I've done this manually with a couple of linked SQLAlchemy models and then use the request body to create these models in code. Once the outer model is synced to the DB the linked models will be too.

Could you please elaborate? Are you saying that we need to find our own ways to do this and there is no specific support from flask-restx?

thedumbterminal commented 2 years ago

I'm not an expert in flask-restx, but just stating how i've achieved this:

https://github.com/thedumbterminal/ci-speed/blob/main/app/resources/TestRunList.py#L80

In the above example the post handler supports a xml file upload, which builds several linked models, which are written to the db in a single db.commit().

Hope this helps.