Lucas
Lucas

Reputation: 949

AttributeError: '<Class name>' object has no attribute 'request'

I defined a method for rendering pages:

def doRender(handler, tname='index.html',values = {}):
    temp = os.path.join(os.path.dirname(__file__),
                        'templates/'+tname)
    if not os.path.isfile(temp):
        return False

    newval = dict(values)
    newval['path'] = handler.request.path

    user = users.get_current_user()
    url = users.create_login_url(handler.request.uri)
    url_linktext = 'Login'

    if user:
        url = users.create_logout_url(handler.request.uri)
        url_linktext = 'Logout'

    newval['user'] = user
    newval['url'] = url
    newval['url_linktext'] = url_linktext

    outstr = template.render(temp, newval)
    handler.response.out.write(outstr)
    return True

Also, I have these classes:

GruposHandler

class GruposHandler(webapp.RequestHandler):    
    def get(self):
        self.obtenerPagina()

    def obtenerPagina(self, pOpcion = None, pMensajeInformacion = None):
        opcion = pOpcion if pOpcion is not None else self.request.get('opcion') 
        usuario = obtenerUsuario()
        rsGrupos = obtenerGruposAll()
        listaGruposCreadosPorUsuario = []
        #
        #

        for grupo in rsGrupos: 
            if grupo.creadoPorUsuario == usuario:
                listaGruposCreadosPorUsuario.append(grupo)

        blahh...

        if opcion == 'gruposMios':
            doRender(self, 'grupos_mios.html', {'listaGruposCreadosPorUsuario':listaGruposCreadosPorUsuario,
                                                'informacion':pMensajeInformacion})

NuevoGrupoHandler

class NuevoGrupoHandler(webapp.RequestHandler):
    def post(self):
        nombre = self.request.get('nombre')
        descripcion = self.request.get('descripcion')

        #comprobar que no exista un grupo con el mismo nombre
        obj = Grupo.get_by_key_name(nombre)
        if obj:
            doRender(self, 'nuevo_grupo.html', {'mensaje_descripcion':'Ya existe un grupo con ese nombre.'})
        else:
            grupo = model.Grupo(key_name = nombre, nombre=nombre, descripcion = descripcion);
            grupo.put()
            grupoHandler = GruposHandler()
            grupoHandler.obtenerPagina("gruposMios", 'Informacion: un nuevo grupo fue agregado.')

When webapp receive an HTTP GET request to the URL /nuevogrupo, it instantiates the NuevoGrupoHandler class and calls the instance's get method. So at this point, everything works as expected

def main():
    application = webapp.WSGIApplication([
                                          ('/nuevogrupo', NuevoGrupoHandler),
                                          etc...

but when I call method GruposHandler.obtenerPagina() from NuevoGrupoHandler.post(), when the method doRender() inside obtenerPagina() is reached, an exception is thrown at this line:

newval['path'] = handler.request.path

This is the stacktrace I'm getting:

AttributeError: 'GruposHandler' object has no attribute 'request'

So it seems that something is not properly setted when it is not called from the webapp.WSGIApplication instance. I'm not so sure.

Sorry I could not explain the problem better.

What should I do to avoid that exception.

Thanks in advance.

Upvotes: 2

Views: 2778

Answers (1)

tito
tito

Reputation: 13251

I don't know about google-app-engine, but the issue is from your side, not from the WSGIApplication.

In NuevoGrupoHandler.post method, you're instanciate a new GruposHandler(), that you use for rendering. And this instance doesn't have request attribute, that cause your exception.

My approach would be to copy the request attribute from your current instance to the new one:

grupoHandler = GruposHandler()
grupoHandler.request = self.request # <<< add this
grupoHandler.response = self.response # <<< and this
grupoHandler.obtenerPagina("gruposMios", 'Informacion: un nuevo grupo fue agregado.')

Then your new instance handler will have the same request as the current one, and the exception will be avoided.

Edit:

By the way, if you want to just use an external method like this, it would be better to create another baseclass that implement the doRender, and inherit from it for GruposHandler and NuevoGrupoHandler:

class RenderRequestHandler(webapp.RequestHandler):
    def obtenerPagina(self, ...):
        pass

    def do_render(self):
        pass

class GruposHandler(RenderRequestHandler):
    pass

class NuevoGrupoHandler(RenderRequestHandler):
    pass

And implement both method in the baseclass. :)

Upvotes: 4

Related Questions