Class providing the core functionality.
m = Resource(config)
pa = m.add('parent', 'parents')
pa.add('child', 'children')
Parameters: |
|
---|---|
Returns: | ResourceMap object |
Returns the list of ancestor resources.
view is a dotted name of (or direct reference to) a Python view class, e.g. 'my.package.views.MyView'.
member_name should be the appropriate singular version of the resource given your locale and used with members of the collection.
collection_name will be used to refer to the resource collection methods and should be a plural version of the member_name argument.
All keyword arguments are optional.
Perpends the route names that are generated with the name_prefix given. Combined with the path_prefix option, it’s easy to generate route names and paths that represent resources that are in relations.
Example:
config.add_resource('myproject.views:CategoryView', 'message', 'messages',
path_prefix='/category/:category_id',
name_prefix="category_")
# GET /category/7/messages/1
# has named route "category_message"
Last two are derived from BaseView.
Base class for yarhp views. This class holds some common objects used by the derived SQLAView and DynamoDBView classes. Those are:
_default_actions
__model_class__
__validation_schema__
_default_actions are those for which the derived view can omit the implementation for and it will be handled by the parent class.
class MyView(SQLAView): def index(self): ...
In this example we have MyView derived from SQLAView and it defines only the index action. The rest of the actions will by default handled by SQLAView. In case the particular view does not need a certain action, it should declare it so when adding the resource:
root.add('user', 'users', include=['index'])
Here the resource user defines only the index action.
__model_class__ is a class object or dotted path to it which is associated with this view. By default yarhp expects the model to be defined in your_project.model.<resource_member_name>.<Resource>View.py
There are two ways to override this default:
root.add('user', 'users', model='path.to.my.model.ClassView') root.add('whatever',model='yarhp.NoModel') #redefine it to NoModel
or
class MyView(BaseView): __model_class__ = ResourceView
{field_name1:
{'type':<python type>,
'required':<bool>},
field_name2:{...}
...}
This is bare minimum that is checked by validators to make sure that request.params correspond to the model’s requirements.
If you want to supply custom validation schema, you should override the validate_schema method of your view, which must return the dict in the format above.
default_index, default_create, etc must be defined in the child class. See SQLAView or DynamoDBView for examples. also _default_actions is by default empty. It must be defined by the derived view class.
Iterates over actions and appends decorated wrappers for before and after calls to the corresponding before or after dict
Add all the default before and after calls. before calls are validate_types and validate_required which are called with the validation schema returned by validation_schema method. This allows any subclass to change validation schema.
pager : paginates the results, if the result is a sequence. obj2dict: if result is an python object, it calls to_dict on it.
if its a list of objects, it enumerates and calls to_dict on each element.
wrap_in_dict: if action result is a list, it wraps it into a dict. add_pagination_links: if the result was paginated, it appends pagination links
No-op model class to use when defining a resource who doesnt have a model
Use this view for the routes that raise HTTPMethodNotAllowed for any action
Yarhp view used to serve SQLAlchemy objects. ``SQLAView implements the following logic:
default behaviour for all actions validation agaisnt the sqla model’s schema
default for create action. Raises HTTPConflict if there is an integrity error in DB. Returns HTTPCreated on success.
default for delete action. Raises HTTPNotFound if the row is not found. Returns HTTPOk on success.
default for index action. Returns sqla query object which is passed to the pager to paginate the results.
default for show action. Raises HTTPNotFound if the row is not found. Returns the resouce as python dict.
Returns a validation schema for the model the schema is a dict of dicts in the form of:
{field_name1:{ 'type':<python type>, 'required':<bool>, 'length':<int>} field_name2:{ ... } ...}
Simple REST view used to serve dymamodb-mapper objects at the top level.
For hash_key-indexed classes, subclass this and fill in the __model_class__ attribute with the class you want to serve. That’s it! The default __model_class__ value is “your_project.model.resource_name.ResourceName”
Example usage:
class UserView(DynamoDBView):
#__model_class__ = 'your_project.model.user.User'
pass
Yarhp specific json renderer which will apply all after_calls(filters) to the result.
Add links to the result dict to the resouce itself.
Base class for all before and after calls. __eq__ method is overloaded in order to prevent duplicate callables of the same type. For example, you could have a before call pager which is called in the base class and also decorate the action with paginate. __eq__ declares all same type callables to be the same.
Decorator which adds a wrapper to check the ancestors.
kwargs are passed down to webhelpers.paginate.Page
some of the usefull kw args with defaults are: - items_per_page=20: how many items per page - item_count=None: total count if known, otherwise DB will be queried. - presliced_list=False: if collection was alredy sliced fitting into a page
For more see http://sluggo.scrapping.cc/python/WebHelpers/modules/paginate.html
Decorator used to paginate the results. Its an after-call
if result has “links”, update it with new_links if result has “link”, change it to “links” and add values from new_links if not empty if result has neither, create “link” or “links” depending len(new_links)
Validates that all ancestor resources of the given resource exist
Validates that fields in request.params are present according to kwargs argument passed to ``__call__. Raises ValidationError in case of the mismatch
Validates the field types in request.params match the types declared in kwargs. Raises ValidationError if there is mismatch.
Validators are implemented as wrappers that are before-calls. Essentially they ‘wrap’ your action (or any method really) and are called before the action is called.
There are two ways how validators can be involved:
- Decorator
- Subclassing from one of yarhp’s base view classes
- The Chuck Norris way
@validator(name={'type': str, 'required': True}, age={'type': int, 'required': True}, birthdate={'type': date, 'required': False}) def create(self): pass
Keyword arguments passed to the validator are the validation schema that is used to check request.params validity.
Yarhp provides 2 base classes one could derive from to have automated validation in the views. SQLAView and DynamoDBView. The essential difference between those two is what kind of information about the underlaying schema yarhp is able to collect. In case of SQL for example it gets the type, required and also length of the field.
class MyView(SQLAView): def create(self): pass
In the example above the create action is automatically gets validated by yarhp: the type and the required field. So you dont have to do anything. The way it does this magic is pulling the metadata (schema) from SQLA and comparing with request.params. If you wish to override any default behavior, you could do:
class MyView(SQLAView): @validator(name={'type':str, required=False}) def create(self): ...
Here we change the required to False, thus overriding the metadata coming from the DB schema where name was required. This is obviously not recommended and should be done with care, understanding the side effects. In this case it might raise DB error since name could be NULL, but DB requires it.
Now what if you write a common validator and you want to apply it to all of your actions? One way is to decorate them all. But another is “Chuck Norris way” !
Stay tuned for more..
defines a new resource, its named routes:
config.add_resource("user", "users")
view to find : UsersView
URL | route name | HTTP verb | action name |
---|---|---|---|
/users | users | GET | index |
/users | users | POST | create |
/users/:id | user | GET | show |
/users/:id | user | PUT | update |
/users/:id | user | DELETE | delete |
/users/:id/edit | edit_user | GET | edit |
/users/new | new_user | GET | new |
These last two are non-standard CRUD actions.
config.add_resource("transaction", "transactions", parent="user")
view to find: UserTransactionsView model: user_transaction.UserTransaction
URL | route name | HTTP verb | action name |
---|---|---|---|
/users/:user_id/transactions | user_transactions | GET | index |
/users/:user_id/transactions | user_transactions | POST | create |
/users/:user_id/transactions/:id | user_transaction | GET | show |
/users/:user_id/transactions/:id | user_transaction | PUT | update |
/users/:user_id/transactions/:id | user_transaction | DELETE | delete |
/users/1/transactions/edit | user_edit_transaction | GET | edit |
/users/1/transactions/new | user_new_transaction | GET | new |
These last two are non-standard CRUD actions.
singular resource:
config.add_resource('detail', parent='transaction')
view to find: UserTransactionDetailView
URL | route name | HTTP verb | action |
---|---|---|---|
/users/:user_id/transactions/:transaction_id/detail | user_transaction_detail | GET | show |
/users/:user_id/transactions/:transaction_id/detail | user_transaction_detail | POST | create |
/users/:user_id/transactions/:transaction_id/detail | user_transaction_detail | PUT | update |
/users/:user_id/transactions/:transaction_id/detail | user_transaction_detail | DELETE | delete |
/users/:user_id/transactions/:transaction_id/detail/edit | user_transaction_edit_detail | GET | edit |
/users/:user_id/transactions/:transaction_id/detail/new | user_transaction_new_detail | GET | new |