mrevutskyi / flask-restless-ng

A Flask extension for creating simple ReSTful JSON APIs from SQLAlchemy models.
https://flask-restless-ng.readthedocs.io
Other
65 stars 11 forks source link

Examples / documentation needed #28

Closed luigi-bar closed 3 years ago

luigi-bar commented 3 years ago

Hi, many thanks for this wonderful library! I would like to request a couple of examples (if possible): 1) how to add a custom endpoint , i.e. a rest "function" (or should i use a plain flask post endpoint?) 2) how to apply some business logic for example during a POST (i.e. send info to another service, put a message to queue, whatever)

many thanks! Luigi

mrevutskyi commented 3 years ago

I'm just maintaining what @jfinkels has created, so credits should go to him :)

As for custom endpoints, yes - you can still use plain Flask endpoints alongside Flask-Restless. If you want to perform some additional actions with Flask-Restless's endpoints, you can use post-/pre-processors which are described here

Let me know if you have more questions

luigi-bar commented 3 years ago

Hi, thanks for the suggestions: for custom endpoints it works nicely, but I am having some difficulties with the additional actions. This is the scenario:

  1. client creates a record via POST
  2. server saves, gets id=33
  3. in the same transaction server would like to send a copy of this record to somewhere else (a message queue for example)
  4. for some reason step 3. fails, server would like to rollback all the transaction (including step 2.) and return error to client

I have tried with the code below (running on the docs example): the error is correctly sent to the client but the transaction is not rolled back (i.e. at the end I find id=33 on the sqlite3 database). Am i doing something worng? thanks!

class Person(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.Unicode)
    birth_date = db.Column(db.Date)

    @staticmethod
    def create_postprocessor(result, **kw):
        print("this is create_postprocessor with result="+str(result))

        ## let's say we have a data transfer/integration to another service / message queue
        ## sometimes it may fail

        ## dummy test: if id is odd , the action fails, I should rollback the transaction
        id=int(result['data']['id'])
        if  id % 2 == 1:
            db.session.rollback()
            raise flask_restless.ProcessingException(detail='Sync actions failed: odd id', status=400)

manager.create_api(Person, methods=['POST'] postprocessors={"POST_RESOURCE": [Person.create_postprocessor] }   )
mrevutskyi commented 3 years ago

I see what you mean. Please try version 2.2.6 I've updated the order in which session is being committed, so you should be able to rollback in post-processors

luigi-bar commented 3 years ago

Hi, thanks for the update, yes now POST are fine :) What about PATCH? Also, I have noticed that in the patch post-processor I get an empty "result" , is this expected? regards!

mrevutskyi commented 3 years ago

Updated for PATCH, also for PATCH and POST for relationships, version 2.2.7

As for an empty result, yes - this is currently expected, as JSON API requires:

A server MUST return a 200 OK status code if an update is successful,
the client’s current fields remain up to date, and the server responds
only with top-level meta data. In this case the server MUST NOT
include a representation of the updated resource(s)

The result will not be empty if there was a side effect update on your model

If a server accepts an update but also changes the resource(s) in ways other
than those specified by the request (for example, updating the updated-at attribute
or a computed sha), it MUST return a 200 OK response. The response document 
MUST include a representation of the updated resource(s) as if a GET request
was made to the request URL.

https://jsonapi.org/format/#crud-updating-responses-200