Warning

Starting from CubicWeb version 4.0 all code related to generating html views has been moved to the Cube cubicweb_web.

If you want to migrate a project from 3.38 to 4.* while still using all the html views you need to both install the cubicweb_web cube AND add it to your dependencies and run add_cube('web').

cubicweb_web can be installed from pypi this way:

pip install cubicweb_web

We don’t plan to maintain the features in cubicweb_web in the long run; we are moving to a full javascript frontend using both cubicweb_api (which exposes a HTTP API) and @cubicweb/client as a frontend javascript toolkit.

In the long run cubicweb_api will be merged inside of CubicWeb.

URL publishing#

(cubicweb.web.views.urlpublishing)

You can write your own URLPathEvaluator class to handle custom paths. For instance, if you want /my-card-id to redirect to the corresponding card’s primary view, you would write:

class CardWikiidEvaluator(URLPathEvaluator):
    priority = 3 # make it be evaluated *before* RestPathEvaluator

    def evaluate_path(self, req, segments):
        if len(segments) != 1:
            raise PathDontMatch()
        rset = req.execute('Any C WHERE C wikiid %(w)s',
                           {'w': segments[0]})
        if len(rset) == 0:
            # Raise NotFound if no card is found
            raise PathDontMatch()
        return None, rset

On the other hand, you can also deactivate some of the standard evaluators in your final application. The only thing you have to do is to unregister them, for instance in a registration_callback in your cube:

def registration_callback(vreg):
    vreg.unregister(RestPathEvaluator)

You can even replace the cubicweb.web.views.urlpublishing.URLPublisherComponent class if you want to customize the whole toolchain process or if you want to plug into an early enough extension point to control your request parameters:

class SanitizerPublisherComponent(URLPublisherComponent):
    """override default publisher component to explicitly ignore
    unauthorized request parameters in anonymous mode.
    """
    unauthorized_form_params = ('rql', 'vid', '__login', '__password')

    def process(self, req, path):
        if req.session.anonymous_session:
            self._remove_unauthorized_params(req)
        return super(SanitizerPublisherComponent, self).process(req, path)

    def _remove_unauthorized_params(self, req):
        for param in req.form.keys():
            if param in self.unauthorized_form_params:
                 req.form.pop(param)


def registration_callback(vreg):
    vreg.register_and_replace(SanitizerPublisherComponent, URLPublisherComponent)

URL rewriting#

(cubicweb.web.views.urlrewrite)

SimpleReqRewriter is enough for a certain number of simple cases. If it is not sufficient, SchemaBasedRewriter allows to do more elaborate things.

Here is an example of SimpleReqRewriter usage with plain string:

from cubicweb.web.views.urlrewrite import SimpleReqRewriter
class TrackerSimpleReqRewriter(SimpleReqRewriter):
    rules = [
     ('/versions', dict(vid='versionsinfo')),
     ]

When the url is <base_url>/versions, the view with the __regid__ versionsinfo is displayed.

Here is an example of SimpleReqRewriter usage with regular expressions:

from cubicweb.web.views.urlrewrite import (
    SimpleReqRewriter, rgx)

class BlogReqRewriter(SimpleReqRewriter):
    rules = [
        (rgx('/blogentry/([a-z_]+)\.rss'),
         dict(rql=('Any X ORDERBY CD DESC LIMIT 20 WHERE X is BlogEntry,'
                   'X creation_date CD, X created_by U, '
                   'U login "%(user)s"'
                   % {'user': r'\1'}), vid='rss'))
        ]

When a url matches the regular expression, the view with the __regid__ rss which match the result set is displayed.

To deal with URL rewriting with an underlying RQL query, it is possible to specify the behaviour in the case of an empty rset with the option empty_rset_raises_404.

The following example shows a SimpleReqRewriter usage with the empty_rset_raises_404 option set to True. In this case, the path mycwetypeurl/pouet will return a 404. Without this option, it would return a 200.

from cubicweb.web.views.urlrewrite import (
    SimpleReqRewriter, rgx)

class MyRewriter(SimpleReqRewriter):
    rules = [(rgx(r'/mycwetypeurl/([^/]+)'),
                                dict(vid='primary',
                                     rql=r'Any T WHERE T is CWEType, T name "\1"',
                                     empty_rset_raises_404=True),)]

Here is an example of SchemaBasedRewriter usage:

from cubicweb.web.views.urlrewrite import (
    SchemaBasedRewriter, rgx, build_rset)

class TrackerURLRewriter(SchemaBasedRewriter):
    rules = [
        (rgx('/project/([^/]+)/([^/]+)/tests'),
         build_rset(rql='Version X WHERE X version_of P, P name %(project)s, X num %(num)s',
                    rgxgroups=[('project', 1), ('num', 2)], vid='versiontests')),
        ]