Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Official Guide on how to structure Flask application #2626

Closed
lepture opened this Issue Feb 10, 2018 · 28 comments

Comments

Projects
None yet
@lepture
Copy link
Member

lepture commented Feb 10, 2018

I've just learned that many people are learning "how to structure Flask application" with this post: https://www.digitalocean.com/community/tutorials/how-to-structure-large-flask-applications via lepture/authlib#8 (comment)

This guide however it really a bad example and many people new to Flask are learning from it. I'd like to create a guide on this topic in the official docs. Here is my thoughts:

  1. Use MVC pattern
  2. Use factory pattern
  3. Another simple example on other folder structure
app/
   __init__.py
   templates/
   models/
   controllers/  (or other names)

@lepture lepture self-assigned this Feb 10, 2018

@lepture lepture added the docs label Feb 10, 2018

@ThiefMaster

This comment has been minimized.

Copy link
Member

ThiefMaster commented Feb 10, 2018

Real MVC is very uncommon in webapps nowadays, even more so in Flask apps. So talking about MVC may confuse people. Especially since what's usually the controller is called a "view function" in Flask.

I'd rather point to some well-structured example applications than blessing one single way of doing it as the right way. Or maybe just point out some basics in a clearer way, e.g. how to properly use an app factory etc.

@lepture

This comment has been minimized.

Copy link
Member Author

lepture commented Feb 10, 2018

Actually I don’t call it controllers myself, that is why I left a message “or other names”.

