Skip to content

Instantly share code, notes, and snippets.

@gamesbrainiac
Last active August 29, 2015 14:06
Show Gist options
  • Select an option

  • Save gamesbrainiac/b1074eb5d2e5ec35af4b to your computer and use it in GitHub Desktop.

Select an option

Save gamesbrainiac/b1074eb5d2e5ec35af4b to your computer and use it in GitHub Desktop.
Questions about Morepath

I've been trying to understand how morepath works with the quickstart guide in the documentation.I have a couple of questions regarding the design, and my understanding of what's happening.

So, a model is a resources, pretty much a representation of an object stored in a databse. Atleast, this is how I understand it, if this is so, why can't we have a path assigned to it, inside the classbody itself. So, right now:

# We declare the object
class User(object):
    def __init__(self, username, fullname, email):
        self.username = username
        self.fullname = fullname
        self.email = email
        
# We then assing a path that is handled here
@App.path(model=User, path='/user/{username}')
def get_user(username):
    return users.get(username)

The question that arises here is this, if all we are doing is using the App.path decorator as a means of registering a path, and then assigning a filter, in this case get_user, why not just let a view function handle all the url understanding, and then the eventual rendering? Also, since you're naming a function here, with the App.path decorator, can you assign multiple masks or filters before the view is finally rendered?

@faassen
Copy link

faassen commented Sep 8, 2014

I think what you're asking is basically: why is Morepath not like Flask or almost any other routing framework.

Why not simply have a view function associated with a path instead like these others do?

Routing directly to a view definitely has a benefit of simplicity, but you lose a bunch of nice features.
Morepath gets several benefits of separating these concerns; I tried to document them in the superpowers document and various other places, but I'll try to summarize here:

  • by doing this you separate the database query functionality from the representation functionality. This can make code easier to understand, separating concerns.
  • get_user can return None if it can't find the user, and the web framework can do an automatic 404 for you.
  • the web framework knows about what path works for a model, so you can generate a link to it using request.link(). If you associated the route with the view you wouldn't have the information to do that.
  • this decoupling makes other reuse patterns possible. For instance, you could have a base class for User that you associated some views with in more frameworky parts of your code, and those views would work automatically for that path too. Or you can use request.render() to get the rendered view of a model programmatically.

I'm not entirely sure what you mean by your masks or filters question. What do you mean by masks in particular if this is different from filters? I think it might have something to do with collections and doing a query on them. What you'd typically do is come up with a Collection class in your application that takes whatever things you want to filter with and implements a method called "query" (or whatever) that when executed does the actual query. Then you expose this Collection to a URL, along these lines:

class UserCollection(object):
     def __init__(self, part_of_name, offset, limit):
          self.part_of_name = part_of_name
          self.offset = offset
          self.limit = limit

    def query(self):
          # do database query using offset, limit, part of name, returning users that match

@App.path(model=UserCollection, path='/users')
def get_users(part_of_name, offset, limit):
    return UserCollection(part_of_name, offset, limit)

@App.view(model=UserCollection)
def default_user_collection(self, request):
    return [request.render(user) for user in self.query()]

@gamesbrainiac
Copy link
Author

Firstly, I'd like to apologize for this late response. I had a lot of work that was piled up, and I needed to address a whole range of issues.

by doing this you separate the database query functionality from the representation functionality. This can make code easier to understand, separating concerns.

Ahh, that's what I thought but I had not quite thought through as to why you might want to do this, but I guess you want to further decouple things. I can also see that with additional decorators you can add filters on top of the data gained from the database giving you more control.

Although I still have not gone through request.link() examples, I will do so shortly.

Thank you for answering my questions, and I hope you accept my humble apologies for this late reply.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment