1

我的看法如下:

@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) 调用中设置正确的上下文?

4

1 回答 1

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'

或者您可以加载真实对象并传入真实上下文。

于 2012-10-22T18:05:36.730 回答