I’ve been working on this for a bit now and felt it was finally at a point where I could share it. I’d love to get any feedback!
I really love the front page with all the getting started examples. Those are the kind of thoughtful touches and attention to detail that make me want to use an open source framework.
This looks interesting, and makes good use of typing. It also looks similar to Apistar, which is another python framework for APIs that also uses typing. Could you please describe the differences between these two? I’ve been using Apistar for a project for a while and it works great so far.
Thanks! I tried to do that on the motivation page. Basically, I wanted more control over the component lifecycle (molten lets you define which components are cacheable (reused during a single request) and which are singletons), I think apistar’s hooks are super clunky and, as an apistar user myself, this announcement kind of scared me, especially after the huge 0.3 to 0.4 transition.
I’m sorry, I was so amazed by all the examples on the homepage that I’ve missed the “motivation” link.
That explains it to me, thank you. I also wasent aware of the change of focus re. Apistar, I’m still running 0.3 but I share your concern.
I’ll definitively have a thorough look at Molten and will give porting my API over to it a try.
I played around with it and molten is awesome. Still not sure, whether type hints are pythonic or not, but this gave me another tilt towards finding it perfectly suitable, especially for the web dev use case.
This specific usage of the type annotations is nice in terms of visual clutter, but I think that it will require extra cognitive work to understand and write the code.
I disagree, type hints are awesome especially for things like this.
Usually, when your route takes e.g. a user_id you either have to use the right regex (in Django’s urls.py) or remember to validate it yourself in every route. Screw up once -> boom.
Molten, similar to Rocket for Rust, makes sure that you’re handler is only called when the passed user_id is a valid integer (assuming user_id: int).
This becomes even more valuable with more complex types.
I agree that type hints can be useful to make sure that these kinds of bugs are taken care of easily. But the way it is used in the Todo example is that the TodoManager class is passed as an annotation in the methods “list_todos” and “get_todos” . Why not just use a keyword argument for this?
Why not just use a keyword argument for this?
Why not just use a keyword argument for this?
That “just” makes the problem seem less complicated than it really is! :D
Let’s say you’re using a framework like falcon that doesn’t provide DI support out of the box. Assuming you wanted to
then your API might look something like this:
from falcon import API
# Define Database and TodoManager here...
def __init__(self, todo_manager):
self.todo_manager = todo_manager
def on_get(self, req, resp):
resp.media = self.todo_manager.get_all()
def setup_app(db_impl=Database, todo_manager_impl=TodoManager):
db = db_impl()
todo_manager = todo_manager_impl(db)
app = API()
# In your entrypoint:
app = setup_app()
# In your tests:
app = setup_app(db_impl=StubDatabase)
This isn’t bad and it’s explicit, but manually configuring the dependency tree can get quite hairy over time and when a particular component’s dependencies change, rather than only changing that component’s code to depend on different deps, you’ll have to also change all of the places where the dependency tree is constructed (not a huge deal if you have this sort of setup_app function like I’ve got above, but not a particularly fun thing to do either way). Another downside here is that it’s not immediately clear what components the TodosResource.get method relies on from its header.
If, instead, you use type annotations to do the wiring for you then you get the best of all worlds in exchange for a little bit of magic (that, in my experience, people get used to fairly quickly).
I hope that makes sense!
Yeah, I was reminded a lot of Rocket when I was reading the examples. Which is a good thing. There are a lot of things in Rocket I wish I was able to do more transparently in Django.
Can someone maybe explain when one should use an API framework and when something like a micro framework such as flask or django?
I wouldn’t call Django a micro framework. It is more a full featured web frameworks which works well for building web applications. However, it is not intentionally designed for building small footprint APIs (although it is perfectly possible, e.g. together with django-rest-framework).
Flask is a general purpose framework but with a smaller footprint. This is a real micro framework imho.
Molten looks much like flask but it adds some interesting aspects like type hinting, dependency injection and is primarily designed for building APIs.
So, in general the more your use case leans towards a full blown (multi page) web app, the more likely Django might be a good candidate to look at, the more you’re just building APIs, the more something like Molten could be a thing to look at. Flask is somewhere in between.
However, as all three of those frameworks would certainly be able to fit nearly more or less any web based use case, remember there are some other things to consider when choosing a framework, such as developer’s knowledge or preference, availability of third party libs, popularity/community etc.
Yeah Django is optimized for making it incredibly easy to create server side database driven applications. It’s also great for creating APIs, but it’s still optimized for the use case of “define your data model and we’ll take care of the rest”.
For some people like myself who are web dev newbies, that can be a huge bonus, but lots of folks want more flexibility and less overhead, so packages like this come in.
Looks very interesting. Would you be considering a BSD license? (I personally don’t mind but since LGPL contains the substring “GPL”, my employer would hear the alarm bells..