1. Access control - you can create new SQL accounts and only give them access to select from specified views
2. Encapsulation and implementation hiding - the underlying table structure can change as long as the views exposed doesn't change.
At least that's all I know. I'm sure people will add or correct when they read this.
- ability to do transformations uniformly e.g. if you want to represent a value in a certain way uniformly instead of having to do that in multiple places
- ability to get generated values (like 'create_ts() - now()' to get the age of the record) directly from the database instead of computing it repetitively
- move the join mechanisms on the database side to do those efficiently instead of the ORM having to do it (sometimes suboptimally); also helps with joins that are repetitive
- ability to apply certain "default" filters e.g. if you are always fetching with predicate 'active = true', then you can include that in the view
So, I wrapped common queries in views.
(None of this should be taken as advice for how to approach such a problem.)