今回は、ログインしないと表示できないページにしてみます。
まず、データベースは使わないで、ソースの中に ID と password を持つようにします。
- myproject/__init__.py の修正
インポート部分にいくつか追加します。
#!/usr/bin/env python # coding: UTF-8 from pyramid.config import Configurator from pyramid_jinja2 import renderer_factory from sqlalchemy import engine_from_config from pyramid.session import UnencryptedCookieSessionFactoryConfig from pyramid.authentication import AuthTktAuthenticationPolicy from pyramid.authorization import ACLAuthorizationPolicy from myproject.security import groupfinder from myproject.models import ( initialize_sql, DBSession, Base, )
- myproject/__init__.py の修正
UnencryptedCookieSessionFactoryConfig をインポートの次に追加します。
'something_so_secret_strings' はそれなりの文字列にしておいてください。
my_session_factory = UnencryptedCookieSessionFactoryConfig('something_so_secret_strings')
- myproject/__init__.py の修正
main() の修正
<修正前>
#SQLAlchemy engine config for main DB #Any setting that begins with 'sqlalchemy.' will be picked up db_engine = engine_from_config(settings,'sqlalchemy.') #Binding engine to the model initialize_sql(db_engine) config = Configurator(settings=settings) config.include('pyramid_jinja2') config.add_renderer(".html", "pyramid_jinja2.renderer_factory") #The views/routes are added here config.add_static_view('static', 'static') config.add_route('home', '/') config.add_route('next_page', '/next') config.scan() return config.make_wsgi_app()
<修正後>
'sosecret' はそれなりの文字列にしておいてください。
#SQLAlchemy engine config for main DB #Any setting that begins with 'sqlalchemy.' will be picked up db_engine = engine_from_config(settings, 'sqlalchemy.') #Binding engine to the model initialize_sql(db_engine)
authn_policy = AuthTktAuthenticationPolicy( 'sosecret', callback=groupfinder, hashalg='sha512') authz_policy = ACLAuthorizationPolicy() config = Configurator(settings=settings, root_factory='myproject.models.RootFactory', session_factory=my_session_factory)
config.include('pyramid_jinja2') config.add_renderer(".html", "pyramid_jinja2.renderer_factory")
config.set_authentication_policy(authn_policy) config.set_authorization_policy(authz_policy)
#The views/routes are added here config.add_static_view('static', 'static') config.add_route('home', '/') config.add_route('next_page', '/next')
config.add_route('login', '/login') config.add_route('logout', '/logout')
config.scan() return config.make_wsgi_app()
- pypwm/views.py の修正
<修正前>
#!/usr/bin/env python # coding: UTF-8 from pyramid.i18n import TranslationStringFactory from myproject.models import DBSession from pyramid.view import view_config _ = TranslationStringFactory('MyProject') @view_config(route_name='home', renderer='home.html') def home(request): page_name = 'home' return {'page_name':page_name, 'next_uri':'/next', 'next_name':'next_page'} @view_config(route_name='next_page', renderer='home.html') def next_page(request): page_name = 'next_page' return {'page_name':'page_name', 'next_uri':'/', 'next_name':'home'}
<修正後>ほとんど全面的に修正。
#!/usr/bin/env python # coding: UTF-8 from pyramid.i18n import TranslationStringFactory from myproject.models import DBSession from pyramid.httpexceptions import HTTPFound from pyramid.response import Response from pyramid.view import ( view_config, forbidden_view_config, ) from pyramid.security import ( remember, forget, authenticated_userid, ) from .security import USERS _ = TranslationStringFactory('MyProject') @view_config(route_name='home', renderer='home.html', permission='edit', request_method="GET") def home(request): page_name = 'home' return {'page_name':page_name, 'next_uri':'/next', 'next_name':'next_page'} @view_config(route_name='next_page', renderer='home.html', permission='edit', request_method="GET") def next_page(request): page_name = 'next_page' return {'page_name':'page_name', 'next_uri':'/', 'next_name':'home'} @view_config(route_name='login', renderer='login.html') @forbidden_view_config(renderer='login.html') def login(request): login_url = request.route_url('login') referrer = request.url if referrer == login_url: referrer = '/' # never use the login form itself as came_from came_from = request.params.get('came_from', referrer) message = '' login = '' password = '' if 'form.submitted' in request.params: login = request.params['login'] password = request.params['password'] if USERS.get(login) == password: headers = remember(request, login) return HTTPFound(location = came_from, headers = headers) message = 'Failed login' return dict( message = message, url = request.application_url + '/login', came_from = came_from, login = login, password = password, ) @view_config(route_name='logout') def logout(request): headers = forget(request) return HTTPFound(location = request.route_url('home'), headers = headers)
- myproject/security.py を追加
#!/usr/bin/env python # coding: UTF-8 USERS = { 'editor':'editor', 'viewer':'viewer' } GROUPS = { 'editor':['group:editors'], 'viewer':['group:viewers'], } def groupfinder(userid, request): if userid in USERS: return GROUPS.get(userid, [])
- myproject/models.py の修正
<修正前>
from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker,scoped_session from zope.sqlalchemy import ZopeTransactionExtension DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension())) Base = declarative_base() #Define your models here #class MyModel(Base): # pass def initialize_sql(engine): DBSession.configure(bind=engine)
<修正後>
#!/usr/bin/env python # coding: UTF-8 from pyramid.security import ( Allow, Everyone, ) from sqlalchemy import ( Column, Integer, Text, ) from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import ( scoped_session, sessionmaker, ) from zope.sqlalchemy import ZopeTransactionExtension DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension())) Base = declarative_base() class MyModel(Base): __tablename__ = 'models' id = Column(Integer, primary_key=True) name = Column(Text, unique=True) value = Column(Integer) def __init__(self, name, value): self.name = name self.value = value class User(Base): """ The SQLAlchemy declarative model class for a User object. """ __tablename__ = 'users' id = Column(Integer, primary_key=True) name = Column(Text, unique=True) password = Column(Text) def __init__(self, name, password): self.name = name self.password = password class RootFactory(object): __acl__ = [ (Allow, Everyone, 'view'), (Allow, 'group:editors', 'edit') ] def __init__(self, request): pass def initialize_sql(engine): DBSession.configure(bind=engine)
- テンプレート home.html の修正
<br /><a href="{{ request.application_url }}/logout">Logout</a> を body 内に追加します。
<html> <head> <title>{{ page_name }}</title> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> <link rel="shortcut icon" href="{{request.application_url}}/static/favicon.ico" /> <link rel="stylesheet" href="{{request.application_url}}/static/pylons.css" type="text/css" media="screen" charset="utf-8" /> </head> <body> This page name is '{{ page_name }}'.<br /> <a href="{{ request.application_url }}{{ next_uri }}">{{ next_name }}</a>
<br /> <a href="{{ request.application_url }}/logout">Logout</a> </body> </html>
- テンプレートの追加
myproject/templates/login.html を追加します。
<!DOCTYPE html> <html> <head> <title>Login</title> <meta charset="utf-8"> <link rel="stylesheet" href="{{request.application_url}}/static/pylons.css" type="text/css" media="screen" charset="utf-8" /> </head> <body> <form action="{{ url }}" method="post" id="id_login_form"> <input type="text" name="login" value="{{ login }}" placeholder="login name" autofocus required/><br/> <input type="password" name="password" value="{{ password }}" placeholder="password" required /><br/> <input type="hidden" name="came_from" value="{{ came_from }}" /> <input type="submit" name="form.submitted" value="Log In" /> </form> </body> </html>
- おしまい
ログイン前に localhost:6543/next を表示しようとしても、ログインフォームが表示されます。
localhost:6543/next からログインフォームでログインすると、ちゃんと localhost:6543/next のページになります。
どこかのサイトを参考にしたのですが、その URL はわからなくなってしまいました。
次回は、ひとまず sqlite にしてみます。それから mysql ですね。
0 件のコメント:
コメントを投稿