我的观点如下:
@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)调用中设置正确的上下文?
答案 0 :(得分:0)
现在,您的测试用例使用testing.DummyResource()
作为上下文,其中包含__parent__ = None
,这就是您收到错误的原因。
要解决此问题,您需要使上下文看起来像您的视图所期望的那样。你可以通过附加属性来实现这一点(你实际上是在嘲笑上下文):
parent = testing.DummyResource()
parent.get_conn = # some function to get a connection
context.__parent__ = parent
context.app_name = 'some app name'
或者您可以加载真实对象并传入真实的上下文。