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 に答える