We're approaching a substantial UI refactor with our Flask application. One goal is to keep the existing UI functional while the new interface is being developed. We're already using blueprints. Since both UIs have feature parity and share common business logic, this work will be contained within an existing "web" blueprint rather than creating a new blueprint for the updated UI. I'm thinking we might try to do something where an optional, leading version ID on the URL path would point us to the selected UI for the requested resource. For example: .../v0/widgets (old widgets UI) .../v1/widgets (new widgets UI) .../widgets (old widgets UI) You can imagine that <path:version> is an optional element for all routes and the preferred version is a configuration setting. For the most part, the view functions will stay the same. But there will be separate sets of template + static files. Therefore, render_template would modify the template name based on the current route. For example, template targets for the above routes might be: ...web/templates/v0/widgets.html (uses .../web/static/v0/ resources) ...web/templates/v1/widgets.html (uses .../web/static/v1/ resources) Since my suggested change results in a major shake-up of the codebase, I wanted to reach out for a sanity check. Does this approach make sense? Or should I be looking at this from a different angle? Such as: - use blueprints (differently) - think about using Dispatcher middleware - lazy views? - etc. I've got to think the subject of "UI refactor" is (or will be) a fairly common scenario for the Flask community. Maybe we can help each other develop some best practice here. Thanks, Jonathan.
We tried something like this ( urls with /v1/etc...) for a django app not too long ago, and for us it caused no end of trouble, as there turned out to be many more places than we suspected where we had to pass along the current version setting. We ended up moving very quickly to the new UI, so then we had all this dead weight of the versioning code cluttering things up for no benefit. On Mon, Oct 24, 2011 at 11:41 AM, Jonathan Zempel <jzempel@gmail.com> wrote: > We're approaching a substantial UI refactor with our Flask application. One > goal is to keep the existing UI functional while the new interface is being > developed. We're already using blueprints. Since both UIs have feature > parity and share common business logic, this work will be contained within > an existing "web" blueprint rather than creating a new blueprint for the > updated UI. > > I'm thinking we might try to do something where an optional, leading > version ID on the URL path would point us to the selected UI for the > requested resource. For example: > > .../v0/widgets (old widgets UI) > .../v1/widgets (new widgets UI) > .../widgets (old widgets UI) > > You can imagine that <path:version> is an optional element for all routes > and the preferred version is a configuration setting. For the most part, the > view functions will stay the same. But there will be separate sets of > template + static files. Therefore, render_template would modify the > template name based on the current route. For example, template targets for > the above routes might be: > > ...web/templates/v0/widgets.html (uses .../web/static/v0/ resources) > ...web/templates/v1/widgets.html (uses .../web/static/v1/ resources) > > Since my suggested change results in a major shake-up of the codebase, I > wanted to reach out for a sanity check. Does this approach make sense? Or > should I be looking at this from a different angle? Such as: > > - use blueprints (differently) > - think about using Dispatcher middleware > - lazy views? > - etc. > > I've got to think the subject of "UI refactor" is (or will be) a fairly > common scenario for the Flask community. Maybe we can help each other > develop some best practice here. > > Thanks, > Jonathan. >
Many thanks for the responses! Charlie, I'm going to follow your sage advice. The deeper I get into my approach the more complex it feels. In the spirit of keeping things simple, we're just going to develop the UI in a new blueprint and trash the old blueprint when we're done. (Amirouche: I like the expansive thinking on repurposing django-waffle for Flask. I've had a similar idea of taking some of the django-lean concepts and doing a Flask-AB extension for split testing. At the moment I need to concentrate on the immediate UI refactor, so I won't be able to collab. with you on this project. But thanks for the offer.) Cheers, Jonathan. On Wed, Oct 26, 2011 at 4:58 AM, Charlie Evett <charlieevett@litl.com>wrote: > We tried something like this ( urls with /v1/etc...) for a django app not > too long ago, and for us it caused no end of trouble, as there turned out to > be many more places than we suspected where we had to pass along the current > version setting. We ended up moving very quickly to the new UI, so then we > had all this dead weight of the versioning code cluttering things up for no > benefit. > > > On Mon, Oct 24, 2011 at 11:41 AM, Jonathan Zempel <jzempel@gmail.com>wrote: > >> We're approaching a substantial UI refactor with our Flask application. >> One goal is to keep the existing UI functional while the new interface is >> being developed. We're already using blueprints. Since both UIs have feature >> parity and share common business logic, this work will be contained within >> an existing "web" blueprint rather than creating a new blueprint for the >> updated UI. >> >> I'm thinking we might try to do something where an optional, leading >> version ID on the URL path would point us to the selected UI for the >> requested resource. For example: >> >> .../v0/widgets (old widgets UI) >> .../v1/widgets (new widgets UI) >> .../widgets (old widgets UI) >> >> You can imagine that <path:version> is an optional element for all routes >> and the preferred version is a configuration setting. For the most part, the >> view functions will stay the same. But there will be separate sets of >> template + static files. Therefore, render_template would modify the >> template name based on the current route. For example, template targets for >> the above routes might be: >> >> ...web/templates/v0/widgets.html (uses .../web/static/v0/ resources) >> ...web/templates/v1/widgets.html (uses .../web/static/v1/ resources) >> >> Since my suggested change results in a major shake-up of the codebase, I >> wanted to reach out for a sanity check. Does this approach make sense? Or >> should I be looking at this from a different angle? Such as: >> >> - use blueprints (differently) >> - think about using Dispatcher middleware >> - lazy views? >> - etc. >> >> I've got to think the subject of "UI refactor" is (or will be) a fairly >> common scenario for the Flask community. Maybe we can help each other >> develop some best practice here. >> >> Thanks, >> Jonathan. >> > >
Hey flask-ers, Coming back at you on this one. Got any good ideas (or time to read my verbose email)? Whatever I'm coming up with is feeling a bit too creative :-/ On Mon, Oct 24, 2011 at 8:41 AM, Jonathan Zempel <jzempel@gmail.com> wrote: > We're approaching a substantial UI refactor with our Flask application. One > goal is to keep the existing UI functional while the new interface is being > developed. We're already using blueprints. Since both UIs have feature > parity and share common business logic, this work will be contained within > an existing "web" blueprint rather than creating a new blueprint for the > updated UI. > > I'm thinking we might try to do something where an optional, leading > version ID on the URL path would point us to the selected UI for the > requested resource. For example: > > .../v0/widgets (old widgets UI) > .../v1/widgets (new widgets UI) > .../widgets (old widgets UI) > > You can imagine that <path:version> is an optional element for all routes > and the preferred version is a configuration setting. For the most part, the > view functions will stay the same. But there will be separate sets of > template + static files. Therefore, render_template would modify the > template name based on the current route. For example, template targets for > the above routes might be: > > ...web/templates/v0/widgets.html (uses .../web/static/v0/ resources) > ...web/templates/v1/widgets.html (uses .../web/static/v1/ resources) > > Since my suggested change results in a major shake-up of the codebase, I > wanted to reach out for a sanity check. Does this approach make sense? Or > should I be looking at this from a different angle? Such as: > > - use blueprints (differently) > - think about using Dispatcher middleware > - lazy views? > - etc. > > I've got to think the subject of "UI refactor" is (or will be) a fairly > common scenario for the Flask community. Maybe we can help each other > develop some best practice here. > > Thanks, > Jonathan. >
You could create your own template loader, something like this: https://gist.github.com/1315752 and then you can add this template loader to you app: app.jinja_loader = VersionedTemplatesLoader(app) You then just move your templates into their own subdirectory: /templates/v0/ /templates/v1/ Now you should be able to use both template versions without modifying you render_template call or you templates. On Wed, Oct 26, 2011 at 5:26 AM, Jonathan Zempel <jzempel@gmail.com> wrote: > Hey flask-ers, > > Coming back at you on this one. Got any good ideas (or time to read my > verbose email)? Whatever I'm coming up with is feeling a bit too creative > :-/ > > > On Mon, Oct 24, 2011 at 8:41 AM, Jonathan Zempel <jzempel@gmail.com>wrote: > >> We're approaching a substantial UI refactor with our Flask application. >> One goal is to keep the existing UI functional while the new interface is >> being developed. We're already using blueprints. Since both UIs have feature >> parity and share common business logic, this work will be contained within >> an existing "web" blueprint rather than creating a new blueprint for the >> updated UI. >> >> I'm thinking we might try to do something where an optional, leading >> version ID on the URL path would point us to the selected UI for the >> requested resource. For example: >> >> .../v0/widgets (old widgets UI) >> .../v1/widgets (new widgets UI) >> .../widgets (old widgets UI) >> >> You can imagine that <path:version> is an optional element for all routes >> and the preferred version is a configuration setting. For the most part, the >> view functions will stay the same. But there will be separate sets of >> template + static files. Therefore, render_template would modify the >> template name based on the current route. For example, template targets for >> the above routes might be: >> >> ...web/templates/v0/widgets.html (uses .../web/static/v0/ resources) >> ...web/templates/v1/widgets.html (uses .../web/static/v1/ resources) >> >> Since my suggested change results in a major shake-up of the codebase, I >> wanted to reach out for a sanity check. Does this approach make sense? Or >> should I be looking at this from a different angle? Such as: >> >> - use blueprints (differently) >> - think about using Dispatcher middleware >> - lazy views? >> - etc. >> >> I've got to think the subject of "UI refactor" is (or will be) a fairly >> common scenario for the Flask community. Maybe we can help each other >> develop some best practice here. >> >> Thanks, >> Jonathan. >> > >
2011/10/26 Pitmairen <progrper@gmail.com> > You could create your own template loader, something like this: > https://gist.github.com/1315752 > > and then you can add this template loader to you app: > > app.jinja_loader = VersionedTemplatesLoader(app) > > You then just move your templates into their own subdirectory: > > /templates/v0/ > /templates/v1/ > > > Now you should be able to use both template versions without modifying you > render_template call or you templates. Nice trick. On Wed, Oct 26, 2011 at 5:26 AM, Jonathan Zempel <jzempel@gmail.com> wrote: > Hey flask-ers, > > Coming back at you on this one. Got any good ideas (or time to read my > verbose email)? Whatever I'm coming up with is feeling a bit too creative > :-/ > Your use case might be solved by the above trick. I was thinking about a feature flipper like django-waffle [1] but it's kind of a generalization of the above technique. Anyway, if you go the feature-flipper way don't hesitate to contact me maybe we could collaborate on it Amirouche [1] Django waffle doesn't have a versionned template loading system but it might be a good addition https://github.com/jsocol/django-waffle