Ok, so here is a basic guide to optimizing views (and other long queries) in PostgreSQL.
The first thing is to understand that the more information the planner has, the better. Calls to functions are sometimes unavoidable but you have to understand that they are usually planner-opaque, which means, effectively, that the planner cannot fold in the logic into the main query, and has to run the query separately. So removing functions is a good first step (unless your view merely wraps a function, in which case there is no benefit to doing this).
The second thing to understand is that views encapsulate data logic, and while this may seem like a good thing, it has many, many pitfalls. SQL programming is just about the opposite of good object-oriented design in this regard, in part because SQL is declarative and in part because it is rigorously organized (making debugging of a much longer statement easier than a comparably long function in, say, Python). So one thing to do is to remove joins against views in other views.
Imagine, for example, if I have a view with, say, joins (which is not excessive, really). But then I run a query on the view with a self-join. Now I have gone from 9 joins to 81 and the problem is not evident from looking at the query that caused the problem (but boy, look at the query plan!).
In general your best views are going to be one of three kinds:
Simple function wrappers. For example:
CREATE VIEW current_stock_list AS select * from parts_stock_list(now());
Simple subsets of other tables or views (but not of views wrapping functions), for example:
CREATE VIEW warehouse_current_stock AS select * onhand_stock WHERE warehouse = 1;
Large, complex queries hitting underlying tables. 100 line queries would be preferable to 10 line queries if you avoid joining against views and functions in the process.
Hope this helps.