Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flask project structure for grunt based workflow

I recently purchased an HTML/CSS/Js admin template based on the Bootstrap framework. It basically covered all my needs for an MVP and my plan was to customize it a bit and then plug my already developed back-end through flask.

I am quite inexperienced in this field, so I was quite impressed by the automatic workflow that was used by this admin template. The basic structure is the following one:

root/
├── dist/
│   └── html/
│       ├── assets/
│       └── all_pages.html
├── grunt/
│   └── tasks/
├── node_modules/
├── src/
│   ├── assets/
│   ├── html/
│   ├── js/
│   └── sass/
├── Gruntfile.js
└── package.json

Thanks to grunt tasks and npm management, handling assets is very easy, after an npm install you can handle everything with grunt.

The sass are compiled in a css style for production and all code gets minified and copied to the dist folder depending on the settings.

You can easily develop on the src path, and use the grunt task "server" to both watch for changes and directly display them before sending everything to production folder "dist".

My problems arise when I try to keep this behavior with a flask application interacting with it.

My flask application uses this structure:

root/
├── __init__.py
├── templates/
│   ├── layout.html
│   └── bp1/
│   │   ├── layout.html
│   │   └── other_pages.html
│   └── bp2/
│       ├── layout.html
│       └── other_pages.html
├── views/
│   ├── __init__.py
│   ├── bp1.py.py
│   └── bp2.py.py
├── static/
│   ├── css/
│   ├── js/
│   └── img/
├── Dockerfile
└── requirements.txt

Basically, there is no difference between development and production version, and the web-app gets deployed through its docker image.

My question here is, how on earth should I approach the merging of these two guys? How to have a flask project with src-dist separation and a workflow similar to the one I described above?

I would like to keep all the good features (I managed to notice with my skills) of the admin template and have something with:

  • src and dist folders separation...so that all sass items, unused/discarded js code and html pages are only in the development "src" folder and will not be used in production
  • grunt automation for compiling sass, cleaning lib directories, watching for changes, npmcopy (to install packages with npm and move only required files to production), notifications, minification, etc...
  • Docker image based deployment that is based only on the "dist-generated" resource and ignores the "src-development" stuff.
like image 820
Bertone Avatar asked Apr 05 '26 23:04

Bertone


1 Answers

Alright, I came up with a setup that works pretty neatly and that I think is worth sharing for anyone else stuck or doubtful when in a similar scenario.

Structure

root/
├── src/
│   ├── __init__.py
│   ├── models.py
│   ├── database.py
│   ├── static/
│   │   ├── css/
│   │   │   └── app.css
│   │   ├── js/
│   │   ├── img
│   │   └── lib
│   ├── templates/
│   │   ├── layout.html
│   │   ├── bp1/
│   │   │   ├── layout.html
│   │   │   └── other_pages.html
│   │   └── bp2/
│   │       ├── layout.html
│   │       └── other_pages.html
│   ├── views/
│   │   ├── __init__.py
│   │   ├── bp1.py
│   │   └── bp2.py
│   └── sass/
├── dist/
│   ├── __init__.py
│   ├── models.py
│   ├── database.py
│   ├── static/
│   │   ├── css/
│   │   │   └── app.css
│   │   ├── js/
│   │   ├── img
│   │   └── lib
│   ├── templates/
│   │   ├── layout.html
│   │   ├── bp1/
│   │   │   ├── layout.html
│   │   │   └── other_pages.html
│   │   └── bp2/
│   │       ├── layout.html
│   │       └── other_pages.html
│   └── views/
│       ├── __init__.py
│       ├── bp1.py
│       └── bp2.py
├── templates/
│   ├── layout.html
│   └── bp1/
│   │   ├── layout.html
│   │   └── other_pages.html
│   └── bp2/
│       ├── layout.html
│       └── other_pages.html
├── views/
│   ├── __init__.py
│   ├── bp1.py.py
│   └── bp2.py.py
├── static/
│   ├── css/
│   ├── js/
│   └── img/
├── instance/
│   └── flask.cfg
├── grunt/
│   └── tasks/
├── static/
├── node_modules/
├── venv/
├── Gruntfile.js
├── package.json
├── Dockerfile
├── .gitignore
└── requirements.txt

Workflow

  • packages are installed with npm and the package.json (node_modules gets generated).
  • a python virtualenv is configured using the 'requirements.txt' and linked to 'venv'.
  • a grunt tasks is called and uses npmcopy to move only the required files to src/static/lib that gets used by flasks' templates as: static/lib in order to keep src-dist compatibility.
  • a grunt task is able to compile sass parts and create 'app.css' within static/css.
  • several other grunt tasks do other useful things like minification.
  • grunt's default task performs concurrently a 'watch task' and launches flask run to let the development continue smoothly (more on this later).
  • grunt dist creates in the dist folder a production-ready flask project with all packages, styles and pages developed in the previous steps.

Grunt's flask task

This simple piece of code manages to launch a flask server locally to start development.

// Launch flask's server
grunt.registerTask('flask', 'Run flask server.', function() {
  var spawn = require('child_process').spawn;
  grunt.log.writeln('Starting Flask.');
  var PIPE = {
    stdio: 'inherit',
    env: {
      FLASK_APP: './src/__init__.py:create_app()',
      FLASK_ENV: 'development',
      LC_ALL: 'C.UTF-8',
      LANG: 'C.UTF-8'
    }
  };
  // more on venv later
  spawn('venv/bin/flask', ['run'], PIPE);
});

Flask setup for development

In order for the flask run command to work properly in development mode, the following are configured:

  • venv: symbolic link to the python virtualenv used for the project.
  • instance/flask.cfg: flask instance folder

Gitignore

Other than the whole 'dist' folder, these are excluded from VCS:

  • venv;
  • instance folder;
  • lib folder within the src one;
  • node_modules;

Conclusion

This setup is pretty handy and is quite easy to share. Local, easy, configurations let everything work neatly for development. Production code can be generated and then deployed/configured quickly depending on the strategies (k8s, server deployments, ...).

like image 172
Bertone Avatar answered Apr 08 '26 15:04

Bertone



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!