Our application has URLs that allow people to add/edit/delete content
via a web browser. Time to add security to the application. Let's
protect our add/edit views to require a login (username of
editor and password of editor). We will allow the other views
to continue working without a password.

frompyramid.httpexceptionsimportHTTPFoundfrompyramid.securityimport(remember,forget,)frompyramid.viewimport(view_config,view_defaults,forbidden_view_config)from.securityimportUSERS@view_defaults(renderer='home.pt')classTutorialViews:def__init__(self,request):self.request=requestself.logged_in=request.authenticated_userid@view_config(route_name='home')defhome(self):return{'name':'Home View'}@view_config(route_name='hello',permission='edit')defhello(self):return{'name':'Hello View'}@view_config(route_name='login',renderer='login.pt')@forbidden_view_config(renderer='login.pt')deflogin(self):request=self.requestlogin_url=request.route_url('login')referrer=request.urlifreferrer==login_url:referrer='/'# never use login form itself as came_fromcame_from=request.params.get('came_from',referrer)message=''login=''password=''if'form.submitted'inrequest.params:login=request.params['login']password=request.params['password']ifUSERS.get(login)==password:headers=remember(request,login)returnHTTPFound(location=came_from,headers=headers)message='Failed login'returndict(name='Login',message=message,url=request.application_url+'/login',came_from=came_from,login=login,password=password,)@view_config(route_name='logout')deflogout(self):request=self.requestheaders=forget(request)url=request.route_url('home')returnHTTPFound(location=url,headers=headers)

Of course, this only applies on Root. Some other part of the site
(a.k.a. context) might have a different ACL.

If you are not logged in and visit /howdy, you need to get
shown the login screen. How does Pyramid know what is the login page to
use? We explicitly told Pyramid that the login view should be used
by decorating the view with @forbidden_view_config.