Advice on writing a package for Django integration


#1

Hello.

I’ve got two apistar projects in production at the moment. Unfortunately, they’ve both had to stay at <0.4.0 because of the removal of the ORM components.

I’m interested in upgrading and am therefore interested in writing a package to re-introduce Django support. The problem lies in the fact that I’m not sure where to start. The SQLAlchemy integrations seem fairly straight-forward, but I fear a similar Django integration would be more complicated.

If anyone has done this integration already, or knows a good place to start it would be much appreciated.

Thank you


#2

Hi,

I would start placing everything in the old Django ORM integration similar to the the new 0.5.x SQLAlchemy integration.

  • The configure() and setup() goes into Component.__init__().
  • Session can go into Component.resolve().
  • get_session() goes into hooks like the SQLAlchemy integration.
  • commands probably you can place where you want and just main.add_command(your_func) like in main.py.

Good component!


#3

@pslacerda Thank you for the advice. It really helped. I’ve made the component and it seems to work. I did a fairly simple test case.

Here it is: https://github.com/AceFire6/apistar-django

Any recommendations/advice on structure/problems with the implementation would be greatly appreciated.


#4

Not that I’m aware of, seems nice for me.

Maybe you prefeer to use a @transaction decorator that set an _atomic attribute on your handlers and return the handler as is.

def transaction(handler):
    handler._atomic = True

Then DjangoTransactionHook.on_request can instantiate Atomic and enter in the transaction context only if this attribute is present or true.

 def on_request(self, handler: Route):
    if getattr(handler, '_atomic', False):
        Atomic.__enter__()

 def on_response(self, handler: Route, response: Response, exc: Exception) -> Response:
    if getattr(handler, '_atomic', False):
        Atomic.__exit__()
     return response

Then you can opt-in if an handler be atomic or not.

def h1(non_atomic_session: Session):
    return non_atomic_session.Model.get(id=1)

@transaction
def h2(atomic_session: Session):
    m = atomic_session.Model.get(id=1)
    m.column = 'changed'
    m.save()

Or even simply:

@Atomic()
def h3(session: Session):
    return session.Model.get(id=1).column

I’m no sure about all details but you can do something like the above.

You can also setup() your Django ORM layer directly on a module and forget about components if you like, could also be a great option if you have problems with autocompletion.


#5

Sorry about @Atomic, seems that it don’t work as I expected. However the remaining seems to be true.


#6

@pslacerda Thanks for the advice. I really like your ideas. I’ve begun implementing them :grin:

This one, in particular, intrigues me

How did you imagine this working?


#7

You can put everything about django setup and configuration inside a function (eg setup_django()) and call it in some __init__.py or where else your initialization occurs.