私は次のような見解を持っています。
@view_config(name="clone-site", context=ctx.Site)
def clone_site(context, request):
"""Cloning the current Site.
"""
doc = context.__parent__.get_conn(app=context.appname).SiteDocument.one({'title':context.slug})
doc1 = context.__parent__.get_conn(app=context.appname).SiteDocument()
doc1['title'] = doc['title']+ '1'
doc1['slug'] = str(doc['slug'] + '1')
doc1.save()
for post in context.pages_data().find({'parent':context.__name__}):
page = ctx.Page(parent=context)
page1 = page.pages_data().PageDocument()
page1['parent'] = page.__parent__.__name__=str(doc1['title'])
page1['title'] = page.title=post['title']
page1['slug'] = page.__name__=page.slug=str(post['slug'])
page1['source'] = page.source= str(post['source'])
page1['data'] = post['data']
page1.save()
return HTTPFound(location=request.resource_url(context))
上記のビューのテスト ケースを作成しました。
def test_clone_site(self):
from piano.views.sites import clone_site
from piano.resources import contexts as ctx
from piano.lib import base as b
request = testing.DummyRequest(path='/sample/dhara')
context = testing.DummyResource()
response = clone_site(context, request)
self.assertEqual(response.location, 'http://localhost:8080/sample/dhara')
私のリソースツリーは次のとおりです。
class Root(b.ContextBase):
"""The root segment is the entry-point into the context tree. From the
root it will try to find an application, then the site, then any pages. The
only exception are services (/services) which can only be accessed from the
the root.
"""
__acl__ = [ (Allow, Everyone, 'view'),
(Allow, 'group:editors', 'edit') ]
def __init__(self, request):
self.request = request
def __getitem__(self, key):
# If /services return the service context
if key == c.SRVC_NAME:
return Service(key=key, parent=self)
#Try and return an app context otherwise
try:
return self.app(key=key, parent=self)
except:
raise KeyError(key)
class Service(b.ContextBase):
pass
@implementer(i.IApp)
class App(b.ContextBase):
def __getitem__(self, key):
try:
return Site.find(key=key, parent=self)
except:
raise KeyError(key)
def get_sites(self):
"""Returns a list of sites under the application.
"""
#@cache_region('hourly', 'site.list')
def _find_sites(a):
docs = self.get_conn(a).SiteDocument.find({}, {'title':1, 'slug':1})
return list(SiteItem(s['title'], '/'.join([a, s['slug']])) for s in docs)
#Get the list of available sites
site_list = _find_sites(self.appname)
return site_list
class Version(b.ContextBase):
def __getitem__(self, key):
try:
return self.finder(key, self.__parent__, versioned=True)
except:
raise KeyError(key)
def compare(self, source, target):
"""Compares two versions and returns the changes.
"""
doc_source = self.finder(source, self.__parent__, versioned=True)
doc_target = self.finder(target, self.__parent__, versioned=True)
return diff(
doc_source.data,
doc_target.data)
def rollback(self, source, target):
pass
class Page(b.ContextBase):
def __getitem__(self, key):
try:
if key == c.V:
#Return a versioned instance of the page. It finds the
#artifact by assigning its 'finder' function to the context.
return Version(key=key, parent=self, finder=self.find)
#Return the head page
return Page.find(key=key, parent=self)
except:
raise KeyError(key)
@classmethod
def find(cls, key, parent, versioned=False):
"""Finds a page by its parent and slug or version.
"""
#@cache_region('hourly', 'page.find')
def _find_page(k, p, s, a, v):
if v:
return parent.history_data().one({'pageid': parent.id, 'version':int(k)})
return parent.pages_data().one({'parent': p, 'slug':k})
#Find the page
doc = _find_page(key,
parent.__name__,
parent.sitename,
parent.appname,
versioned)
return cls(
key=key,
parent=parent,
id=doc['_id'],
title=doc['title'],
data=doc['data'],
slug=doc['slug'],
origin=doc['parent'],
views=doc['views'],
source=str(doc['source']),
date_created=doc['created'])
def get_history(self):
"""Finds the history for the page.
"""
docs = self.history_data().find({'pageid': self.id})
return list((v['version'], v['archived']) for v in docs)
def create(self, data):
"""Creates a new page and associates it to a parent.
"""
doc = self.pages_data().PageDocument()
doc['title'] = self.title = data['page']['title']
doc['slug'] = self.slug = self.__name__ = str(h.urlify(self.title))
doc['source'] = self.source = str(data['page']['source'])
doc['parent'] = str(self.__parent__.__name__)
#Try to import custom models and get doc
try:
#Explicitly look for a 'models' module with a 'PageModel' class
mod = __import__('.'.join([self.source, c.MODEL_PATH]), fromlist=[self.source])
pdoc = getattr(mod, c.MODEL_NAME)
except ImportError:
logger.warn("Cannot import '%s.models' module" % self.source)
except AttributeError:
logger.warn("Cannot load '%s.models.PageModel' class" % self.source)
else:
#Embed a new document
doc['data'] = pdoc()
doc.save()
return self
def update(self, data, archive=True):
"""Update myself with data (and copy to the archives collection)
"""
doc = self.pages_data().PageDocument.get_from_id(self.id)
doc['title'] = self.title = data['page']['title']
doc['slug'] = self.slug = self.__name__ = str(h.urlify(data['page']['slug']))
doc['data'] = self.data = data['data']
doc['version'] = doc['version'] + 1
doc.save(validate=False)
#Create archived version?
if archive:
ver = deepcopy(doc)
ver['pageid'] = doc['_id']
ver['archived'] = h.now()
del(ver['_id'])
self.history_data().insert(ver, validate=False)
return self
@implementer(i.ISite)
class Site(Page):
def __getitem__(self, key):
try:
return Page.find(key, self)
except:
raise KeyError(key)
@classmethod
def find(cls, key, parent):
"""Returns a single site by its slug.
"""
@cache_region('hourly', 'site.find')
def _find_site(k, a):
return parent.get_conn(app=a).SiteDocument.one({'slug':k})
#Find the site
doc = _find_site(key, parent.__name__)
return cls(
key=key,
parent=parent,
id=doc['_id'],
title=doc['title'],
slug=doc['slug'],
views=doc['views'],
date_created=doc['created'])
def save(self, data, include_default=False):
"""Saves the primary site details and creates a new collection to house
the pages in. It also creates a default (Home) page if needed.
"""
doc = self.get_conn(app=self.appname).SiteDocument()
doc['title'] = self.title = data['site']['title']
doc['slug'] = self.slug = self.__name__ = str(h.urlify(self.title))
doc.save()
#Create default (home) page?
if include_default:
page = Page(parent=self)
page.create(dict(page=dict(title=u'Home', source='sample.home')))
return self
def delete(self):
"""Deletes the site and its associated collection.
"""
db = self.get_conn(app=self.appname)
db.SiteDocument.get_from_id(self.id).delete()
db.drop_collection(self.__name__)
次のエラーが発生しています。
ERROR: test_clone_site (piano.tests.MapperTests)
Traceback (most recent call last):
File "D:\Auto\kjq-piano-6830d29\src\piano\tests\__init__.py", line 70, in test_clone_site
response = clone_site(context, request)
File "D:\Auto\kjq-piano-6830d29\src\piano\views\sites.py", line 62, in clone_site
doc=context.__parent__.get_conn(app=context.appname).SiteDocument.one({'title':context.slug})
AttributeError: 'NoneType' object has no attribute 'get_conn'
URL の戻り値が適切なコンテキストで正しいかどうかを確認したい。適切なコンテキストを設定できません。テスト ケースの clone_site(context, request) 呼び出しで正しいコンテキストを設定するにはどうすればよいですか?