Có thể hữu ích khi bạn sử dụng phương pháp kết hợp để tải trang web.
def groupfinder(userid, request):
user = request.db.query(User).filter_by(id=userid).first()
if user is not None:
# somehow get the list of sites they are members
sites = user.allowed_sites
return ['site:%d' % s.id for s in sites]
class SiteFactory(object):
def __init__(self, request):
self.request = request
def __getitem__(self, key):
site = self.request.db.query(Site).filter_by(id=key).first()
if site is None:
raise KeyError
site.__parent__ = self
site.__name__ = key
site.__acl__ = [
(Allow, 'site:%d' % site.id, 'view'),
]
return site
Chúng tôi sẽ sử dụng để lập bản đồ groupfinder người dùng hiệu trưởng. Chúng tôi đã chọn ở đây để chỉ lập bản đồ cho các trang web mà họ có tư cách thành viên bên trong. Quá trình truyền tải đơn giản của chúng tôi chỉ yêu cầu đối tượng gốc. Nó cập nhật các site
được nạp với một __acl__
sử dụng cùng một hiệu trưởng mà groupfinder
được thiết lập để tạo.
Bạn sẽ cần phải thiết lập các mẫu request.db
được đưa ra trong Sách hướng dẫn kim tự tháp.
def site_pregenerator(request, elements, kw):
# request.route_url(route_name, *elements, **kw)
from pyramid.traversal import find_interface
# we use find_interface in case we improve our hybrid traversal process
# to take us deeper into the hierarchy, where Site might be context.__parent__
site = find_interface(request.context, Site)
if site is not None:
kw['site_id'] = site.id
return elements, kw
Trình phát trước có thể tìm thấy site_id
và tự động thêm URL đó vào URL cho bạn.
def add_site_route(config, name, pattern, **kw):
kw['traverse'] = '/{site_id}'
kw['factory'] = SiteFactory
kw['pregenerator'] = site_pregenerator
if pattern.startswith('/'):
pattern = pattern[1:]
config.add_route(name, '/site/{site_id}/' + pattern, **kw)
def main(global_conf, **settings):
config = Configurator(settings=settings)
authn_policy = AuthTktAuthenticationPolicy('seekrit', callback=groupfinder)
config.set_authentication_policy(authn_policy)
config.set_authorization_policy(ACLAuthorizationPolicy())
config.add_directive(add_site_route, 'add_site_route')
config.include(site_routes)
config.scan()
return config.make_wsgi_app()
def site_routes(config):
config.add_site_route('site_users', '/user')
config.add_site_route('site_items', '/items')
Chúng tôi thiết lập ứng dụng của mình tại đây. Chúng tôi cũng đã chuyển các tuyến đường thành một hàm có thể bao gồm, cho phép chúng tôi dễ dàng kiểm tra các tuyến đường hơn.
@view_config(route_name='site_users', permission='view')
def users_view(request):
site = request.context
Quan điểm của chúng tôi sau đó được đơn giản hóa. Chúng chỉ được gọi nếu người dùng có quyền truy cập trang web và đối tượng trang web đã được tải cho chúng tôi.
lai Traversal
Một tùy chỉnh chỉ thị add_site_route
được thêm vào để tăng cường đối tượng config
của bạn với một wrapper xung quanh add_route
mà sẽ tự động thêm hỗ trợ traversal vào tuyến đường. Khi tuyến đường đó phù hợp, nó sẽ lấy trình giữ chỗ {site_id}
từ mẫu tuyến đường và sử dụng làm đường đi ngang của bạn (/{site_id}
là đường dẫn mà chúng tôi xác định dựa trên cách cây có cấu trúc của chúng tôi được cấu trúc).
Sự cố xảy ra trên đường dẫn /{site_id}
nơi bước đầu tiên tìm gốc của cây (/
). Tuyến đường được thiết lập để thực hiện traversal bằng cách sử dụng SiteFactory
làm gốc của đường dẫn truyền tải.Lớp này được khởi tạo là gốc, và __getitem__
được gọi với khóa là phân đoạn tiếp theo trong đường dẫn ({site_id}
). Sau đó chúng tôi tìm thấy đối tượng trang web khớp với khóa đó và tải nó nếu có thể. Đối tượng trang web sau đó được cập nhật với __parent__
và __name__
để cho phép find_interface
hoạt động. Nó cũng được tăng cường với một số __acl__
cung cấp các quyền được đề cập sau.
Pregenerator
Mỗi tuyến đường được cập nhật với một pregenerator mà cố gắng để tìm ra thể hiện của Site
trong hệ thống phân cấp traversal cho một yêu cầu. Điều này có thể thất bại nếu yêu cầu hiện tại không giải quyết được với URL dựa trên trang web. Trình tạo tiền tố sau đó cập nhật các từ khóa được gửi đến route_url
với id trang web.
Xác thực
Ví dụ cho thấy cách bạn có thể có một chính sách xác thực mà bản đồ người dùng vào các hiệu trưởng chỉ ra rằng người dùng này nằm ở cùng "site:" nhóm. Trang web (request.context
) sau đó được cập nhật để có ACL nói rằng nếu một người trong nhóm "site: 1" phải có quyền "xem". Sau đó, users_view
được cập nhật để yêu cầu quyền "xem". Điều này sẽ tăng một ngoại lệ HTTPForbidden
nếu người dùng bị từ chối truy cập vào chế độ xem. Bạn có thể viết một ngoại lệ xem để điều kiện dịch này thành một 404 nếu bạn muốn.
Mục đích của câu trả lời của tôi là chỉ cho thấy cách tiếp cận lai có thể làm cho số lượt xem của bạn đẹp hơn một chút bằng cách xử lý các phần phổ biến của URL trong nền. HTH.
Vì sự rò rỉ của tôi về kiến thức tra cứu của Kim tự tháp, tôi không thể hiểu rõ ví dụ của bạn nhưng tôi sẽ đọc tài liệu và cố gắng hiểu nó ... :-) BTW: Giải pháp của bạn có thể loại bỏ tham số 'site_id' khi tôi gọi yêu cầu .route_path? –
Bạn có thể loại bỏ 'site_id' bằng cách thêm một bộ phát trước cho các tuyến tự động điền vào site_id khi một tuyến được tạo ra. Nó không rõ ràng, đó là lý do tại sao tôi đăng nó để kích thích sự thèm ăn của bạn. Nhưng quan điểm của bạn có thể trở nên khá đơn giản với một số cấu hình khai báo lên phía trước. –
Tôi vẫn còn trong một mớ hỗn độn ..... Bạn có nhớ cập nhật ví dụ của mình với bộ phát trước mà bạn đã đề cập không? Cảm ơn! Nhân tiện, nếu tôi muốn thêm các tuyến khác nhau cho Site.type khác nhau, tôi phải làm gì? Ví dụ: nếu site1.type là 'hộ chiếu' và site1.id là 1, site2.type là 'www' và site2.id là 2 thì/site/1/người dùng phải được ánh xạ tới chế độ xem, nhưng/site/2/người dùng nên tăng lỗi 404. –