Archive for the ‘Pyramid’ Category

New Relic and Pyramid

Tuesday, December 20th, 2011

While developing an application we decided to try New Relic, this is how we implemented their agent into pyramid.

import newrelic.agent
newrelic.agent.initialize('path/to/newrelic.ini', 'development')

application = config.make_wsgi_app()
return newrelic.agent.wsgi_application()(application)

Pyramid top level route issue

Wednesday, November 16th, 2011

I found this issue when I was developing an application that needed to use top level urls.

__init__.py

config.add_route('profile_view', '/:id')

views.py

@view_config(route_name='profile_view', renderer='profile/view.jinja2')
def view(request):
    profile = AuthUser.get_by_id(request.matchdict.get('id'))
    return {
        'profile': profile,
    }

On every page load I was getting the following error:

/var/www/pyramid/lib/python2.6/site-packages/SQLAlchemy-0.7.3-py2.6-linux-x86_64.egg/sqlalchemy/engine/default.py:330: Warning: Truncated incorrect DOUBLE value: 'favicon.ico'

I didn’t think too much about this error, I was running a testing version of Apex, where we changed the request.user object from a ContextFound subscriber to a Request Factory, so I figured it might have been a bug.

I started to debug Apex when I found the issue. The issue was that any request that was requesting any top level route would match my route, including the favicon.ico.

 

There are a few fixes to this problem.

You can add a regex condition to your route so it will only match on numerical values.

config.add_route('profile_view', '/{id:\d+}')

or

Add a route and a corresponding view that would match favicon.ico. The following code sample can be found at: http://docs.pylonsproject.org/projects/pyramid/dev/narr/assets.html#registering-a-view-callable-to-serve-a-static-asset

__init__.py

config.add_route('favicon', '/favicon.ico')

views.py

import os
from pyramid.response import Response   

@view_config(route_name='favicon')
def favicon(request):
    here = os.path.dirname(__file__)
    icon = open(os.path.join(here, 'static', 'images', 'favicon.ico'))
    return Response(content_type='image/x-icon', app_iter=icon)  

This code really shouldn’t be used in production, you should use something like Apache’s Alias method to alias the favicon.

Raja, an Apex Scaffold

Friday, November 4th, 2011

Raja is a pyramid scaffold that uses Routes, SQLAlchemy, Jinja, and Apex. The project layout might be a bit different than what you are used to, but I find this layout to be easy to use, and very organized. It comes prebuilt with an easily extendable 960 grid, template layout, filled with the apex imports for flash message support. The scaffold also comes with the minimal settings to run Apex. Check it out at Github

Apex’s AuthUser get_profile() problem

Wednesday, November 2nd, 2011

After reviewing apex’s code I noticed a flaw in its models. The AuthUser model has a function named get_profile, similar to Django’s auth get_profile, this function returns a user’s profile. This function was formally a classmethod, where the signed in user could only access their profile.

Sadly, this code couldn’t have been used on any social site currently in production. The code has been fixed to be an instancemethod function, and now any use of the AuthUser model can access the get_profile function. This fix was pushed in commit e94e63fcfe6495163517e164b9ac5f017e1fe7d4

Dealing with a user’s assets.

Tuesday, November 1st, 2011

With everyone building social sites I find it funny that no python framework seems handle user profiles very well.

Normally the code would written as followed:

__init__.py

config.add_route('profile_view', '/:id')
config.add_route('profile_photos', '/:id/photos')

views/profile.py

@view_config(route_name='profile_view', renderer='profile/view.jinja2')
def view(request):
    profile = AuthUser.get_by_id(request.matchdict.get('id'))
    return {
        'profile': profile,
    }

@view_config(route_name='profile_photos', renderer='profile/photos.jinja2')
def photos(request):
    profile = AuthUser.get_by_id(request.matchdict.get('id'))
    return {
        'profile': profile,
    }

Now this code isn’t very DRY, so this is where pyramid_handlers comes in handy.

Same code, using pyramid_handlers.

__init__.py

config.add_handler('profile_view', '/:id', handler='project.views.profile.Profile', action='view')
config.add_handler('profile_photos', '/:id/photos', handler='project.views.profile.Profile', action='photos')

Adding multiple add_handler isn’t very DRY either, so condense the code more.

__init__.py

config.add_handler('profile', '/:id/:action', handler='project.views.profile.Profile')

views/profile.py

class Profile(object):
    def __init__(self, request):
        self.request = request
        self.extra = {}
        self.extra['profile'] = AuthUser.get_by_id(request.matchdict.get('id'))
    
    @action(renderer='profile/view.jinja2')
    def view(self):
        return dict({}, **self.extra)

    @action(renderer='profile/photos.jinja2')
    def photos(self):
        return dict({}, **self.extra)

In response to Wayne’s comment:

This way does use more add_route calls, but it also removes a dependency.

__init__.py

config.add_route('profile_view', '/:id')
config.add_route('profile_photos', '/:id/photos')

views/profile.py

class Profile(object):
    def __init__(self, request):
        self.request = request
        self.extra = {}
        self.extra['user'] = AuthUser.get_by_id(request.matchdict.get('id'))
        
    @view_config(route_name='profile_view', renderer='profile/view.jinja2')
    def view(self):
        return dict({}, **self.extra)        

    @view_config(route_name='profile_photos', renderer='profile/photos.jinja2')
    def photos(self):
        return dict({}, **self.extra)