Request Parameters

There are two provided utilities for accessing request parameters. The first is the request.param() method. You can use this method by including pyramid_duh in your app (which comes with some other things), or if you only want the param() method you can include pyramid_duh.params:

config.include('pyramid_duh')

Or in the config file:

pyramid.includes =
    pyramid_duh

Here is an example use case:

def register_user(request):
    username = request.param('username')
    password = request.param('password')
    birthdate = request.param('birthdate', type=date)
    metadata = request.param('metadata', {}, type=dict)
    # insert into database

Note that you can pass in default values and perform type conversion. This will handle both form-encoded data and application/json. If a required argument is missing, it will raise a 400. For greater detail, see the function docs at param().

Argify

Let’s make the above example sexier:

from pyramid_duh import argify

@argify(birthdate=date, metadata=dict)
def register_user(request, username, password, birthdate, metadata=None):
    # insert into database

Again, pretty intuitive. If any types are non-unicode, specify them in the @argify() decorator. Positional arguments are required; keyword arguments are optional. It even supports the value validation of request.param():

from pyramid_duh import argify

def is_natural_number(num):
    return isinstance(num, int) and num > 0

@argify(age=(int, is_natural_number))
def set_age(request, username, age):
    # Set user age

It also makes unit tests nicer:

def test_my_view(self):
    request = DummyRequest()
    ret = my_view(request, 'dsa', 'conspiracytheory', date(1989, 4, 1))

Note

If you’re only using @argify, you don’t need to include pyramid_duh.

Custom Parameter Types

You’re now using argument sugar and you’re loving it. But you’re hungry for more. You want to auto-convert to your own super-special Unicorn data type. Well who doesn’t?

Here are the POST parameters:

{
    username: "stevearc",
    pet: {
        "name": "Sparklelord",
        "sparkly": true,
        "cuddly": true
    }
}

And here is the code to parse that mess:

class Unicorn(object):
    def __init__(self, name, sparkly, cuddly):
        self.name = name
        self.sparkly = sparkly
        self.cuddly = cuddly

    @classmethod
    def __from_json__(cls, data):
        return cls(**data)


@argify(pet=Unicorn)
def set_user_pet(request, username, pet):
    # Set user pet

The __from_json__ method can be a classmethod or a staticmethod, and the signature must be either (arg) or (request, arg).

Note

I’m using @argify, but this also works with request.param().

You can also pass in a factory function as the type:

class Unicorn(object):
    def __init__(self, name, sparkly, cuddly):
        self.name = name
        self.sparkly = sparkly
        self.cuddly = cuddly

def make_unicorn(data):
    return Unicorn(**data)

@argify(pet=make_unicorn)
def set_user_pet(request, username, pet):
    # Set user pet

If you’re running into import dependency hell, you can use a dotted path for the type:

@argify(pet='mypkg.models.make_unicorn')
def set_user_pet(request, username, pet):
    # Set user pet

Multi-Parameter Types

You can define custom types that will consume multiple request parameters. Let’s look at a new set of POST parameters;

{
    name: "Sparklelord",
    secret: "Radical",
}

Let’s say you want to pass up these parameters as login credentials. You would like to fetch the named Unicorn from the database and use that in your view. What would you call that argument? unicorn would make sense, but there aren’t any parameters named unicorn, so how would you inject a parameter that is generated from multiple request parameters? All you need to do is take your type factory function and decorate it with @argify as well.

@argify
def fetch_unicorn(request, name, secret):
    return request.db.query_for_unicorn(name, secret)

@argify(unicorn=fetch_unicorn)
def make_rainbows(request, unicorn):
    # Make some fukkin' rainbows

You’ll notice here that we’re injecting a field named unicorn, which doesn’t exist in the POST parameters. You can decorate factory methods or the __from_json__ magic method on type classes.

This particular functionality is kind of magic, and as such I would not recommend using it frequently because it obfuscates your code. This was really made with one thing in mind: user authentication. This is a great way to both authenticate a user and inject the User model into your view with minimal code duplication.