The problem is that bad example has a better SEO. :(

For advanced developers, flexible is a good thing. But for new people, a fixed guide would be better. If you don’t give them, they will find them on Google which usually shows the bad ones.

@davidism

This comment has been minimized.

Copy link
Member

davidism commented Feb 10, 2018

I'm running into this while rewriting the tutorial. The users reading the tutorial are the ones most in need of seeing a well structured app with the factory and blueprints, but that adds a lot of up front explanation and boilerplate that looks confusing. It feels like I'm sacrificing the "quick and easy to get started" idea, which is one of Flask's selling points that brought in those new users.

@davidism

This comment has been minimized.

Copy link
Member

davidism commented Feb 10, 2018

That tutorial is definitely lacking in explanation and clarity in general. Specifically for layout, whether using a factory or "import last", most tutorials are missing the why: because it avoids circular imports and is more reusable.

For reference, I divide my app up by components, rather than grouping all models, views, etc. I find it easier to work with all realated objects in relatively small folders, especially once projects get very big.

project/
  flaskr/
    __init__.py  # contains factory and extensions
    auth/
      __init__.py  # contains blueprint
      models.py
      forms.py
      views.py
    blog/
      ...
    templates/
  setup.py
@ThiefMaster

This comment has been minimized.

Copy link
Member

ThiefMaster commented Feb 10, 2018

I would avoid putting lots of stuff into __init__.py in the tutorial. Especially things like the app factory don't really need to be there (could go into an app.py); same for instances of extension classes (one file per extension keeps things clean if you ever need more code related to some extension, e.g. custom sqlalchemy naming schemes).

I used to point people to https://github.com/GameSurge/web quite often when they were asking for suggestions how to structure their apps. The project in that repo is kind of unfinished but the structure works pretty well.

@nanomosfet

This comment has been minimized.

Copy link

nanomosfet commented Feb 10, 2018

I'm running into this while rewriting the tutorial. The users reading the tutorial are the ones most in need of seeing a well structured app with the factory and blueprints, but that adds a lot of up front explanation and boilerplate that looks confusing. It feels like I'm sacrificing the "quick and easy to get started" idea, which is one of Flask's selling points that brought in those new users.
@davidism

I think the quick start and a tutorial are two different things. The quick start is the minimal amount to start the app, i.e, writing a short app and running flask run. I think it makes sense for the tutorial to aim for people who want to learn how to structure their app correctly. In the tutorial case it makes sense to add more detail and isn't exactly a quick start. The 0.12 tutorial isn't really a quick start either.

@davidism

This comment has been minimized.

Copy link
Member

davidism commented Feb 10, 2018

@ThiefMaster Yeah, I'm keeping things out of init.

Another point of reference, the Mega Tutorial uses the "import last" pattern as well as putting stuff in init.

@ThiefMaster

This comment has been minimized.

Copy link
Member

ThiefMaster commented Feb 10, 2018

Regarding small/quick app and anything bigger it'd be a good idea to make it clear that single-file apps are fine for small things where you have a few routes and that's it. No need for blueprints etc. either. And that as soon as you want to do something bigger, you should start with a proper Python package, separate files, blueprints, etc.

@davidism

This comment has been minimized.

Copy link
Member

davidism commented Feb 10, 2018

I'm also rewriting the quickstart, but that's more of an overview of concepts and common API. You don't end up with an app at the end of it.

My current plan for the tutorial is to start minimal, a single file with no auth, validation, or templates, explain when that's useful, then move to a package.

@nanomosfet

This comment has been minimized.

Copy link

nanomosfet commented Feb 10, 2018

@davidism Would you at least end up with one route displaying "Hello World"?

@lepture

This comment has been minimized.

Copy link
Member Author

lepture commented Feb 10, 2018

Also mention here. There is a very popular repo "A simple Flask boilerplate app with SQLAlchemy, Redis, User Authentication, and more": https://github.com/hack4impact/flask-base

This one has so many stars while actually it has a very bad practice. Those things defined in the root __init__.py will cause a cyclic dependency sooner or later.

@davidism

This comment has been minimized.

Copy link
Member

davidism commented Feb 10, 2018

There are many low quality tutorials, I run into them constantly while answering on Stack Overflow. Boilerplate / cookiecutter / swagger projects are especially notorious because they leave the user with a bunch of mysterious code with little explanation or understanding.

The most we can realistically do is make our docs and examples as clear as possible. This will be an ongoing project, I'm only focusing on the a few docs for 1.0.

@davidism

This comment has been minimized.

Copy link
Member

davidism commented Feb 10, 2018

Not to say boilerplate / cookiecutter / swagger projects are bad, but the issue is that they're found by new users as a shortcut to learning, when they're really meant for experienced users who want to automate more.

@up1and

This comment has been minimized.

Copy link

up1and commented Feb 11, 2018

I learned Flask from this book, Flask Web Development Developing Web Applications with Python and the companion code flasky also put db in root __init__.py.

Thanks for the tips.

@insha

This comment has been minimized.

Copy link

insha commented Feb 12, 2018

When I first started to use Flask I came across a blog post on structuring the Flask app for bigger projects. This too put the db in the root __init__.py.

@RyanSquared

This comment has been minimized.

Copy link

RyanSquared commented Feb 22, 2018

This one has so many stars while actually it has a very bad practice. Those things defined in the root init.py will cause a cyclic dependency sooner or later.

Actually, I got into a pretty heated discussion with someone quite recently about this exact repository about how that's a bad example, because they refused to restructure the application, but had an issue with exactly that cyclic dependency issue.

I think a good solution is to, somewhere where the users first open up the Flask website, put a list of curated examples. That way, users can still follow the tutorial on the website as well as having access to some good examples.

@davidism

This comment has been minimized.

Copy link
Member

davidism commented Feb 23, 2018

@lepture I think this will be covered in the new tutorial. Can we close this for #2513?

@lepture lepture closed this Feb 27, 2018

@lepture

This comment has been minimized.

Copy link
Member Author

lepture commented Apr 21, 2018

FYI, I wrote a post to share my folder structures: https://lepture.com/en/2018/structure-of-a-flask-project

@TimothyBramlett

This comment has been minimized.

Copy link

TimothyBramlett commented Jun 13, 2018

@davidism I hate to give bad feedback but honestly I have been going through the tutorial and I find the Application factor to be incredibly confusing. It may be a great pattern later on when building Flask apps but it seems quite complex and you don't really go into a lot of reasoning as to WHY its needed.

I am new to Flask but not Python and dealing with import errors when trying to modify the tutorial codebase to suit my own purposes had me wanting to pull my hair out.

I think tutorials are best when they start simple and add things in layers. You could have started with the sub-optimal way to do things by statically declaring the Flask object and then added examples showing the factory pattern.

To be honest, the tutorial has kind of given be a bad taste for Flask, and I'm considering moving to Django. :(

Edit: Maybe adding more info about how the application factory works would help? One thing that confuses me after going through the tutorial is what is actually calling the factory? How does it get created and used?

@RyanSquared

This comment has been minimized.

Copy link

RyanSquared commented Jun 14, 2018

@TimothyBramlett the thing mostly calling the factories is your WSGI server, which I agree really needs to be explained more, as a lot of people are used to frameworks being an "all-in-one" webserver and web framework, which Flask isn't.

@neerajshukla1911

This comment has been minimized.

Copy link

neerajshukla1911 commented Jun 14, 2018

@lepture : Flask-Full is a boilerplate framework on top of flask for developing large applications using flask. It has in built support for shell commands, celery, websocket, eventlet, sqlalchemy, mongoengine, signals and rst docs. One can also have separate staging, production config.

@ThiefMaster

This comment has been minimized.

Copy link
Member

ThiefMaster commented Jun 14, 2018

"mongo" is where I stopped reading...

@wgwz

This comment has been minimized.

Copy link
Contributor

wgwz commented Jun 14, 2018

i have not run through the new tutorial yet so i can’t exactly comment in detail. but what i will say is understanding the application factory and why to use it, does carry overhead for people new to using flask. so it definitely should be explained well.

the tutorial previously did not use the application factory pattern and it did start from the ground up to introduce users to circular imports and discussed how the app factory pattern helps to avoid these.

if im not mistaken many people were using the tutorial with the idea that it was best practices. which meant that people were running into circular import errors quite frequently. and this is why the devs decided to start actually adding best practices to it; like the app factory and like the setup.py script.

also because this a closed issue, if there are outstanding issues with the tutorial lets open up new issues for that. @TimothyBramlett i’d encourage you to open up a new issue, if there’s not already one. it’s a very valid point

@lepture

This comment has been minimized.

Copy link
Member Author

lepture commented Jun 15, 2018

@neerajshukla1911 please don't initialize your extension in the root __init__.py, sooner or later you will face a cyclic dependencies problem. Check out why: https://lepture.com/en/2018/structure-of-a-flask-project

@sandys

This comment has been minimized.

Copy link

sandys commented Jul 12, 2018

I have a request - the tutorial describes a database (sqlite) backed application. Therefore, I am assuming that most people are interested in a tutorial that demonstrates a database backed application.

However, instead of using sqlite3 directly, I believe that the tutorial should be using flask-sqlalchemy.
Using flask-sqlalchemy is not more complex than using sqlite3 directly, however it will eliminate the next step of people searching for how to use sqlalchemy to connect to a non-sqlite database. In reality, people dont built sqlite backed application.. but instead using some kind of a relational db or mongo.

In fact, this is so important that the official tutorial has dedicated a section to showing how NOT to configure sqlalchemy (http://flask.pocoo.org/docs/1.0/patterns/appfactories/#factories-extensions). Stackoverflow is full of people asking very basic questions on how to setup sqlalchemy in the right way.

My proposal results in no increase in complexity of the tutorial - the user today has to install sqlite3 anyways. It just uses the most popular library (which most people will try to use unsuccessfully anyway).

@davidism

This comment has been minimized.

Copy link
Member

davidism commented Jul 12, 2018

The tutorial will not be using extensions. It is meant to teach the parts of Flask, not how to plug in extensions. Extensions have their own examples based off the tutorial, although they probably all need updating at this point.

Re: other sections in docs, the docs have a lot of things, and I can only get to so many. You've pointed to the patterns section, not the tutorial section. There are plenty of overlapping parts that are slightly out of sync now, if you'd like to improve those in the style of other sections I've edited, go for it.

@sandys

This comment has been minimized.

Copy link

sandys commented Jul 12, 2018

thank you for replying. I do think that it is already using an extension - sqlite3. I would not have suggested this, if the tutorial was one without any database implication.

If you look at it, there is already upfront complexity coming from teardown_appcontext (why do you need to close the database, etc). If you think about it, using flask-sqlalchemy will actually reduce the need to understand/worry about this (since it will attach teardowns inside the library itself).

With the happy consequence that, going forward, the learner continues to use this pattern with any other database they use. This is such a big issue that sqlalchemy clarifications are kind of present all over the documentation anyway.

Please do think about it. The reality is that your tutorial is good that it reflects real world usage (database). There is no harm down in reducing library complexity by using the most popular extension .. that people will end up using anyway!

@ThiefMaster

This comment has been minimized.

Copy link
Member

ThiefMaster commented Jul 12, 2018

sqlite3 is not a flask extension.

@pallets pallets locked as resolved and limited conversation to collaborators Jul 12, 2018

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
You can’t perform that action at this time.