Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error with class based views #207

Closed
chiganov opened this issue Apr 30, 2018 · 9 comments
Closed

Error with class based views #207

chiganov opened this issue Apr 30, 2018 · 9 comments

Comments

@chiganov
Copy link

Hi

I try use debugtoolbar like this:

import asyncio
import jinja2
import aiohttp_debugtoolbar
import aiohttp_jinja2

from aiohttp import web


class IndexView(web.View):
    @aiohttp_jinja2.template('index.html')
    async def get(self):
        return {'title': 'example aiohttp_debugtoolbar!',
                'text': 'Hello aiohttp_debugtoolbar!',
                'app': self.request.app}


async def exception_handler(request):
    raise NotImplementedError


async def init(loop):
    # add aiohttp_debugtoolbar middleware to you application
    app = web.Application(loop=loop)
    # install aiohttp_debugtoolbar
    aiohttp_debugtoolbar.setup(app)

    template = """
    <html>
        <head>
            <title>{{ title }}</title>
        </head>
        <body>
            <h1>{{ text }}</h1>
            <p>
              <a href="{{ app.router['exc_example'].url_for() }}">
              Exception example</a>
            </p>
        </body>
    </html>
    """
    # install jinja2 templates
    loader = jinja2.DictLoader({'index.html': template})
    aiohttp_jinja2.setup(app, loader=loader)

    # init routes for index page, and page with error
    app.router.add_view('/', IndexView, name='index')
    app.router.add_route('GET', '/exc', exception_handler,
                         name='exc_example')
    return app


loop = asyncio.get_event_loop()
app = loop.run_until_complete(init(loop))
web.run_app(app, host='127.0.0.1', port=9000)

I get an error in debugtoolbar-page:

builtins.TypeError
TypeError: 'IndexView' object is not iterable
Traceback (most recent call last)
File "/home/ch/code/embryo/web/venv/lib/python3.6/site-packages/aiohttp_debugtoolbar/utils.py", line 168, in __call__
_y = next(_i)
File "/home/ch/code/embryo/web/venv/lib/python3.6/site-packages/aiohttp_debugtoolbar/panels/performance.py", line 58, in resource_timer_handler
result = yield from handler(request)
TypeError: 'IndexView' object is not iterable
TypeError: 'IndexView' object is not iterable

If I use function view style - everything works correctly.

@asvetlov
Copy link
Member

asvetlov commented May 8, 2018

Sorry for the late reply.
If you want to fix utils.py -- you are welcome.

@chiganov
Copy link
Author

chiganov commented May 8, 2018

Honestly, I'm studying the async/await syntax for the example aiohttp and my experience with asynchronous python programming is extremely small.

Nevertheless, I will try to help something.

At this point, I just changed the code in aiohttp.web_urldispatcher.py:

class View(AbstractView):

    async def _iter(self):
        if self.request.method not in hdrs.METH_ALL:
            self._raise_allowed_methods()
        method = getattr(self, self.request.method.lower(), None)
        if method is None:
            self._raise_allowed_methods()
        resp = await method()
        return resp

    def __await__(self):
        return self._iter().__await__()

    def __iter__(self):
        return self._iter().__await__()

    def _raise_allowed_methods(self):
        allowed_methods = {
            m for m in hdrs.METH_ALL if hasattr(self, m.lower())}
        raise HTTPMethodNotAllowed(self.request.method, allowed_methods)

As you can see I added __iter__() and its work. Perhaps we should place the call code _i._iter().__await__() in the class ContextSwitcher.

I'm not sure that this is the right solution to the problem.

@asvetlov
Copy link
Member

asvetlov commented May 9, 2018

@jettify have you time to take a look?

@jettify
Copy link
Member

jettify commented May 9, 2018 via email

@zhenhua32
Copy link

zhenhua32 commented May 24, 2018

same question, fix please

@Dalas
Copy link

Dalas commented Sep 28, 2018

same issue

@asvetlov
Copy link
Member

Do somebody want to make a pull request with the fix?

@wenmaai
Copy link

wenmaai commented Dec 17, 2018

this is the right solution to the problem:

# -*- coding: utf-8 -*-
import aiohttp_jinja2
from aiohttp import web


class CommonView(web.View):
    # 使用jinja2渲染html模板
    async def render(self, template_name, request, params):
        response = aiohttp_jinja2.render_template(
            template_name,
            request,
            params
        )
        return response

    def __iter__(self):
        return self._iter().__await__()

class SettingsView(CommonView):
    # GET请求
    async def get(self):
        response = await self.render(
            'settings.html',
            self.request,
            {
                'title': '系统设置'
            }
        )
        return response

@TheLazzziest TheLazzziest mentioned this issue Jan 19, 2020
3 tasks
@asvetlov
Copy link
Member

Fixed by 0.6.0 release

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants